328 lines
9.8 KiB
YAML
328 lines
9.8 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 */Makefile; do
|
|
if [[ -f "$makefile" ]]; then
|
|
PKG=$(dirname "$makefile")
|
|
echo " 🔍 Checking $PKG..."
|
|
|
|
# Required fields
|
|
REQUIRED_FIELDS=(
|
|
"PKG_NAME"
|
|
"PKG_VERSION"
|
|
"PKG_RELEASE"
|
|
"PKG_LICENSE"
|
|
"LUCI_TITLE"
|
|
)
|
|
|
|
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
|
|
|
|
# Find all JSON files
|
|
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..."
|
|
|
|
# Install node for syntax check
|
|
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)
|
|
|
|
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..."
|
|
|
|
ERRORS=0
|
|
|
|
# Check RPCD scripts
|
|
while IFS= read -r script; do
|
|
echo " 🔍 Checking $script..."
|
|
if ! shellcheck -s sh "$script"; then
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
done < <(find . -path "*/rpcd/*" -type f -executable)
|
|
|
|
# Check init scripts
|
|
while IFS= read -r script; do
|
|
echo " 🔍 Checking $script..."
|
|
if ! shellcheck -s sh "$script"; then
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
done < <(find . -path "*/init.d/*" -type f)
|
|
|
|
if [[ $ERRORS -gt 0 ]]; then
|
|
echo "⚠️ Found $ERRORS 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"
|
|
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"
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
done < <(find . -path "*/etc/init.d/*" -type f 2>/dev/null)
|
|
|
|
if [[ $ERRORS -gt 0 ]]; then
|
|
echo "❌ Found $ERRORS permission errors"
|
|
exit 1
|
|
fi
|
|
echo "✅ File permissions correct"
|
|
|
|
- name: Validate package structure
|
|
run: |
|
|
echo "📋 Validating package structure..."
|
|
|
|
for pkg in luci-app-*/; do
|
|
if [[ -d "$pkg" ]]; then
|
|
echo " 📦 Checking $pkg..."
|
|
|
|
# Required directories/files
|
|
REQUIRED=(
|
|
"Makefile"
|
|
)
|
|
|
|
# Optional but recommended
|
|
RECOMMENDED=(
|
|
"htdocs/luci-static/resources"
|
|
"root/usr/share/luci/menu.d"
|
|
"root/usr/share/rpcd/acl.d"
|
|
)
|
|
|
|
for req in "${REQUIRED[@]}"; do
|
|
if [[ ! -e "${pkg}${req}" ]]; then
|
|
echo " ❌ Missing required: $req"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
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-distutils 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
|
|
|
|
- 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
|
|
make defconfig
|
|
|
|
- name: Copy packages
|
|
run: |
|
|
mkdir -p ~/sdk/package/secubox
|
|
|
|
for pkg in luci-app-*/; do
|
|
if [[ -d "$pkg" ]]; then
|
|
cp -r "$pkg" ~/sdk/package/secubox/
|
|
fi
|
|
done
|
|
|
|
- name: Build test
|
|
run: |
|
|
cd ~/sdk
|
|
|
|
# Enable packages
|
|
for pkg in ~/sdk/package/secubox/*/; do
|
|
PKG_NAME=$(basename "$pkg")
|
|
echo "CONFIG_PACKAGE_${PKG_NAME}=m" >> .config
|
|
done
|
|
|
|
make defconfig
|
|
|
|
# Build with timeout
|
|
timeout 30m make package/secubox/compile V=s -j$(nproc) || {
|
|
echo "⚠️ Build timeout or error"
|
|
exit 1
|
|
}
|
|
|
|
- name: Verify output
|
|
run: |
|
|
echo "📋 Built packages:"
|
|
find ~/sdk/bin -name "*.ipk" -exec ls -la {} \;
|
|
|
|
PKG_COUNT=$(find ~/sdk/bin -name "*.ipk" | wc -l)
|
|
echo "📦 Total packages built: $PKG_COUNT"
|
|
|
|
if [[ $PKG_COUNT -eq 0 ]]; then
|
|
echo "❌ No packages were built!"
|
|
exit 1
|
|
fi
|
|
|
|
# ============================================
|
|
# 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 "| 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-)
|
|
|
|
echo "| $PKG_NAME | $PKG_VERSION | $PKG_TITLE |" >> PACKAGES.md
|
|
fi
|
|
done
|
|
|
|
echo "" >> PACKAGES.md
|
|
echo "Generated: $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> PACKAGES.md
|
|
|
|
cat PACKAGES.md
|
|
|
|
- name: Upload docs
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: documentation
|
|
path: PACKAGES.md
|