Moved telephony removal to occur BEFORE './scripts/feeds update' to prevent the telephony feed from ever being cloned or indexed. The previous fix tried to remove telephony after feeds were already updated, which was too late. Key changes: - Remove telephony from feeds.conf.default BEFORE feed updates - Keep final cleanup before make defconfig as safety measure - Applies to all three workflows This should completely eliminate the 'Collecting package info: feeds/telephony' error during make defconfig.
387 lines
12 KiB
YAML
387 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 telephony from feeds.conf.default BEFORE updating feeds
|
|
if [[ -f "feeds.conf.default" ]]; then
|
|
sed -i '/telephony/d' feeds.conf.default
|
|
echo "✅ Removed telephony from feeds.conf.default"
|
|
fi
|
|
|
|
./scripts/feeds update -a
|
|
./scripts/feeds install -a
|
|
|
|
# Final cleanup of telephony feed
|
|
rm -f feeds/telephony.index 2>/dev/null || true
|
|
rm -rf feeds/telephony 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 2>/dev/null || true
|
|
rm -rf feeds/telephony 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
|