The telephony feed was causing 'Collecting package info' failures during make defconfig. This fix removes the telephony feed directory and references from feeds.conf.default before running defconfig in all workflows. Fixes applied to: - build-openwrt-packages.yml - build-secubox-images.yml - test-validate.yml
386 lines
12 KiB
YAML
386 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
|
|
./scripts/feeds update -a
|
|
./scripts/feeds install -a
|
|
|
|
# Clean up telephony feed to avoid indexing errors
|
|
rm -f feeds/telephony.index 2>/dev/null || true
|
|
rm -rf feeds/telephony 2>/dev/null || true
|
|
if [[ -f "feeds.conf.default" ]]; then
|
|
sed -i '/telephony/d' feeds.conf.default
|
|
fi
|
|
|
|
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
|
|
|
|
# Clean up telephony feed before defconfig
|
|
rm -f feeds/telephony.index 2>/dev/null || true
|
|
rm -rf feeds/telephony 2>/dev/null || true
|
|
if [[ -f "feeds.conf.default" ]]; then
|
|
sed -i '/telephony/d' feeds.conf.default
|
|
fi
|
|
|
|
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
|