secubox-openwrt/.github/workflows/build-openwrt-packages.yml

562 lines
20 KiB
YAML

name: Build OpenWrt Packages
on:
push:
branches: [main, master, develop]
tags:
- 'v*'
pull_request:
branches: [main, master]
workflow_dispatch:
inputs:
openwrt_version:
description: 'OpenWrt version'
required: true
default: '23.05.5'
type: choice
options:
- '23.05.5'
- '23.05.4'
- '22.03.7'
- 'SNAPSHOT'
architectures:
description: 'Architectures to build (comma-separated or "all")'
required: false
default: 'aarch64-cortex-a72'
env:
OPENWRT_VERSION: ${{ github.event.inputs.openwrt_version || '23.05.5' }}
jobs:
# ============================================
# Determine build matrix
# ============================================
setup:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
version: ${{ steps.version.outputs.version }}
packages: ${{ steps.packages.outputs.list }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine version
id: version
run: |
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
VERSION="${{ github.ref_name }}"
else
VERSION="0.0.0-$(git rev-parse --short HEAD)"
fi
echo "version=${VERSION#v}" >> $GITHUB_OUTPUT
echo "📦 Package version: ${VERSION#v}"
- name: List packages to build
id: packages
run: |
# Find all luci-app-* directories with Makefile
PACKAGES=""
for pkg in luci-app-*/; do
if [[ -f "${pkg}Makefile" ]]; then
PKG_NAME=$(basename "$pkg")
PACKAGES="${PACKAGES}${PKG_NAME},"
echo "📦 Found: $PKG_NAME"
fi
done
# Remove trailing comma
PACKAGES="${PACKAGES%,}"
echo "list=${PACKAGES}" >> $GITHUB_OUTPUT
echo "📋 Packages to build: $PACKAGES"
- name: Set build matrix
id: set-matrix
run: |
cat > /tmp/matrix.json << 'MATRIX_EOF'
{
"include": [
{
"target": "x86-64",
"arch": "x86_64",
"sdk_name": "x86-64",
"description": "x86 64-bit (PC, VM, containers)"
},
{
"target": "aarch64-cortex-a53",
"arch": "aarch64_cortex-a53",
"sdk_name": "mvebu-cortexa53",
"description": "ARM Cortex-A53 (ESPRESSObin, Sheeva64)"
},
{
"target": "aarch64-cortex-a72",
"arch": "aarch64_cortex-a72",
"sdk_name": "mvebu-cortexa72",
"description": "ARM Cortex-A72 (MOCHAbin)"
},
{
"target": "aarch64-generic",
"arch": "aarch64_generic",
"sdk_name": "armsr-armv8",
"description": "ARM 64-bit generic (RPi4, Rock64)"
},
{
"target": "arm-cortex-a7-neon",
"arch": "arm_cortex-a7_neon-vfpv4",
"sdk_name": "sunxi-cortexa7",
"description": "ARM Cortex-A7 (Orange Pi, Banana Pi)"
},
{
"target": "arm-cortex-a9-neon",
"arch": "arm_cortex-a9_neon",
"sdk_name": "mvebu-cortexa9",
"description": "ARM Cortex-A9 (Linksys WRT, Turris)"
},
{
"target": "mips-24kc",
"arch": "mips_24kc",
"sdk_name": "ath79-generic",
"description": "MIPS 24Kc (TP-Link, Ubiquiti)"
},
{
"target": "mipsel-24kc",
"arch": "mipsel_24kc",
"sdk_name": "ramips-mt7621",
"description": "MIPS Little-Endian (Xiaomi, GL.iNet)"
},
{
"target": "mediatek-filogic",
"arch": "aarch64_cortex-a53",
"sdk_name": "mediatek-filogic",
"description": "MediaTek Filogic (MT7981, MT7986)"
},
{
"target": "rockchip-armv8",
"arch": "aarch64_generic",
"sdk_name": "rockchip-armv8",
"description": "Rockchip (NanoPi R4S, R5S)"
},
{
"target": "bcm27xx-bcm2711",
"arch": "aarch64_cortex-a72",
"sdk_name": "bcm27xx-bcm2711",
"description": "Raspberry Pi 4"
}
]
}
MATRIX_EOF
INPUT_ARCHS="${{ github.event.inputs.architectures }}"
if [[ -z "$INPUT_ARCHS" || "$INPUT_ARCHS" == "all" ]]; then
MATRIX=$(cat /tmp/matrix.json | jq -c '.')
else
MATRIX=$(cat /tmp/matrix.json | jq -c --arg archs "$INPUT_ARCHS" '
.include |= map(select(.target as $t | $archs | split(",") | map(gsub("^\\s+|\\s+$";"")) | any(. == $t or . == "all")))
')
fi
echo "matrix<<EOF" >> $GITHUB_OUTPUT
echo "$MATRIX" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
echo "📋 Build matrix:"
echo "$MATRIX" | jq '.'
# ============================================
# Build packages for each architecture
# ============================================
build:
needs: setup
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.setup.outputs.matrix) }}
name: Build ${{ matrix.target }}
steps:
- name: Checkout source
uses: actions/checkout@v4
- name: Free disk space
run: |
echo "🧹 Cleaning up disk space..."
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL
sudo docker image prune --all --force
df -h
- 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 \
swig unzip zlib1g-dev file wget curl jq
- name: Cache OpenWrt SDK
uses: actions/cache@v4
id: cache-sdk
with:
path: ~/sdk
key: openwrt-sdk-${{ env.OPENWRT_VERSION }}-${{ matrix.sdk_name }}-v2
- name: Download OpenWrt SDK
if: steps.cache-sdk.outputs.cache-hit != 'true'
run: |
echo "📥 Downloading SDK for ${{ matrix.description }}..."
BASE_URL="https://downloads.openwrt.org/releases/${{ env.OPENWRT_VERSION }}/targets"
# Map sdk_name to target/subtarget
case "${{ matrix.sdk_name }}" in
x86-64) TARGET_PATH="x86/64" ;;
x86-generic) TARGET_PATH="x86/generic" ;;
mvebu-cortexa53) TARGET_PATH="mvebu/cortexa53" ;;
mvebu-cortexa72) TARGET_PATH="mvebu/cortexa72" ;;
mvebu-cortexa9) TARGET_PATH="mvebu/cortexa9" ;;
armsr-armv8) TARGET_PATH="armsr/armv8" ;;
sunxi-cortexa7) TARGET_PATH="sunxi/cortexa7" ;;
ath79-generic) TARGET_PATH="ath79/generic" ;;
ramips-mt7621) TARGET_PATH="ramips/mt7621" ;;
bcm47xx-mips74k) TARGET_PATH="bcm47xx/mips74k" ;;
mediatek-filogic) TARGET_PATH="mediatek/filogic" ;;
ipq40xx-generic) TARGET_PATH="ipq40xx/generic" ;;
ipq806x-generic) TARGET_PATH="ipq806x/generic" ;;
rockchip-armv8) TARGET_PATH="rockchip/armv8" ;;
bcm27xx-bcm2711) TARGET_PATH="bcm27xx/bcm2711" ;;
armvirt-32) TARGET_PATH="armvirt/32" ;;
*)
echo "❌ Unknown SDK: ${{ matrix.sdk_name }}"
exit 1
;;
esac
SDK_URL="${BASE_URL}/${TARGET_PATH}"
echo "🔍 Looking for SDK at: $SDK_URL"
# Find SDK filename
SDK_FILE=$(curl -sL "$SDK_URL/" | grep -oP 'openwrt-sdk[^"<>]+\.tar\.(xz|zst)' | head -1)
if [[ -z "$SDK_FILE" ]]; then
echo "❌ SDK not found for ${{ matrix.sdk_name }}"
exit 1
fi
echo "📥 Downloading: $SDK_FILE"
wget -q "${SDK_URL}/${SDK_FILE}" -O /tmp/sdk.tar.xz || \
wget -q "${SDK_URL}/${SDK_FILE}" -O /tmp/sdk.tar.zst
# Extract
mkdir -p ~/sdk
if [[ -f /tmp/sdk.tar.xz ]]; then
tar -xf /tmp/sdk.tar.xz -C ~/sdk --strip-components=1
else
tar --zstd -xf /tmp/sdk.tar.zst -C ~/sdk --strip-components=1
fi
echo "✅ SDK extracted"
- name: Setup SDK feeds
run: |
cd ~/sdk
# Update and install feeds
./scripts/feeds update -a
./scripts/feeds install -a
# Base config
make defconfig
echo "✅ SDK feeds configured"
- name: Copy packages to SDK
run: |
VERSION="${{ needs.setup.outputs.version }}"
echo "📦 Copying SecuBox packages (version: $VERSION)..."
# 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/
# Update version in Makefile
sed -i "s/PKG_VERSION:=.*/PKG_VERSION:=$VERSION/" ~/sdk/package/${PKG_NAME}/Makefile
sed -i "s/PKG_RELEASE:=.*/PKG_RELEASE:=1/" ~/sdk/package/${PKG_NAME}/Makefile
fi
done
echo ""
echo "📋 Packages in SDK:"
ls -la ~/sdk/package/luci-app-* 2>/dev/null || echo "No luci-app packages found"
- name: Configure packages
run: |
cd ~/sdk
echo "⚙️ Enabling packages in config..."
# Enable each package
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
make defconfig
echo ""
echo "📋 Enabled packages:"
grep "CONFIG_PACKAGE_luci-app" .config | head -20
- name: Build packages
run: |
cd ~/sdk
echo "🔨 Building SecuBox packages for ${{ matrix.description }}..."
echo ""
BUILD_ERRORS=0
BUILT_PACKAGES=""
# Build each package individually
for pkg in ~/sdk/package/luci-app-*/; do
if [[ -d "$pkg" ]]; then
PKG_NAME=$(basename "$pkg")
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "📦 Building: $PKG_NAME"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
# Build the specific package
if make package/${PKG_NAME}/compile V=s -j$(nproc) 2>&1; then
echo "✅ Successfully built: $PKG_NAME"
BUILT_PACKAGES="${BUILT_PACKAGES}${PKG_NAME},"
else
echo "⚠️ Failed to build: $PKG_NAME, retrying with -j1..."
if make package/${PKG_NAME}/compile V=s -j1 2>&1; then
echo "✅ Successfully built on retry: $PKG_NAME"
BUILT_PACKAGES="${BUILT_PACKAGES}${PKG_NAME},"
else
echo "❌ Failed to build: $PKG_NAME"
BUILD_ERRORS=$((BUILD_ERRORS + 1))
fi
fi
echo ""
fi
done
# Generate package index
make package/index V=s || true
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "📊 Build Summary"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Built packages: $BUILT_PACKAGES"
echo "Build errors: $BUILD_ERRORS"
if [[ $BUILD_ERRORS -gt 0 ]]; then
echo "⚠️ Some packages failed to build"
fi
- name: Collect artifacts
id: collect
run: |
echo "📦 Collecting built packages..."
mkdir -p $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}
# Find and copy .ipk files
find ~/sdk/bin -name "luci-app-*.ipk" -exec cp {} $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}/ \;
# Also copy any dependency packages we might have built
find ~/sdk/bin -name "*.ipk" -exec cp {} $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}/ \; 2>/dev/null || true
# Remove duplicates (keep largest)
cd $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}
for f in *.ipk; do
[[ -f "$f" ]] || continue
done
# Copy package index
find ~/sdk/bin -name "Packages*" -exec cp {} $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}/ \; 2>/dev/null || true
# List artifacts
echo ""
echo "📋 Built packages for ${{ matrix.target }}:"
ls -la $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}/
# Count packages
PKG_COUNT=$(find $GITHUB_WORKSPACE/artifacts/${{ matrix.target }} -name "luci-app-*.ipk" | wc -l)
echo "pkg_count=$PKG_COUNT" >> $GITHUB_OUTPUT
echo ""
echo "📦 Total SecuBox packages built: $PKG_COUNT"
if [[ $PKG_COUNT -eq 0 ]]; then
echo "⚠️ No packages were built!"
exit 1
fi
- name: Create checksums
run: |
cd $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}
sha256sum *.ipk > SHA256SUMS 2>/dev/null || echo "No .ipk files to checksum"
echo "✅ Checksums created"
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: packages-${{ matrix.target }}
path: artifacts/${{ matrix.target }}/
retention-days: 30
# ============================================
# Create combined release
# ============================================
release:
needs: [setup, build]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: packages
pattern: packages-*
- name: Organize packages
run: |
echo "📁 Organizing release packages..."
VERSION="${{ needs.setup.outputs.version }}"
mkdir -p release
# Create architecture-specific archives
for arch_dir in packages/packages-*/; do
ARCH=$(basename "$arch_dir" | sed 's/packages-//')
echo "📦 Processing $ARCH..."
tar -czf "release/secubox-${VERSION}-${ARCH}.tar.gz" -C "$arch_dir" .
mkdir -p "release/ipk/${ARCH}"
cp "$arch_dir"/*.ipk "release/ipk/${ARCH}/" 2>/dev/null || true
done
# Create "all architectures" mega-archive
tar -czf "release/secubox-${VERSION}-all-architectures.tar.gz" -C packages .
# Create release notes
cat > release/RELEASE_NOTES.md << 'EOF'
# SecuBox Packages v${{ needs.setup.outputs.version }}
## 📦 Included Packages
| Package | Description |
|---------|-------------|
| luci-app-secubox | SecuBox Hub - Central Dashboard |
| luci-app-crowdsec-dashboard | CrowdSec Security Dashboard |
| luci-app-netdata-dashboard | Netdata Monitoring |
| luci-app-netifyd-dashboard | Netifyd DPI Dashboard |
| luci-app-wireguard-dashboard | WireGuard VPN Dashboard |
| luci-app-network-modes | Network Mode Switcher |
| luci-app-client-guardian | NAC & Captive Portal |
| luci-app-system-hub | System Control Center |
| luci-app-bandwidth-manager | QoS & Bandwidth Control |
| luci-app-auth-guardian | OAuth & Voucher Portal |
| luci-app-media-flow | Streaming DPI |
| luci-app-vhost-manager | Reverse Proxy Manager |
| luci-app-cdn-cache | Local CDN Cache |
## 📥 Installation
```bash
# Upload .ipk to router, then:
opkg update
opkg install /tmp/luci-app-secubox_*.ipk
```
## 🔗 Links
- [SecuBox Website](https://secubox.cybermood.eu)
- [Documentation](https://cybermind.fr/docs/secubox)
- [CyberMind.fr](https://cybermind.fr)
---
Built with OpenWrt SDK ${{ env.OPENWRT_VERSION }}
EOF
echo "✅ Release organized"
ls -la release/
- name: Create global checksums
run: |
cd release
sha256sum *.tar.gz > SHA256SUMS
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
name: SecuBox ${{ needs.setup.outputs.version }}
body_path: release/RELEASE_NOTES.md
files: |
release/*.tar.gz
release/SHA256SUMS
draft: false
prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') || contains(github.ref, 'rc') }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# ============================================
# Build status summary
# ============================================
summary:
needs: [setup, build]
runs-on: ubuntu-latest
if: always()
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: packages
pattern: packages-*
continue-on-error: true
- name: Generate build summary
run: |
echo "# 📊 SecuBox Build Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Version:** ${{ needs.setup.outputs.version }}" >> $GITHUB_STEP_SUMMARY
echo "**OpenWrt:** ${{ env.OPENWRT_VERSION }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Build Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Architecture | Status | Packages |" >> $GITHUB_STEP_SUMMARY
echo "|--------------|--------|----------|" >> $GITHUB_STEP_SUMMARY
for arch_dir in packages/packages-*/; do
if [[ -d "$arch_dir" ]]; then
ARCH=$(basename "$arch_dir" | sed 's/packages-//')
PKG_COUNT=$(find "$arch_dir" -name "luci-app-*.ipk" 2>/dev/null | wc -l)
if [[ $PKG_COUNT -gt 0 ]]; then
echo "| $ARCH | ✅ Success | $PKG_COUNT |" >> $GITHUB_STEP_SUMMARY
else
echo "| $ARCH | ⚠️ No packages | 0 |" >> $GITHUB_STEP_SUMMARY
fi
fi
done
echo "" >> $GITHUB_STEP_SUMMARY
echo "## 📦 Artifacts" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Download artifacts from the Actions tab above." >> $GITHUB_STEP_SUMMARY