- Split builds into SDK (PKGARCH:=all) and Toolchain (native binaries) - Mirror OPENWRT_ONLY_PACKAGES list from local-build.sh - Add all architectures: x86-64, aarch64-cortex-a72, aarch64-cortex-a53, aarch64-generic, rockchip-armv8, mips-24kc, mipsel-24kc - SDK builds: LuCI apps, shell scripts, configs - Toolchain builds: Go (crowdsec), C++ (netifyd, ndpid) - Combine artifacts per architecture with checksums - Create GitHub releases on tags Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
744 lines
26 KiB
YAML
744 lines
26 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: '24.10.5'
|
|
type: choice
|
|
options:
|
|
- '24.10.5'
|
|
- '23.05.5'
|
|
build_toolchain_packages:
|
|
description: 'Build toolchain packages (Go/C++)'
|
|
required: false
|
|
default: true
|
|
type: boolean
|
|
architectures:
|
|
description: 'Architectures (comma-separated or "all")'
|
|
required: false
|
|
default: 'all'
|
|
|
|
env:
|
|
OPENWRT_VERSION: ${{ github.event.inputs.openwrt_version || '24.10.5' }}
|
|
|
|
permissions:
|
|
contents: write
|
|
|
|
jobs:
|
|
# ============================================
|
|
# Setup - determine version and build matrix
|
|
# Mirrors: local-build.sh setup logic
|
|
# ============================================
|
|
setup:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
|
version: ${{ steps.version.outputs.version }}
|
|
sdk_packages: ${{ steps.packages.outputs.sdk_packages }}
|
|
toolchain_packages: ${{ steps.packages.outputs.toolchain_packages }}
|
|
|
|
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: Categorize packages (mirrors local-build.sh OPENWRT_ONLY_PACKAGES)
|
|
id: packages
|
|
run: |
|
|
# Toolchain-only packages (from local-build.sh OPENWRT_ONLY_PACKAGES)
|
|
# These compile native code and need full OpenWrt buildroot
|
|
TOOLCHAIN_ONLY=(
|
|
# C/C++ native binaries
|
|
"secubox-app-netifyd"
|
|
"secubox-app-ndpid"
|
|
"secubox-app-nodogsplash"
|
|
# Go binaries
|
|
"secubox-app-crowdsec"
|
|
"secubox-app-cs-firewall-bouncer"
|
|
# Python/special packages
|
|
"secubox-app-mitmproxy"
|
|
"secubox-app-metablogizer"
|
|
"secubox-app-tor"
|
|
)
|
|
|
|
SDK_PACKAGES=""
|
|
TOOLCHAIN_PACKAGES=""
|
|
|
|
# Find all secubox packages
|
|
for pkg_dir in package/secubox/*/; do
|
|
[ -f "${pkg_dir}Makefile" ] || continue
|
|
PKG_NAME=$(basename "$pkg_dir")
|
|
|
|
# Check if it's in toolchain-only list
|
|
IS_TOOLCHAIN=false
|
|
for tc_pkg in "${TOOLCHAIN_ONLY[@]}"; do
|
|
if [[ "$PKG_NAME" == "$tc_pkg" ]]; then
|
|
IS_TOOLCHAIN=true
|
|
break
|
|
fi
|
|
done
|
|
|
|
if $IS_TOOLCHAIN; then
|
|
TOOLCHAIN_PACKAGES="${TOOLCHAIN_PACKAGES}${PKG_NAME},"
|
|
else
|
|
SDK_PACKAGES="${SDK_PACKAGES}${PKG_NAME},"
|
|
fi
|
|
done
|
|
|
|
# Root level luci-app-* (all SDK buildable)
|
|
for pkg_dir in luci-app-*/; do
|
|
[ -f "${pkg_dir}Makefile" ] || continue
|
|
PKG_NAME=$(basename "$pkg_dir")
|
|
SDK_PACKAGES="${SDK_PACKAGES}${PKG_NAME},"
|
|
done
|
|
|
|
# luci-theme-secubox
|
|
[ -d "luci-theme-secubox" ] && SDK_PACKAGES="${SDK_PACKAGES}luci-theme-secubox,"
|
|
|
|
echo "sdk_packages=${SDK_PACKAGES%,}" >> $GITHUB_OUTPUT
|
|
echo "toolchain_packages=${TOOLCHAIN_PACKAGES%,}" >> $GITHUB_OUTPUT
|
|
|
|
echo "📦 SDK packages (PKGARCH:=all): ${SDK_PACKAGES%,}"
|
|
echo "🔧 Toolchain packages (native binaries): ${TOOLCHAIN_PACKAGES%,}"
|
|
|
|
- name: Set build matrix (mirrors local-build.sh set_architecture)
|
|
id: set-matrix
|
|
run: |
|
|
# Architecture mapping from local-build.sh
|
|
cat > /tmp/matrix.json << 'EOF'
|
|
{
|
|
"include": [
|
|
{
|
|
"target": "x86-64",
|
|
"arch": "x86_64",
|
|
"sdk_path": "x86/64",
|
|
"toolchain_target": "x86",
|
|
"toolchain_subtarget": "64",
|
|
"description": "x86 64-bit (PC, VM)"
|
|
},
|
|
{
|
|
"target": "aarch64-cortex-a72",
|
|
"arch": "aarch64_cortex-a72",
|
|
"sdk_path": "mvebu/cortexa72",
|
|
"toolchain_target": "mvebu",
|
|
"toolchain_subtarget": "cortexa72",
|
|
"description": "ARM Cortex-A72 (MOCHAbin, RPi4)"
|
|
},
|
|
{
|
|
"target": "aarch64-cortex-a53",
|
|
"arch": "aarch64_cortex-a53",
|
|
"sdk_path": "mvebu/cortexa53",
|
|
"toolchain_target": "mvebu",
|
|
"toolchain_subtarget": "cortexa53",
|
|
"description": "ARM Cortex-A53 (ESPRESSObin)"
|
|
},
|
|
{
|
|
"target": "aarch64-generic",
|
|
"arch": "aarch64_generic",
|
|
"sdk_path": "armsr/armv8",
|
|
"toolchain_target": "armsr",
|
|
"toolchain_subtarget": "armv8",
|
|
"description": "ARM 64-bit generic"
|
|
},
|
|
{
|
|
"target": "rockchip-armv8",
|
|
"arch": "aarch64_generic",
|
|
"sdk_path": "rockchip/armv8",
|
|
"toolchain_target": "rockchip",
|
|
"toolchain_subtarget": "armv8",
|
|
"description": "Rockchip (NanoPi R4S/R5S)"
|
|
},
|
|
{
|
|
"target": "mips-24kc",
|
|
"arch": "mips_24kc",
|
|
"sdk_path": "ath79/generic",
|
|
"toolchain_target": "ath79",
|
|
"toolchain_subtarget": "generic",
|
|
"description": "MIPS 24Kc (Atheros/QCA)"
|
|
},
|
|
{
|
|
"target": "mipsel-24kc",
|
|
"arch": "mipsel_24kc",
|
|
"sdk_path": "ramips/mt7621",
|
|
"toolchain_target": "ramips",
|
|
"toolchain_subtarget": "mt7621",
|
|
"description": "MIPS LE (MT7621)"
|
|
}
|
|
]
|
|
}
|
|
EOF
|
|
|
|
# Filter by input architectures if specified
|
|
INPUT_ARCHS="${{ github.event.inputs.architectures }}"
|
|
if [[ -z "$INPUT_ARCHS" || "$INPUT_ARCHS" == "all" ]]; then
|
|
MATRIX=$(cat /tmp/matrix.json)
|
|
else
|
|
MATRIX=$(jq -c --arg archs "$INPUT_ARCHS" '
|
|
.include |= map(select(.target as $t | $archs | split(",") | map(gsub("^\\s+|\\s+$";"")) | any(. == $t)))
|
|
' /tmp/matrix.json)
|
|
fi
|
|
|
|
echo "matrix=$(echo "$MATRIX" | jq -c)" >> $GITHUB_OUTPUT
|
|
echo "📋 Build matrix:"
|
|
echo "$MATRIX" | jq '.'
|
|
|
|
# ============================================
|
|
# Build SDK packages (LuCI apps, shell scripts)
|
|
# Mirrors: local-build.sh SDK build path
|
|
# ============================================
|
|
build-sdk:
|
|
needs: setup
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
fail-fast: false
|
|
matrix: ${{ fromJson(needs.setup.outputs.matrix) }}
|
|
|
|
name: SDK ${{ matrix.target }}
|
|
|
|
steps:
|
|
- name: Checkout source
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Free disk space
|
|
run: |
|
|
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL
|
|
sudo docker image prune --all --force
|
|
|
|
- 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 rsync 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.target }}-v6
|
|
|
|
- name: Download OpenWrt SDK
|
|
if: steps.cache-sdk.outputs.cache-hit != 'true'
|
|
run: |
|
|
BASE_URL="https://downloads.openwrt.org/releases/${{ env.OPENWRT_VERSION }}/targets/${{ matrix.sdk_path }}"
|
|
|
|
for attempt in 1 2 3; do
|
|
SDK_FILE=$(curl -sL "$BASE_URL/" | grep -oP 'openwrt-sdk[^"<>]+\.tar\.(xz|zst)' | head -1) && break
|
|
sleep 10
|
|
done
|
|
|
|
[ -z "$SDK_FILE" ] && { echo "❌ Could not find SDK"; exit 1; }
|
|
|
|
echo "📥 Downloading: $SDK_FILE"
|
|
wget -q "${BASE_URL}/${SDK_FILE}" -O /tmp/sdk.tar.xz
|
|
mkdir -p sdk
|
|
tar -xf /tmp/sdk.tar.xz -C sdk --strip-components=1
|
|
rm -f /tmp/sdk.tar.xz
|
|
|
|
- name: Setup SDK feeds (mirrors local-build.sh)
|
|
run: |
|
|
cd sdk
|
|
|
|
# Remove unwanted feeds (from local-build.sh)
|
|
sed -i '/telephony/d; /routing/d' feeds.conf.default 2>/dev/null || true
|
|
|
|
# Determine branch based on OpenWrt version
|
|
VERSION="${{ env.OPENWRT_VERSION }}"
|
|
if [[ "$VERSION" =~ ^24\. ]]; then
|
|
BRANCH="openwrt-24.10"
|
|
elif [[ "$VERSION" =~ ^23\. ]]; then
|
|
BRANCH="openwrt-23.05"
|
|
else
|
|
BRANCH="master"
|
|
fi
|
|
|
|
echo "📌 Using branch: $BRANCH for OpenWrt $VERSION"
|
|
|
|
cat > feeds.conf << EOF
|
|
src-git packages https://github.com/openwrt/packages.git;$BRANCH
|
|
src-git luci https://github.com/openwrt/luci.git;$BRANCH
|
|
src-link secubox ${{ github.workspace }}/secubox-tools/local-feed
|
|
EOF
|
|
|
|
# Update feeds with retry
|
|
for feed in packages luci; do
|
|
for attempt in 1 2 3; do
|
|
./scripts/feeds update $feed && break
|
|
sleep $((10 * attempt))
|
|
done
|
|
done
|
|
|
|
./scripts/feeds install -a
|
|
make defconfig
|
|
|
|
- name: Copy packages to SDK
|
|
run: |
|
|
VERSION="${{ needs.setup.outputs.version }}"
|
|
|
|
# Sync to local-feed first (mirrors local-build.sh)
|
|
mkdir -p secubox-tools/local-feed
|
|
|
|
for pkg in package/secubox/*/; do
|
|
[ -f "${pkg}Makefile" ] || continue
|
|
PKG_NAME=$(basename "$pkg")
|
|
cp -r "$pkg" "secubox-tools/local-feed/"
|
|
|
|
# Update version in copied package
|
|
sed -i "s/PKG_VERSION:=.*/PKG_VERSION:=$VERSION/" "secubox-tools/local-feed/${PKG_NAME}/Makefile" 2>/dev/null || true
|
|
sed -i "s/PKG_RELEASE:=.*/PKG_RELEASE:=1/" "secubox-tools/local-feed/${PKG_NAME}/Makefile" 2>/dev/null || true
|
|
done
|
|
|
|
# Copy root level luci-app-*
|
|
for pkg in luci-app-*/; do
|
|
[ -f "${pkg}Makefile" ] || continue
|
|
cp -r "$pkg" "secubox-tools/local-feed/"
|
|
done
|
|
|
|
# Copy theme
|
|
[ -d "luci-theme-secubox" ] && cp -r "luci-theme-secubox" "secubox-tools/local-feed/"
|
|
|
|
# Update secubox feed
|
|
cd sdk
|
|
./scripts/feeds update secubox
|
|
./scripts/feeds install -a -p secubox
|
|
|
|
- name: Build SDK packages
|
|
run: |
|
|
cd sdk
|
|
|
|
SDK_PACKAGES="${{ needs.setup.outputs.sdk_packages }}"
|
|
echo "📦 Building SDK packages: $SDK_PACKAGES"
|
|
|
|
# Enable packages
|
|
for pkg in ${SDK_PACKAGES//,/ }; do
|
|
echo "CONFIG_PACKAGE_${pkg}=m" >> .config
|
|
|
|
# Remove LUCI_DEPENDS for SDK build (runtime only)
|
|
PKG_DIR=$(find package -name "$pkg" -type d | head -1)
|
|
[ -n "$PKG_DIR" ] && sed -i 's/^LUCI_DEPENDS:=/#&/' "$PKG_DIR/Makefile" 2>/dev/null || true
|
|
done
|
|
|
|
make defconfig
|
|
|
|
# Build each package
|
|
BUILT=0
|
|
FAILED=0
|
|
BUILT_LIST=""
|
|
FAILED_LIST=""
|
|
|
|
for pkg in ${SDK_PACKAGES//,/ }; do
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "📦 Building: $pkg"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
|
|
if timeout 300 make package/$pkg/compile V=s -j$(nproc) 2>&1 | tail -30; then
|
|
PKG_FILE=$(find bin -name "${pkg}*.ipk" 2>/dev/null | head -1)
|
|
if [ -n "$PKG_FILE" ]; then
|
|
echo "✅ Built: $pkg → $PKG_FILE"
|
|
BUILT=$((BUILT + 1))
|
|
BUILT_LIST="${BUILT_LIST}${pkg},"
|
|
else
|
|
echo "⚠️ No .ipk generated for $pkg"
|
|
FAILED=$((FAILED + 1))
|
|
FAILED_LIST="${FAILED_LIST}${pkg},"
|
|
fi
|
|
else
|
|
echo "❌ Build failed: $pkg"
|
|
FAILED=$((FAILED + 1))
|
|
FAILED_LIST="${FAILED_LIST}${pkg},"
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "📊 SDK Build Summary for ${{ matrix.target }}"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "✅ Built: $BUILT packages"
|
|
echo "❌ Failed: $FAILED packages"
|
|
[ -n "$BUILT_LIST" ] && echo "Built: ${BUILT_LIST%,}"
|
|
[ -n "$FAILED_LIST" ] && echo "Failed: ${FAILED_LIST%,}"
|
|
|
|
- name: Collect SDK artifacts
|
|
id: collect
|
|
run: |
|
|
mkdir -p artifacts/${{ matrix.target }}
|
|
find sdk/bin -name "*.ipk" -exec cp {} artifacts/${{ matrix.target }}/ \; 2>/dev/null || true
|
|
|
|
PKG_COUNT=$(find artifacts/${{ matrix.target }} -name "*.ipk" 2>/dev/null | wc -l)
|
|
echo "pkg_count=$PKG_COUNT" >> $GITHUB_OUTPUT
|
|
|
|
echo "📦 SDK packages for ${{ matrix.target }}: $PKG_COUNT"
|
|
ls -la artifacts/${{ matrix.target }}/ 2>/dev/null || echo "None"
|
|
|
|
# Create checksums
|
|
[ "$PKG_COUNT" -gt 0 ] && (cd artifacts/${{ matrix.target }} && sha256sum *.ipk > SHA256SUMS)
|
|
|
|
- name: Upload SDK artifacts
|
|
uses: actions/upload-artifact@v4
|
|
if: steps.collect.outputs.pkg_count > 0
|
|
with:
|
|
name: sdk-packages-${{ matrix.target }}
|
|
path: artifacts/${{ matrix.target }}/
|
|
retention-days: 30
|
|
|
|
# ============================================
|
|
# Build Toolchain packages (Go, C/C++)
|
|
# Mirrors: local-build.sh OpenWrt buildroot path
|
|
# ============================================
|
|
build-toolchain:
|
|
needs: setup
|
|
if: github.event.inputs.build_toolchain_packages != 'false' && needs.setup.outputs.toolchain_packages != ''
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
fail-fast: false
|
|
matrix: ${{ fromJson(needs.setup.outputs.matrix) }}
|
|
|
|
name: Toolchain ${{ matrix.target }}
|
|
|
|
steps:
|
|
- name: Checkout source
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Free disk space
|
|
run: |
|
|
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
|
|
|
|
- name: Cache OpenWrt Toolchain
|
|
uses: actions/cache@v4
|
|
id: cache-toolchain
|
|
with:
|
|
path: openwrt
|
|
key: openwrt-toolchain-${{ env.OPENWRT_VERSION }}-${{ matrix.target }}-v4
|
|
|
|
- name: Clone OpenWrt
|
|
if: steps.cache-toolchain.outputs.cache-hit != 'true'
|
|
run: |
|
|
VERSION="${{ env.OPENWRT_VERSION }}"
|
|
if [[ "$VERSION" =~ ^24\. ]]; then
|
|
BRANCH="openwrt-24.10"
|
|
elif [[ "$VERSION" =~ ^23\. ]]; then
|
|
BRANCH="openwrt-23.05"
|
|
else
|
|
BRANCH="master"
|
|
fi
|
|
|
|
git clone --depth 1 -b "$BRANCH" https://github.com/openwrt/openwrt.git
|
|
|
|
- name: Setup OpenWrt feeds
|
|
run: |
|
|
cd openwrt
|
|
./scripts/feeds update -a
|
|
./scripts/feeds install -a
|
|
|
|
- name: Configure and build toolchain
|
|
if: steps.cache-toolchain.outputs.cache-hit != 'true'
|
|
run: |
|
|
cd openwrt
|
|
|
|
# Set target configuration
|
|
cat > .config << EOF
|
|
CONFIG_TARGET_${{ matrix.toolchain_target }}=y
|
|
CONFIG_TARGET_${{ matrix.toolchain_target }}_${{ matrix.toolchain_subtarget }}=y
|
|
CONFIG_PACKAGE_golang=y
|
|
CONFIG_PACKAGE_golang-src=y
|
|
EOF
|
|
|
|
make defconfig
|
|
echo "⚙️ Building toolchain for ${{ matrix.target }}..."
|
|
make toolchain/install -j$(nproc) V=s || make toolchain/install -j1 V=s
|
|
|
|
- name: Copy toolchain packages
|
|
run: |
|
|
VERSION="${{ needs.setup.outputs.version }}"
|
|
TOOLCHAIN_PACKAGES="${{ needs.setup.outputs.toolchain_packages }}"
|
|
|
|
mkdir -p openwrt/package/secubox
|
|
|
|
for pkg in ${TOOLCHAIN_PACKAGES//,/ }; do
|
|
if [ -d "package/secubox/$pkg" ]; then
|
|
cp -r "package/secubox/$pkg" "openwrt/package/secubox/"
|
|
sed -i "s/PKG_VERSION:=.*/PKG_VERSION:=$VERSION/" "openwrt/package/secubox/${pkg}/Makefile" 2>/dev/null || true
|
|
sed -i "s/PKG_RELEASE:=.*/PKG_RELEASE:=1/" "openwrt/package/secubox/${pkg}/Makefile" 2>/dev/null || true
|
|
fi
|
|
done
|
|
|
|
- name: Build toolchain packages
|
|
run: |
|
|
cd openwrt
|
|
|
|
TOOLCHAIN_PACKAGES="${{ needs.setup.outputs.toolchain_packages }}"
|
|
echo "🔧 Building toolchain packages: $TOOLCHAIN_PACKAGES"
|
|
|
|
for pkg in ${TOOLCHAIN_PACKAGES//,/ }; do
|
|
echo "CONFIG_PACKAGE_${pkg}=m" >> .config
|
|
done
|
|
|
|
make defconfig
|
|
|
|
BUILT=0
|
|
FAILED=0
|
|
|
|
for pkg in ${TOOLCHAIN_PACKAGES//,/ }; do
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "🔧 Building: $pkg"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
|
|
if timeout 1800 make package/$pkg/compile V=s -j$(nproc) 2>&1 | tail -50; then
|
|
PKG_FILE=$(find bin -name "${pkg}*.ipk" 2>/dev/null | head -1)
|
|
if [ -n "$PKG_FILE" ]; then
|
|
echo "✅ Built: $pkg → $PKG_FILE"
|
|
BUILT=$((BUILT + 1))
|
|
else
|
|
echo "⚠️ No .ipk generated for $pkg"
|
|
FAILED=$((FAILED + 1))
|
|
fi
|
|
else
|
|
echo "❌ Build failed: $pkg"
|
|
FAILED=$((FAILED + 1))
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo "📊 Toolchain Build Summary: $BUILT built, $FAILED failed"
|
|
|
|
- name: Collect toolchain artifacts
|
|
id: collect
|
|
run: |
|
|
mkdir -p artifacts/${{ matrix.target }}
|
|
find openwrt/bin -name "*.ipk" -exec cp {} artifacts/${{ matrix.target }}/ \; 2>/dev/null || true
|
|
|
|
PKG_COUNT=$(find artifacts/${{ matrix.target }} -name "*.ipk" 2>/dev/null | wc -l)
|
|
echo "pkg_count=$PKG_COUNT" >> $GITHUB_OUTPUT
|
|
|
|
echo "🔧 Toolchain packages for ${{ matrix.target }}: $PKG_COUNT"
|
|
ls -la artifacts/${{ matrix.target }}/ 2>/dev/null || echo "None"
|
|
|
|
- name: Upload toolchain artifacts
|
|
uses: actions/upload-artifact@v4
|
|
if: steps.collect.outputs.pkg_count > 0
|
|
with:
|
|
name: toolchain-packages-${{ matrix.target }}
|
|
path: artifacts/${{ matrix.target }}/
|
|
retention-days: 30
|
|
|
|
# ============================================
|
|
# Combine and publish artifacts
|
|
# ============================================
|
|
publish:
|
|
needs: [setup, build-sdk, build-toolchain]
|
|
if: always() && (needs.build-sdk.result == 'success' || needs.build-toolchain.result == 'success')
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Download all artifacts
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
path: packages
|
|
pattern: '*-packages-*'
|
|
|
|
- name: Combine packages per architecture
|
|
run: |
|
|
VERSION="${{ needs.setup.outputs.version }}"
|
|
mkdir -p release
|
|
|
|
# Combine SDK and toolchain packages per architecture
|
|
for dir in packages/*/; do
|
|
[ -d "$dir" ] || continue
|
|
|
|
# Extract architecture from directory name
|
|
ARCH=$(basename "$dir" | sed 's/.*-packages-//')
|
|
mkdir -p "release/${ARCH}"
|
|
|
|
# Copy all .ipk files
|
|
find "$dir" -name "*.ipk" -exec cp {} "release/${ARCH}/" \; 2>/dev/null || true
|
|
done
|
|
|
|
# Create per-architecture tarballs
|
|
for arch_dir in release/*/; do
|
|
[ -d "$arch_dir" ] || continue
|
|
ARCH=$(basename "$arch_dir")
|
|
PKG_COUNT=$(find "$arch_dir" -name "*.ipk" | wc -l)
|
|
|
|
if [ "$PKG_COUNT" -gt 0 ]; then
|
|
tar -czf "release/secubox-${VERSION}-${ARCH}.tar.gz" -C "release/${ARCH}" .
|
|
echo "📦 $ARCH: $PKG_COUNT packages"
|
|
fi
|
|
done
|
|
|
|
# Create all-in-one archive
|
|
tar -czf "release/secubox-${VERSION}-all-architectures.tar.gz" -C release .
|
|
|
|
# Checksums
|
|
cd release
|
|
sha256sum *.tar.gz > SHA256SUMS 2>/dev/null || true
|
|
|
|
echo ""
|
|
echo "📋 Release contents:"
|
|
ls -la
|
|
|
|
- name: Upload combined release
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: secubox-release-${{ needs.setup.outputs.version }}
|
|
path: |
|
|
release/*.tar.gz
|
|
release/SHA256SUMS
|
|
retention-days: 90
|
|
|
|
# ============================================
|
|
# Create GitHub Release (on tags)
|
|
# ============================================
|
|
release:
|
|
needs: [setup, publish]
|
|
if: startsWith(github.ref, 'refs/tags/v')
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Download release artifact
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: secubox-release-${{ needs.setup.outputs.version }}
|
|
path: release
|
|
|
|
- name: Create GitHub Release
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
name: SecuBox v${{ needs.setup.outputs.version }}
|
|
body: |
|
|
## 📦 SecuBox Packages v${{ needs.setup.outputs.version }}
|
|
|
|
Pre-built OpenWrt packages for OpenWrt ${{ env.OPENWRT_VERSION }}.
|
|
|
|
### 📥 Installation
|
|
|
|
```bash
|
|
# Upload .ipk files to router
|
|
opkg update
|
|
opkg install /tmp/*.ipk
|
|
/etc/init.d/rpcd restart
|
|
```
|
|
|
|
### 🏗️ Supported Architectures
|
|
|
|
| Target | Description |
|
|
|--------|-------------|
|
|
| `x86-64` | PC, VMs, Proxmox |
|
|
| `aarch64-cortex-a72` | MOCHAbin, Raspberry Pi 4 |
|
|
| `aarch64-cortex-a53` | ESPRESSObin |
|
|
| `aarch64-generic` | NanoPi R4S/R5S, Generic ARM64 |
|
|
| `rockchip-armv8` | NanoPi R4S/R5S (Rockchip) |
|
|
| `mips-24kc` | TP-Link, Atheros/QCA |
|
|
| `mipsel-24kc` | Xiaomi, GL.iNet, MT7621 |
|
|
|
|
### 📦 Package Types
|
|
|
|
- **SDK packages**: LuCI apps, shell scripts (PKGARCH:=all)
|
|
- **Toolchain packages**: Go binaries (crowdsec), C++ binaries (netifyd)
|
|
|
|
files: |
|
|
release/*.tar.gz
|
|
release/SHA256SUMS
|
|
draft: false
|
|
prerelease: false
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
# ============================================
|
|
# Summary
|
|
# ============================================
|
|
summary:
|
|
needs: [setup, build-sdk, build-toolchain, publish]
|
|
if: always()
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Download artifacts for summary
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
path: packages
|
|
pattern: '*-packages-*'
|
|
continue-on-error: true
|
|
|
|
- name: Generate summary
|
|
run: |
|
|
echo "# 📊 SecuBox Build Summary" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Property | Value |" >> $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 "## Package Categories" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "**SDK Packages** (PKGARCH:=all):" >> $GITHUB_STEP_SUMMARY
|
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
echo "${{ needs.setup.outputs.sdk_packages }}" | tr ',' '\n' >> $GITHUB_STEP_SUMMARY
|
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "**Toolchain Packages** (native binaries):" >> $GITHUB_STEP_SUMMARY
|
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
echo "${{ needs.setup.outputs.toolchain_packages }}" | tr ',' '\n' >> $GITHUB_STEP_SUMMARY
|
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
echo "## Build Results" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY
|
|
echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY
|
|
echo "| SDK Build | ${{ needs.build-sdk.result }} |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Toolchain Build | ${{ needs.build-toolchain.result }} |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Publish | ${{ needs.publish.result }} |" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
echo "## Packages per Architecture" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Architecture | SDK | Toolchain | Total |" >> $GITHUB_STEP_SUMMARY
|
|
echo "|--------------|-----|-----------|-------|" >> $GITHUB_STEP_SUMMARY
|
|
|
|
for dir in packages/*/; do
|
|
[ -d "$dir" ] || continue
|
|
ARCH=$(basename "$dir" | sed 's/.*-packages-//')
|
|
TYPE=$(basename "$dir" | sed 's/-packages-.*//')
|
|
COUNT=$(find "$dir" -name "*.ipk" 2>/dev/null | wc -l)
|
|
|
|
if [[ "$TYPE" == "sdk" ]]; then
|
|
echo "| $ARCH | $COUNT | - | $COUNT |" >> $GITHUB_STEP_SUMMARY
|
|
else
|
|
echo "| $ARCH | - | $COUNT | $COUNT |" >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
done
|