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.
729 lines
25 KiB
YAML
729 lines
25 KiB
YAML
name: Build OpenWrt Packages
|
|
|
|
on:
|
|
push:
|
|
branches: [main, master, develop]
|
|
tags:
|
|
- 'v*'
|
|
pull_request:
|
|
branches: [main, master]
|
|
workflow_dispatch:
|
|
inputs:
|
|
package_name:
|
|
description: 'Package to build (leave empty for all packages)'
|
|
required: false
|
|
type: choice
|
|
options:
|
|
- ''
|
|
- 'luci-app-secubox'
|
|
- 'luci-app-crowdsec-dashboard'
|
|
- 'luci-app-netdata-dashboard'
|
|
- 'luci-app-netifyd-dashboard'
|
|
- 'luci-app-wireguard-dashboard'
|
|
- 'luci-app-network-modes'
|
|
- 'luci-app-client-guardian'
|
|
- 'luci-app-system-hub'
|
|
- 'luci-app-bandwidth-manager'
|
|
- 'luci-app-auth-guardian'
|
|
- 'luci-app-media-flow'
|
|
- 'luci-app-vhost-manager'
|
|
- 'luci-app-cdn-cache'
|
|
openwrt_version:
|
|
description: 'OpenWrt version'
|
|
required: true
|
|
default: '23.05.5'
|
|
type: choice
|
|
options:
|
|
- '23.05.5'
|
|
- '23.05.4'
|
|
- '24.10.0'
|
|
- 'SNAPSHOT'
|
|
architectures:
|
|
description: 'Architectures (comma-separated or "all")'
|
|
required: false
|
|
default: 'x86-64'
|
|
|
|
env:
|
|
OPENWRT_VERSION: ${{ github.event.inputs.openwrt_version || '23.05.5' }}
|
|
|
|
permissions:
|
|
contents: write
|
|
|
|
jobs:
|
|
# ============================================
|
|
# Setup and determine build matrix
|
|
# ============================================
|
|
setup:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
|
version: ${{ steps.version.outputs.version }}
|
|
|
|
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}"
|
|
|
|
PACKAGE_NAME="${{ github.event.inputs.package_name }}"
|
|
if [[ -n "$PACKAGE_NAME" ]]; then
|
|
echo "🎯 Building single package: $PACKAGE_NAME"
|
|
else
|
|
echo "📦 Building all packages"
|
|
fi
|
|
|
|
- name: Set build matrix
|
|
id: set-matrix
|
|
run: |
|
|
cat > /tmp/matrix.json << 'EOF'
|
|
{
|
|
"include": [
|
|
{
|
|
"target": "x86-64",
|
|
"arch": "x86_64",
|
|
"sdk_path": "x86/64",
|
|
"description": "x86 64-bit (PC, VM)"
|
|
},
|
|
{
|
|
"target": "aarch64-cortex-a53",
|
|
"arch": "aarch64_cortex-a53",
|
|
"sdk_path": "mvebu/cortexa53",
|
|
"description": "ARM Cortex-A53 (ESPRESSObin)"
|
|
},
|
|
{
|
|
"target": "aarch64-cortex-a72",
|
|
"arch": "aarch64_cortex-a72",
|
|
"sdk_path": "mvebu/cortexa72",
|
|
"description": "ARM Cortex-A72 (MOCHAbin)"
|
|
},
|
|
{
|
|
"target": "aarch64-generic",
|
|
"arch": "aarch64_generic",
|
|
"sdk_path": "armsr/armv8",
|
|
"description": "ARM 64-bit generic"
|
|
},
|
|
{
|
|
"target": "mips-24kc",
|
|
"arch": "mips_24kc",
|
|
"sdk_path": "ath79/generic",
|
|
"description": "MIPS 24Kc (TP-Link)"
|
|
},
|
|
{
|
|
"target": "mipsel-24kc",
|
|
"arch": "mipsel_24kc",
|
|
"sdk_path": "ramips/mt7621",
|
|
"description": "MIPS LE (Xiaomi, GL.iNet)"
|
|
},
|
|
{
|
|
"target": "mediatek-filogic",
|
|
"arch": "aarch64_cortex-a53",
|
|
"sdk_path": "mediatek/filogic",
|
|
"description": "MediaTek Filogic"
|
|
},
|
|
{
|
|
"target": "rockchip-armv8",
|
|
"arch": "aarch64_generic",
|
|
"sdk_path": "rockchip/armv8",
|
|
"description": "Rockchip (NanoPi R4S)"
|
|
},
|
|
{
|
|
"target": "bcm27xx-bcm2711",
|
|
"arch": "aarch64_cortex-a72",
|
|
"sdk_path": "bcm27xx/bcm2711",
|
|
"description": "Raspberry Pi 4"
|
|
}
|
|
]
|
|
}
|
|
EOF
|
|
|
|
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<<EOF" >> $GITHUB_OUTPUT
|
|
echo "$MATRIX" >> $GITHUB_OUTPUT
|
|
echo "EOF" >> $GITHUB_OUTPUT
|
|
|
|
echo "📋 Build matrix:"
|
|
echo "$MATRIX" | jq '.'
|
|
|
|
# ============================================
|
|
# Build packages
|
|
# ============================================
|
|
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.target }}-v4
|
|
|
|
- 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/${{ matrix.sdk_path }}"
|
|
|
|
# Find SDK filename with retry
|
|
for attempt in 1 2 3; do
|
|
echo "Attempt $attempt: Fetching SDK list..."
|
|
SDK_FILE=$(curl -sL --retry 3 --retry-delay 5 "$BASE_URL/" | grep -oP 'openwrt-sdk[^"<>]+\.tar\.(xz|zst)' | head -1) && break
|
|
sleep 10
|
|
done
|
|
|
|
if [[ -z "$SDK_FILE" ]]; then
|
|
echo "❌ Could not find SDK"
|
|
exit 1
|
|
fi
|
|
|
|
echo "📥 Downloading: $SDK_FILE"
|
|
|
|
# Download with retry
|
|
for attempt in 1 2 3; do
|
|
echo "Download attempt $attempt..."
|
|
wget -q --retry-connrefused --waitretry=5 --timeout=60 \
|
|
"${BASE_URL}/${SDK_FILE}" -O /tmp/sdk.tar.xz && break
|
|
sleep 15
|
|
done
|
|
|
|
# Extract
|
|
mkdir -p sdk
|
|
tar -xf /tmp/sdk.tar.xz -C sdk --strip-components=1
|
|
rm -f /tmp/sdk.tar.xz
|
|
|
|
echo "✅ SDK extracted"
|
|
|
|
- name: Setup SDK feeds (GitHub mirrors)
|
|
run: |
|
|
cd sdk
|
|
|
|
echo "📝 Configuring feeds with GitHub mirrors..."
|
|
|
|
# FIRST: Remove telephony from feeds.conf.default to prevent it from being indexed
|
|
if [[ -f "feeds.conf.default" ]]; then
|
|
sed -i '/telephony/d' feeds.conf.default
|
|
echo "✅ Removed telephony from feeds.conf.default"
|
|
fi
|
|
|
|
# Use GitHub mirrors - only essential feeds (no telephony)
|
|
cat > feeds.conf << 'FEEDS'
|
|
src-git base https://github.com/openwrt/openwrt.git;openwrt-23.05
|
|
src-git packages https://github.com/openwrt/packages.git;openwrt-23.05
|
|
src-git luci https://github.com/openwrt/luci.git;openwrt-23.05
|
|
FEEDS
|
|
|
|
echo "📋 feeds.conf:"
|
|
cat feeds.conf
|
|
|
|
# Update feeds individually with error handling
|
|
echo ""
|
|
echo "🔄 Updating feeds..."
|
|
|
|
FEEDS_OK=0
|
|
|
|
for feed in base packages luci; do
|
|
echo "Updating feed: $feed"
|
|
for attempt in 1 2 3; do
|
|
if ./scripts/feeds update $feed 2>&1; then
|
|
echo " ✅ $feed updated"
|
|
FEEDS_OK=$((FEEDS_OK + 1))
|
|
break
|
|
fi
|
|
echo " ⚠️ Attempt $attempt failed, retrying..."
|
|
sleep $((10 * attempt))
|
|
done
|
|
done
|
|
|
|
echo ""
|
|
echo "📊 Feeds updated: $FEEDS_OK/3"
|
|
|
|
# Install feeds
|
|
echo ""
|
|
echo "📦 Installing feeds..."
|
|
./scripts/feeds install -a 2>&1 || true
|
|
|
|
# Verify luci.mk exists
|
|
if [[ -f "feeds/luci/luci.mk" ]]; then
|
|
echo "✅ luci.mk found"
|
|
else
|
|
echo "⚠️ Creating fallback luci.mk..."
|
|
mkdir -p feeds/luci
|
|
cat > feeds/luci/luci.mk << 'LUCI_MK'
|
|
# Minimal LuCI build system fallback
|
|
LUCI_PKGARCH:=all
|
|
|
|
define Package/Default
|
|
SECTION:=luci
|
|
CATEGORY:=LuCI
|
|
SUBMENU:=3. Applications
|
|
PKGARCH:=all
|
|
endef
|
|
LUCI_MK
|
|
fi
|
|
|
|
# Final cleanup of telephony feed (if somehow it still got created)
|
|
rm -f feeds/telephony.index 2>/dev/null || true
|
|
rm -rf feeds/telephony 2>/dev/null || true
|
|
|
|
make defconfig
|
|
echo "✅ SDK configured"
|
|
|
|
- name: Copy packages to SDK
|
|
run: |
|
|
VERSION="${{ needs.setup.outputs.version }}"
|
|
PACKAGE_NAME="${{ github.event.inputs.package_name }}"
|
|
|
|
if [[ -n "$PACKAGE_NAME" ]]; then
|
|
echo "📦 Copying single package: $PACKAGE_NAME (version: $VERSION)..."
|
|
|
|
if [[ -d "$PACKAGE_NAME" && -f "${PACKAGE_NAME}/Makefile" ]]; then
|
|
echo " 📁 $PACKAGE_NAME"
|
|
cp -r "$PACKAGE_NAME" sdk/package/
|
|
|
|
# Update version
|
|
sed -i "s/PKG_VERSION:=.*/PKG_VERSION:=$VERSION/" "sdk/package/${PACKAGE_NAME}/Makefile"
|
|
sed -i "s/PKG_RELEASE:=.*/PKG_RELEASE:=1/" "sdk/package/${PACKAGE_NAME}/Makefile"
|
|
else
|
|
echo "❌ Package $PACKAGE_NAME not found or missing Makefile"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "📦 Copying all packages (version: $VERSION)..."
|
|
|
|
for pkg in luci-app-*/; do
|
|
if [[ -d "$pkg" && -f "${pkg}Makefile" ]]; then
|
|
PKG_NAME=$(basename "$pkg")
|
|
echo " 📁 $PKG_NAME"
|
|
cp -r "$pkg" sdk/package/
|
|
|
|
# Update version
|
|
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
|
|
fi
|
|
|
|
echo ""
|
|
echo "📋 Packages in SDK:"
|
|
ls -d sdk/package/luci-app-*/ 2>/dev/null || echo "None"
|
|
|
|
- name: Configure packages
|
|
run: |
|
|
cd sdk
|
|
|
|
echo "⚙️ Enabling packages..."
|
|
|
|
for pkg in package/luci-app-*/; do
|
|
if [[ -d "$pkg" ]]; then
|
|
PKG_NAME=$(basename "$pkg")
|
|
echo "CONFIG_PACKAGE_${PKG_NAME}=m" >> .config
|
|
echo " ✅ $PKG_NAME"
|
|
fi
|
|
done
|
|
|
|
make defconfig
|
|
|
|
- name: Build packages
|
|
run: |
|
|
cd sdk
|
|
|
|
echo "🔨 Building SecuBox packages..."
|
|
echo ""
|
|
|
|
BUILT=0
|
|
FAILED=0
|
|
BUILT_LIST=""
|
|
FAILED_LIST=""
|
|
|
|
for pkg in package/luci-app-*/; do
|
|
[[ -d "$pkg" ]] || continue
|
|
|
|
PKG_NAME=$(basename "$pkg")
|
|
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "📦 Building: $PKG_NAME"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
|
|
# Show package contents for debugging
|
|
echo "📁 Package contents:"
|
|
ls -la "$pkg"
|
|
|
|
# Verify Makefile syntax
|
|
if ! grep -q "BuildPackage" "${pkg}Makefile"; then
|
|
echo "⚠️ WARNING: Makefile missing BuildPackage call"
|
|
fi
|
|
|
|
# Build with timeout (10 minutes per package)
|
|
BUILD_LOG="/tmp/build-${PKG_NAME}.log"
|
|
|
|
if timeout 600 make package/${PKG_NAME}/compile V=s -j$(nproc) > "$BUILD_LOG" 2>&1; then
|
|
# Check if .ipk was created
|
|
IPK_FILE=$(find bin -name "${PKG_NAME}*.ipk" 2>/dev/null | head -1)
|
|
|
|
if [[ -n "$IPK_FILE" ]]; then
|
|
echo "✅ Built: $PKG_NAME"
|
|
echo " → $IPK_FILE"
|
|
BUILT=$((BUILT + 1))
|
|
BUILT_LIST="${BUILT_LIST}${PKG_NAME},"
|
|
else
|
|
echo "⚠️ No .ipk generated for $PKG_NAME"
|
|
echo "📋 Last 50 lines of build log:"
|
|
tail -50 "$BUILD_LOG"
|
|
FAILED=$((FAILED + 1))
|
|
FAILED_LIST="${FAILED_LIST}${PKG_NAME},"
|
|
fi
|
|
else
|
|
echo "❌ Build failed: $PKG_NAME"
|
|
echo "📋 Last 100 lines of build log:"
|
|
tail -100 "$BUILD_LOG"
|
|
FAILED=$((FAILED + 1))
|
|
FAILED_LIST="${FAILED_LIST}${PKG_NAME},"
|
|
fi
|
|
|
|
echo ""
|
|
done
|
|
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "📊 Build Summary"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "✅ Built: $BUILT packages"
|
|
echo "❌ Failed: $FAILED packages"
|
|
echo ""
|
|
echo "Built: $BUILT_LIST"
|
|
if [[ -n "$FAILED_LIST" ]]; then
|
|
echo "Failed: $FAILED_LIST"
|
|
fi
|
|
|
|
- name: Collect artifacts
|
|
id: collect
|
|
run: |
|
|
echo "📦 Collecting artifacts..."
|
|
|
|
mkdir -p artifacts/${{ matrix.target }}
|
|
|
|
# Find and copy .ipk files
|
|
find sdk/bin -name "luci-app-*.ipk" -exec cp {} artifacts/${{ matrix.target }}/ \; 2>/dev/null || true
|
|
|
|
# Also collect any SecuBox related packages
|
|
find sdk/bin -name "*secubox*.ipk" -exec cp {} artifacts/${{ matrix.target }}/ \; 2>/dev/null || true
|
|
|
|
# Count
|
|
PKG_COUNT=$(find artifacts/${{ matrix.target }} -name "*.ipk" 2>/dev/null | wc -l)
|
|
echo "pkg_count=$PKG_COUNT" >> $GITHUB_OUTPUT
|
|
|
|
echo ""
|
|
echo "📋 Built packages for ${{ matrix.target }}:"
|
|
ls -la artifacts/${{ matrix.target }}/ 2>/dev/null || echo "No packages"
|
|
|
|
# Create checksums
|
|
if [[ $PKG_COUNT -gt 0 ]]; then
|
|
cd artifacts/${{ matrix.target }}
|
|
sha256sum *.ipk > SHA256SUMS
|
|
fi
|
|
|
|
echo ""
|
|
echo "📦 Total: $PKG_COUNT packages"
|
|
|
|
- name: Upload artifacts
|
|
uses: actions/upload-artifact@v4
|
|
if: steps.collect.outputs.pkg_count > 0
|
|
with:
|
|
name: packages-${{ matrix.target }}
|
|
path: artifacts/${{ matrix.target }}/
|
|
retention-days: 30
|
|
|
|
- name: Build Summary
|
|
run: |
|
|
PKG_COUNT="${{ steps.collect.outputs.pkg_count }}"
|
|
|
|
echo "## 📦 Build Results: ${{ matrix.target }}" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Property | Value |" >> $GITHUB_STEP_SUMMARY
|
|
echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Target | ${{ matrix.description }} |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Architecture | ${{ matrix.arch }} |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| SDK Path | ${{ matrix.sdk_path }} |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Packages Built | $PKG_COUNT |" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
if [[ "$PKG_COUNT" -gt 0 ]]; then
|
|
echo "### Built Packages" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
ls artifacts/${{ matrix.target }}/*.ipk 2>/dev/null | xargs -I{} basename {} | sort
|
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
|
|
# ============================================
|
|
# Publish combined artifacts (always)
|
|
# ============================================
|
|
publish-artifacts:
|
|
needs: [setup, build]
|
|
runs-on: ubuntu-latest
|
|
if: always() && needs.build.result == 'success'
|
|
|
|
steps:
|
|
- name: Download all artifacts
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
path: packages
|
|
pattern: packages-*
|
|
|
|
- name: Create combined archives
|
|
run: |
|
|
VERSION="${{ needs.setup.outputs.version }}"
|
|
PACKAGE_NAME="${{ github.event.inputs.package_name }}"
|
|
mkdir -p release
|
|
|
|
# Determine prefix for archives
|
|
if [[ -n "$PACKAGE_NAME" ]]; then
|
|
PREFIX="${PACKAGE_NAME}"
|
|
echo "📁 Creating archives for single package: $PACKAGE_NAME..."
|
|
else
|
|
PREFIX="secubox"
|
|
echo "📁 Creating combined archives..."
|
|
fi
|
|
|
|
# Per-architecture archives
|
|
for dir in packages/packages-*/; do
|
|
[[ -d "$dir" ]] || continue
|
|
|
|
ARCH=$(basename "$dir" | sed 's/packages-//')
|
|
echo "📦 $ARCH"
|
|
|
|
# Copy .ipk files to release
|
|
mkdir -p "release/${ARCH}"
|
|
cp "$dir"/*.ipk "release/${ARCH}/" 2>/dev/null || true
|
|
|
|
# Create archive
|
|
if ls "release/${ARCH}"/*.ipk >/dev/null 2>&1; then
|
|
tar -czf "release/${PREFIX}-${VERSION}-${ARCH}.tar.gz" -C "release/${ARCH}" .
|
|
fi
|
|
done
|
|
|
|
# Create all-in-one archive
|
|
tar -czf "release/${PREFIX}-${VERSION}-all-architectures.tar.gz" -C packages .
|
|
|
|
# Checksums
|
|
cd release
|
|
sha256sum *.tar.gz > SHA256SUMS 2>/dev/null || true
|
|
|
|
echo ""
|
|
echo "📋 Release contents:"
|
|
ls -la
|
|
|
|
echo ""
|
|
echo "📊 Package count per architecture:"
|
|
for dir in */; do
|
|
[[ -d "$dir" ]] || continue
|
|
COUNT=$(ls "$dir"/*.ipk 2>/dev/null | wc -l)
|
|
echo " ${dir%/}: $COUNT packages"
|
|
done
|
|
|
|
- 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
|
|
|
|
- name: Upload individual .ipk files
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: secubox-all-ipk-${{ needs.setup.outputs.version }}
|
|
path: release/*/*.ipk
|
|
retention-days: 90
|
|
|
|
# ============================================
|
|
# Create GitHub Release (on tags or manual)
|
|
# ============================================
|
|
release:
|
|
needs: [setup, build, publish-artifacts]
|
|
runs-on: ubuntu-latest
|
|
if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch'
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Download release artifact
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: secubox-release-${{ needs.setup.outputs.version }}
|
|
path: release
|
|
|
|
- name: Download all .ipk files
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: secubox-all-ipk-${{ needs.setup.outputs.version }}
|
|
path: ipk-files
|
|
continue-on-error: true
|
|
|
|
- name: List packages
|
|
id: list-packages
|
|
run: |
|
|
echo "📦 Packages in release:"
|
|
find . -name "*.ipk" -exec basename {} \; | sort -u
|
|
|
|
# Count unique packages
|
|
PKG_LIST=$(find . -name "*.ipk" -exec basename {} \; | sort -u | sed 's/_[0-9].*//g' | sort -u | tr '\n' ', ' | sed 's/,$//')
|
|
echo "packages=$PKG_LIST" >> $GITHUB_OUTPUT
|
|
|
|
- name: Create GitHub Release
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
name: ${{ github.event.inputs.package_name && format('{0} {1}', github.event.inputs.package_name, needs.setup.outputs.version) || format('SecuBox {0}', needs.setup.outputs.version) }}
|
|
tag_name: ${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || format('v{0}', needs.setup.outputs.version) }}
|
|
body: |
|
|
## 📦 ${{ github.event.inputs.package_name && format('{0} Package', github.event.inputs.package_name) || 'SecuBox Packages' }} v${{ needs.setup.outputs.version }}
|
|
|
|
Pre-built LuCI package${{ github.event.inputs.package_name && '' || 's' }} for OpenWrt ${{ env.OPENWRT_VERSION }}.
|
|
|
|
${{ github.event.inputs.package_name && format('🎯 **Single package build**: {0}', github.event.inputs.package_name) || '' }}
|
|
|
|
### ✅ Built Packages
|
|
|
|
${{ steps.list-packages.outputs.packages }}
|
|
|
|
### 📥 Installation
|
|
|
|
```bash
|
|
# Download the archive for your architecture
|
|
# Extract and upload .ipk files to router
|
|
|
|
opkg update
|
|
opkg install /tmp/luci-app-*.ipk
|
|
|
|
# Restart services
|
|
/etc/init.d/rpcd restart
|
|
```
|
|
|
|
### 🏗️ Supported Architectures
|
|
|
|
- `x86-64` - PC, VMs, Proxmox
|
|
- `aarch64-cortex-a72` - MOCHAbin, RPi4
|
|
- `aarch64-cortex-a53` - ESPRESSObin
|
|
- `aarch64-generic` - Generic ARM64
|
|
- `mips-24kc` - TP-Link, ath79
|
|
- `mipsel-24kc` - Xiaomi, GL.iNet
|
|
- `mediatek-filogic` - MT7981/MT7986
|
|
|
|
### 🔗 Links
|
|
|
|
- [SecuBox Website](https://secubox.cybermood.eu)
|
|
- [CyberMind.fr](https://cybermind.fr)
|
|
files: |
|
|
release/*.tar.gz
|
|
release/SHA256SUMS
|
|
draft: false
|
|
prerelease: ${{ github.event_name == 'workflow_dispatch' }}
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
# ============================================
|
|
# Final Summary
|
|
# ============================================
|
|
summary:
|
|
needs: [setup, build]
|
|
runs-on: ubuntu-latest
|
|
if: always()
|
|
|
|
steps:
|
|
- name: Download artifacts
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
path: packages
|
|
pattern: packages-*
|
|
continue-on-error: true
|
|
|
|
- name: Generate summary
|
|
run: |
|
|
PACKAGE_NAME="${{ github.event.inputs.package_name }}"
|
|
|
|
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 "| Triggered by | ${{ github.event_name }} |" >> $GITHUB_STEP_SUMMARY
|
|
|
|
if [[ -n "$PACKAGE_NAME" ]]; then
|
|
echo "| Package | 🎯 $PACKAGE_NAME (single package build) |" >> $GITHUB_STEP_SUMMARY
|
|
else
|
|
echo "| Package | 📦 All packages |" >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
|
|
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
|
|
|
|
TOTAL=0
|
|
|
|
for dir in packages/packages-*/; do
|
|
if [[ -d "$dir" ]]; then
|
|
ARCH=$(basename "$dir" | sed 's/packages-//')
|
|
COUNT=$(find "$dir" -name "*.ipk" 2>/dev/null | wc -l)
|
|
TOTAL=$((TOTAL + COUNT))
|
|
|
|
if [[ $COUNT -gt 0 ]]; then
|
|
echo "| $ARCH | ✅ Success | $COUNT |" >> $GITHUB_STEP_SUMMARY
|
|
else
|
|
echo "| $ARCH | ⚠️ Empty | 0 |" >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
fi
|
|
done
|
|
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "**Total packages built: $TOTAL**" >> $GITHUB_STEP_SUMMARY
|