Extended the feed removal to also exclude the routing feed, which was causing the same indexing error during make defconfig. Now removing both telephony and routing feeds from feeds.conf.default before updating feeds in all three workflows. This ensures only base, packages, and luci feeds are used.
388 lines
12 KiB
YAML
388 lines
12 KiB
YAML
name: Test & Validate Packages
|
|
|
|
on:
|
|
push:
|
|
branches: [main, master, develop]
|
|
pull_request:
|
|
branches: [main, master]
|
|
|
|
jobs:
|
|
# ============================================
|
|
# Lint and validate package structure
|
|
# ============================================
|
|
lint:
|
|
runs-on: ubuntu-latest
|
|
name: Lint & Validate
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Install validators
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y shellcheck jq
|
|
|
|
- name: Validate Makefile structure
|
|
run: |
|
|
echo "📋 Validating Makefile structure..."
|
|
|
|
ERRORS=0
|
|
|
|
for makefile in luci-app-*/Makefile; do
|
|
if [[ -f "$makefile" ]]; then
|
|
PKG=$(dirname "$makefile")
|
|
echo " 🔍 Checking $PKG..."
|
|
|
|
# Required fields
|
|
REQUIRED_FIELDS=(
|
|
"PKG_NAME"
|
|
"PKG_VERSION"
|
|
"PKG_RELEASE"
|
|
"PKG_LICENSE"
|
|
)
|
|
|
|
for field in "${REQUIRED_FIELDS[@]}"; do
|
|
if ! grep -q "^${field}:=" "$makefile"; then
|
|
echo " ❌ Missing: $field"
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
done
|
|
|
|
# Check for include statements
|
|
if ! grep -q "include.*luci.mk\|include.*package.mk" "$makefile"; then
|
|
echo " ❌ Missing include statement (luci.mk or package.mk)"
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
fi
|
|
done
|
|
|
|
if [[ $ERRORS -gt 0 ]]; then
|
|
echo "❌ Found $ERRORS errors"
|
|
exit 1
|
|
fi
|
|
echo "✅ All Makefiles valid"
|
|
|
|
- name: Validate JSON files
|
|
run: |
|
|
echo "📋 Validating JSON files..."
|
|
|
|
ERRORS=0
|
|
|
|
while IFS= read -r jsonfile; do
|
|
echo " 🔍 Checking $jsonfile..."
|
|
if ! jq empty "$jsonfile" 2>/dev/null; then
|
|
echo " ❌ Invalid JSON"
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
done < <(find . -name "*.json" -type f)
|
|
|
|
if [[ $ERRORS -gt 0 ]]; then
|
|
echo "❌ Found $ERRORS JSON errors"
|
|
exit 1
|
|
fi
|
|
echo "✅ All JSON files valid"
|
|
|
|
- name: Validate JavaScript syntax
|
|
run: |
|
|
echo "📋 Validating JavaScript files..."
|
|
|
|
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
|
|
sudo apt-get install -y nodejs
|
|
|
|
ERRORS=0
|
|
|
|
while IFS= read -r jsfile; do
|
|
echo " 🔍 Checking $jsfile..."
|
|
if ! node --check "$jsfile" 2>/dev/null; then
|
|
echo " ❌ Syntax error"
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
done < <(find . -name "*.js" -type f ! -path "*/node_modules/*")
|
|
|
|
if [[ $ERRORS -gt 0 ]]; then
|
|
echo "❌ Found $ERRORS JavaScript errors"
|
|
exit 1
|
|
fi
|
|
echo "✅ All JavaScript files valid"
|
|
|
|
- name: Validate shell scripts
|
|
run: |
|
|
echo "📋 Validating shell scripts..."
|
|
|
|
WARNINGS=0
|
|
|
|
# Check RPCD scripts
|
|
while IFS= read -r script; do
|
|
echo " 🔍 Checking $script..."
|
|
shellcheck -s sh "$script" || WARNINGS=$((WARNINGS + 1))
|
|
done < <(find . -path "*/rpcd/*" -type f 2>/dev/null)
|
|
|
|
# Check init scripts
|
|
while IFS= read -r script; do
|
|
echo " 🔍 Checking $script..."
|
|
shellcheck -s sh "$script" || WARNINGS=$((WARNINGS + 1))
|
|
done < <(find . -path "*/init.d/*" -type f 2>/dev/null)
|
|
|
|
if [[ $WARNINGS -gt 0 ]]; then
|
|
echo "⚠️ Found $WARNINGS shellcheck warnings (non-blocking)"
|
|
fi
|
|
echo "✅ Shell script validation complete"
|
|
|
|
- name: Check file permissions
|
|
run: |
|
|
echo "📋 Checking file permissions..."
|
|
|
|
ERRORS=0
|
|
|
|
# RPCD scripts should be executable
|
|
while IFS= read -r script; do
|
|
if [[ ! -x "$script" ]]; then
|
|
echo " ❌ Not executable: $script"
|
|
chmod +x "$script"
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
done < <(find . -path "*/usr/libexec/rpcd/*" -type f 2>/dev/null)
|
|
|
|
# Init scripts should be executable
|
|
while IFS= read -r script; do
|
|
if [[ ! -x "$script" ]]; then
|
|
echo " ❌ Not executable: $script"
|
|
chmod +x "$script"
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
done < <(find . -path "*/etc/init.d/*" -type f 2>/dev/null)
|
|
|
|
if [[ $ERRORS -gt 0 ]]; then
|
|
echo "⚠️ Fixed $ERRORS permission issues"
|
|
fi
|
|
echo "✅ File permissions checked"
|
|
|
|
- name: Validate package structure
|
|
run: |
|
|
echo "📋 Validating package structure..."
|
|
|
|
for pkg in luci-app-*/; do
|
|
if [[ -d "$pkg" ]]; then
|
|
echo " 📦 Checking $pkg..."
|
|
|
|
# Required
|
|
if [[ ! -f "${pkg}Makefile" ]]; then
|
|
echo " ❌ Missing required: Makefile"
|
|
exit 1
|
|
fi
|
|
|
|
# Recommended
|
|
RECOMMENDED=(
|
|
"htdocs/luci-static/resources"
|
|
"root/usr/share/luci/menu.d"
|
|
"root/usr/share/rpcd/acl.d"
|
|
)
|
|
|
|
for rec in "${RECOMMENDED[@]}"; do
|
|
if [[ ! -e "${pkg}${rec}" ]]; then
|
|
echo " ⚠️ Missing recommended: $rec"
|
|
fi
|
|
done
|
|
fi
|
|
done
|
|
|
|
echo "✅ Package structure valid"
|
|
|
|
# ============================================
|
|
# Quick build test on x86_64
|
|
# ============================================
|
|
test-build:
|
|
runs-on: ubuntu-latest
|
|
name: Test Build (x86_64)
|
|
needs: lint
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y \
|
|
build-essential clang flex bison g++ gawk \
|
|
gcc-multilib g++-multilib gettext git libncurses5-dev \
|
|
libssl-dev python3-setuptools python3-dev rsync unzip zlib1g-dev wget
|
|
|
|
- name: Cache OpenWrt SDK
|
|
uses: actions/cache@v4
|
|
id: cache-sdk
|
|
with:
|
|
path: ~/sdk
|
|
key: openwrt-sdk-23.05.5-x86-64-test-v2
|
|
|
|
- name: Download OpenWrt SDK
|
|
if: steps.cache-sdk.outputs.cache-hit != 'true'
|
|
run: |
|
|
SDK_URL="https://downloads.openwrt.org/releases/23.05.5/targets/x86/64"
|
|
SDK_FILE=$(curl -sL "$SDK_URL/" | grep -oP 'openwrt-sdk[^"]+\.tar\.xz' | head -1)
|
|
|
|
wget -q "${SDK_URL}/${SDK_FILE}" -O /tmp/sdk.tar.xz
|
|
mkdir -p ~/sdk
|
|
tar -xf /tmp/sdk.tar.xz -C ~/sdk --strip-components=1
|
|
|
|
- name: Prepare SDK
|
|
run: |
|
|
cd ~/sdk
|
|
|
|
# Remove unwanted feeds from feeds.conf.default BEFORE updating feeds
|
|
if [[ -f "feeds.conf.default" ]]; then
|
|
sed -i '/telephony/d' feeds.conf.default
|
|
sed -i '/routing/d' feeds.conf.default
|
|
echo "✅ Removed telephony and routing from feeds.conf.default"
|
|
fi
|
|
|
|
./scripts/feeds update -a
|
|
./scripts/feeds install -a
|
|
|
|
# Final cleanup of unwanted feeds
|
|
rm -f feeds/telephony.index feeds/routing.index 2>/dev/null || true
|
|
rm -rf feeds/telephony feeds/routing 2>/dev/null || true
|
|
|
|
make defconfig
|
|
|
|
- name: Copy packages
|
|
run: |
|
|
# IMPORTANT: Copy packages DIRECTLY into package/, not into a subdirectory
|
|
for pkg in luci-app-*/; do
|
|
if [[ -d "$pkg" && -f "${pkg}Makefile" ]]; then
|
|
PKG_NAME=$(basename "$pkg")
|
|
echo "📦 Copying $PKG_NAME..."
|
|
cp -r "$pkg" ~/sdk/package/
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo "📋 Packages in SDK:"
|
|
ls -d ~/sdk/package/luci-app-*/ 2>/dev/null || echo "No packages found"
|
|
|
|
- name: Configure packages
|
|
run: |
|
|
cd ~/sdk
|
|
|
|
# Enable packages
|
|
for pkg in ~/sdk/package/luci-app-*/; do
|
|
if [[ -d "$pkg" ]]; then
|
|
PKG_NAME=$(basename "$pkg")
|
|
echo "CONFIG_PACKAGE_${PKG_NAME}=m" >> .config
|
|
echo "✅ Enabled: $PKG_NAME"
|
|
fi
|
|
done
|
|
|
|
# Final cleanup before defconfig
|
|
rm -f feeds/telephony.index feeds/routing.index 2>/dev/null || true
|
|
rm -rf feeds/telephony feeds/routing 2>/dev/null || true
|
|
|
|
make defconfig
|
|
|
|
- name: Build packages
|
|
run: |
|
|
cd ~/sdk
|
|
|
|
echo "🔨 Building packages..."
|
|
|
|
BUILT=0
|
|
FAILED=0
|
|
|
|
# Build each package individually with timeout
|
|
for pkg in ~/sdk/package/luci-app-*/; do
|
|
if [[ -d "$pkg" ]]; then
|
|
PKG_NAME=$(basename "$pkg")
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "📦 Building: $PKG_NAME"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
|
|
# Build with 5 minute timeout per package
|
|
if timeout 5m make package/${PKG_NAME}/compile V=s -j$(nproc) 2>&1; then
|
|
echo "✅ Built: $PKG_NAME"
|
|
BUILT=$((BUILT + 1))
|
|
else
|
|
echo "❌ Failed: $PKG_NAME"
|
|
FAILED=$((FAILED + 1))
|
|
fi
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "📊 Build Summary"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "Built: $BUILT packages"
|
|
echo "Failed: $FAILED packages"
|
|
|
|
if [[ $BUILT -eq 0 ]]; then
|
|
echo "❌ No packages were built!"
|
|
exit 1
|
|
fi
|
|
|
|
- name: Verify output
|
|
run: |
|
|
echo "📋 Built packages:"
|
|
find ~/sdk/bin -name "luci-app-*.ipk" -exec ls -la {} \;
|
|
|
|
PKG_COUNT=$(find ~/sdk/bin -name "luci-app-*.ipk" | wc -l)
|
|
echo ""
|
|
echo "📦 Total packages built: $PKG_COUNT"
|
|
|
|
if [[ $PKG_COUNT -eq 0 ]]; then
|
|
echo "❌ No packages were built!"
|
|
exit 1
|
|
fi
|
|
|
|
echo "✅ Build test passed"
|
|
|
|
# ============================================
|
|
# Generate documentation
|
|
# ============================================
|
|
docs:
|
|
runs-on: ubuntu-latest
|
|
name: Generate Docs
|
|
needs: lint
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Generate package list
|
|
run: |
|
|
echo "# SecuBox Packages" > PACKAGES.md
|
|
echo "" >> PACKAGES.md
|
|
echo "Auto-generated package documentation." >> PACKAGES.md
|
|
echo "" >> PACKAGES.md
|
|
echo "| Package | Version | Description |" >> PACKAGES.md
|
|
echo "|---------|---------|-------------|" >> PACKAGES.md
|
|
|
|
for makefile in luci-app-*/Makefile; do
|
|
if [[ -f "$makefile" ]]; then
|
|
PKG_NAME=$(grep "^PKG_NAME:=" "$makefile" | cut -d'=' -f2)
|
|
PKG_VERSION=$(grep "^PKG_VERSION:=" "$makefile" | cut -d'=' -f2)
|
|
PKG_TITLE=$(grep "^LUCI_TITLE:=" "$makefile" | cut -d'=' -f2- | sed 's/^[[:space:]]*//')
|
|
|
|
# Fallback if LUCI_TITLE not found
|
|
if [[ -z "$PKG_TITLE" ]]; then
|
|
PKG_TITLE=$(grep "TITLE:=" "$makefile" | head -1 | cut -d'=' -f2- | sed 's/^[[:space:]]*//')
|
|
fi
|
|
|
|
echo "| $PKG_NAME | $PKG_VERSION | $PKG_TITLE |" >> PACKAGES.md
|
|
fi
|
|
done
|
|
|
|
echo "" >> PACKAGES.md
|
|
echo "---" >> PACKAGES.md
|
|
echo "Generated: $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> PACKAGES.md
|
|
|
|
echo "📋 Generated PACKAGES.md:"
|
|
cat PACKAGES.md
|
|
|
|
- name: Upload docs
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: documentation
|
|
path: PACKAGES.md
|