Enhanced the firmware build workflow with better diagnostics: 1. Added directory listing before artifact collection to show what was built 2. Changed collection strategy to copy all files from target dir (excluding metadata like .ipk, .manifest, .json, .buildinfo) 3. Added warnings when no firmware images are found 4. Added file listing after successful builds to verify output 5. Show file sizes during collection This should help identify why firmware artifacts might be missing: - Shows exactly what files were generated - Provides clear warnings if target directory is empty - Helps debug firmware build issues The new approach copies all firmware image files regardless of extension, which is more robust than pattern matching specific file types.
803 lines
34 KiB
YAML
803 lines
34 KiB
YAML
name: Build SecuBox Images (GlobalScale)
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
device:
|
|
description: 'Target device'
|
|
required: true
|
|
type: choice
|
|
options:
|
|
- espressobin-v7
|
|
- espressobin-ultra
|
|
- sheeva64
|
|
- sheeva64-wifi
|
|
- mochabin
|
|
- all
|
|
openwrt_version:
|
|
description: 'OpenWrt version'
|
|
required: true
|
|
default: '23.05.5'
|
|
type: choice
|
|
options:
|
|
- '23.05.5'
|
|
- '23.05.4'
|
|
- 'SNAPSHOT'
|
|
include_secubox:
|
|
description: 'Include SecuBox packages'
|
|
required: true
|
|
type: boolean
|
|
default: true
|
|
|
|
env:
|
|
OPENWRT_VERSION: ${{ github.event.inputs.openwrt_version }}
|
|
|
|
permissions:
|
|
contents: write
|
|
|
|
jobs:
|
|
# ============================================
|
|
# Generate build matrix based on input
|
|
# ============================================
|
|
setup:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
|
steps:
|
|
- name: Set build matrix
|
|
id: set-matrix
|
|
run: |
|
|
DEVICE="${{ github.event.inputs.device }}"
|
|
|
|
# Define all devices in a file to avoid heredoc issues
|
|
cat > /tmp/devices.json << 'DEVICES_EOF'
|
|
[
|
|
{
|
|
"device": "espressobin-v7",
|
|
"target": "mvebu",
|
|
"subtarget": "cortexa53",
|
|
"profile": "globalscale_espressobin",
|
|
"description": "ESPRESSObin V7 (1-2GB DDR4)"
|
|
},
|
|
{
|
|
"device": "espressobin-ultra",
|
|
"target": "mvebu",
|
|
"subtarget": "cortexa53",
|
|
"profile": "globalscale_espressobin-ultra",
|
|
"description": "ESPRESSObin Ultra (PoE, WiFi)"
|
|
},
|
|
{
|
|
"device": "sheeva64",
|
|
"target": "mvebu",
|
|
"subtarget": "cortexa53",
|
|
"profile": "globalscale_sheeva64",
|
|
"description": "Sheeva64 (Plug computer)"
|
|
},
|
|
{
|
|
"device": "sheeva64-wifi",
|
|
"target": "mvebu",
|
|
"subtarget": "cortexa53",
|
|
"profile": "globalscale_sheeva64",
|
|
"description": "Sheeva64 WiFi (802.11ac + BT)"
|
|
},
|
|
{
|
|
"device": "mochabin",
|
|
"target": "mvebu",
|
|
"subtarget": "cortexa72",
|
|
"profile": "globalscale_mochabin",
|
|
"description": "MOCHAbin (Quad-core A72, 10G)"
|
|
}
|
|
]
|
|
DEVICES_EOF
|
|
|
|
# Filter based on input
|
|
if [[ "$DEVICE" == "all" ]]; then
|
|
MATRIX=$(jq -c '{"include": .}' /tmp/devices.json)
|
|
else
|
|
MATRIX=$(jq -c --arg dev "$DEVICE" '{"include": [.[] | select(.device == $dev)]}' /tmp/devices.json)
|
|
fi
|
|
|
|
# Use delimiter for multiline output
|
|
echo "matrix<<EOF" >> $GITHUB_OUTPUT
|
|
echo "$MATRIX" >> $GITHUB_OUTPUT
|
|
echo "EOF" >> $GITHUB_OUTPUT
|
|
|
|
echo "📋 Build matrix:"
|
|
echo "$MATRIX" | jq '.'
|
|
|
|
# ============================================
|
|
# Build firmware images for GlobalScale devices
|
|
# ============================================
|
|
build-image:
|
|
needs: setup
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
fail-fast: false
|
|
matrix: ${{ fromJson(needs.setup.outputs.matrix) }}
|
|
|
|
name: ${{ matrix.description }}
|
|
|
|
steps:
|
|
- name: Checkout SecuBox packages
|
|
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
|
|
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 qemu-utils
|
|
|
|
- name: Clone OpenWrt
|
|
run: |
|
|
if [[ "${{ env.OPENWRT_VERSION }}" == "SNAPSHOT" ]]; then
|
|
git clone --depth 1 https://github.com/openwrt/openwrt.git openwrt
|
|
else
|
|
git clone --depth 1 --branch v${{ env.OPENWRT_VERSION }} \
|
|
https://github.com/openwrt/openwrt.git openwrt
|
|
fi
|
|
|
|
- name: Update feeds
|
|
run: |
|
|
cd openwrt
|
|
|
|
# Remove unwanted feeds from feeds.conf.default BEFORE updating feeds
|
|
if [[ -f "feeds.conf.default" ]]; then
|
|
sed -i '/telephony/d' feeds.conf.default
|
|
sed -i '/routing/d' feeds.conf.default
|
|
echo "✅ Removed telephony and routing from feeds.conf.default"
|
|
fi
|
|
|
|
./scripts/feeds update -a
|
|
./scripts/feeds install -a
|
|
|
|
- name: Copy SecuBox packages
|
|
if: ${{ github.event.inputs.include_secubox == 'true' }}
|
|
run: |
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "📦 COPYING SECUBOX PACKAGES"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo ""
|
|
|
|
mkdir -p openwrt/package/secubox
|
|
|
|
PKG_COUNT=0
|
|
for pkg in luci-app-*/; do
|
|
if [[ -d "$pkg" ]]; then
|
|
PKG_NAME=$(basename "$pkg")
|
|
echo " ✅ $PKG_NAME"
|
|
cp -r "$pkg" openwrt/package/secubox/
|
|
PKG_COUNT=$((PKG_COUNT + 1))
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo "📊 Total: $PKG_COUNT SecuBox packages copied"
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
|
|
- name: Generate SecuBox config
|
|
run: |
|
|
cd openwrt
|
|
|
|
# Base configuration
|
|
cat > .config << EOF
|
|
# Target
|
|
CONFIG_TARGET_${{ matrix.target }}=y
|
|
CONFIG_TARGET_${{ matrix.target }}_${{ matrix.subtarget }}=y
|
|
CONFIG_TARGET_${{ matrix.target }}_${{ matrix.subtarget }}_DEVICE_${{ matrix.profile }}=y
|
|
|
|
# Image settings
|
|
CONFIG_TARGET_ROOTFS_SQUASHFS=y
|
|
CONFIG_TARGET_ROOTFS_EXT4FS=y
|
|
CONFIG_TARGET_KERNEL_PARTSIZE=32
|
|
CONFIG_TARGET_ROOTFS_PARTSIZE=512
|
|
|
|
# Base packages
|
|
CONFIG_PACKAGE_luci=y
|
|
CONFIG_PACKAGE_luci-ssl=y
|
|
CONFIG_PACKAGE_luci-app-opkg=y
|
|
CONFIG_PACKAGE_luci-theme-openwrt-2020=y
|
|
|
|
# Networking essentials
|
|
CONFIG_PACKAGE_curl=y
|
|
CONFIG_PACKAGE_wget-ssl=y
|
|
CONFIG_PACKAGE_iptables=y
|
|
CONFIG_PACKAGE_ip6tables=y
|
|
CONFIG_PACKAGE_kmod-nft-core=y
|
|
|
|
# USB support
|
|
CONFIG_PACKAGE_kmod-usb-core=y
|
|
CONFIG_PACKAGE_kmod-usb3=y
|
|
CONFIG_PACKAGE_kmod-usb-storage=y
|
|
|
|
# Filesystem
|
|
CONFIG_PACKAGE_kmod-fs-ext4=y
|
|
CONFIG_PACKAGE_kmod-fs-vfat=y
|
|
CONFIG_PACKAGE_block-mount=y
|
|
|
|
# Wireless (if applicable)
|
|
CONFIG_PACKAGE_hostapd-common=y
|
|
CONFIG_PACKAGE_wpad-basic-mbedtls=y
|
|
|
|
# Monitoring tools
|
|
CONFIG_PACKAGE_htop=y
|
|
CONFIG_PACKAGE_iftop=y
|
|
CONFIG_PACKAGE_tcpdump=y
|
|
|
|
# SSH
|
|
CONFIG_PACKAGE_openssh-sftp-server=y
|
|
EOF
|
|
|
|
- name: Add SecuBox packages to config
|
|
if: ${{ github.event.inputs.include_secubox == 'true' }}
|
|
run: |
|
|
cd openwrt
|
|
|
|
# CrowdSec
|
|
cat >> .config << EOF
|
|
CONFIG_PACKAGE_crowdsec=y
|
|
CONFIG_PACKAGE_crowdsec-firewall-bouncer=y
|
|
CONFIG_PACKAGE_luci-app-crowdsec-dashboard=y
|
|
EOF
|
|
|
|
# Netdata
|
|
cat >> .config << EOF
|
|
CONFIG_PACKAGE_netdata=y
|
|
CONFIG_PACKAGE_luci-app-netdata-dashboard=y
|
|
EOF
|
|
|
|
# Netifyd
|
|
cat >> .config << EOF
|
|
CONFIG_PACKAGE_netifyd=y
|
|
CONFIG_PACKAGE_luci-app-netifyd-dashboard=y
|
|
EOF
|
|
|
|
# WireGuard
|
|
cat >> .config << EOF
|
|
CONFIG_PACKAGE_wireguard-tools=y
|
|
CONFIG_PACKAGE_kmod-wireguard=y
|
|
CONFIG_PACKAGE_luci-app-wireguard-dashboard=y
|
|
CONFIG_PACKAGE_qrencode=y
|
|
EOF
|
|
|
|
# SecuBox core
|
|
cat >> .config << EOF
|
|
CONFIG_PACKAGE_luci-app-network-modes=y
|
|
CONFIG_PACKAGE_luci-app-client-guardian=y
|
|
CONFIG_PACKAGE_luci-app-system-hub=y
|
|
EOF
|
|
|
|
- name: Add device-specific packages
|
|
run: |
|
|
cd openwrt
|
|
|
|
case "${{ matrix.device }}" in
|
|
mochabin)
|
|
# 10G networking, more RAM
|
|
cat >> .config << EOF
|
|
CONFIG_PACKAGE_kmod-sfp=y
|
|
CONFIG_PACKAGE_kmod-phy-marvell-10g=y
|
|
CONFIG_PACKAGE_prometheus-node-exporter-lua=y
|
|
EOF
|
|
;;
|
|
|
|
espressobin-ultra|sheeva64-wifi)
|
|
# WiFi support
|
|
cat >> .config << EOF
|
|
CONFIG_PACKAGE_kmod-mt76=y
|
|
CONFIG_PACKAGE_kmod-mac80211=y
|
|
EOF
|
|
;;
|
|
|
|
sheeva64*)
|
|
# Minimal for plug computer
|
|
cat >> .config << EOF
|
|
# Optimized for plug form factor
|
|
CONFIG_PACKAGE_kmod-ledtrig-heartbeat=y
|
|
EOF
|
|
;;
|
|
esac
|
|
|
|
- name: Make defconfig
|
|
run: |
|
|
cd openwrt
|
|
|
|
# Final cleanup of unwanted feeds (if somehow they still got created)
|
|
rm -f feeds/telephony.index feeds/routing.index 2>/dev/null || true
|
|
rm -rf feeds/telephony feeds/routing 2>/dev/null || true
|
|
|
|
make defconfig
|
|
|
|
- name: Download packages
|
|
run: |
|
|
cd openwrt
|
|
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "📥 DOWNLOADING PACKAGES"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo ""
|
|
echo "Downloading source packages and dependencies..."
|
|
echo "This may take several minutes depending on network speed."
|
|
echo ""
|
|
|
|
if make download -j$(nproc) V=s; then
|
|
echo ""
|
|
echo "✅ All packages downloaded successfully"
|
|
else
|
|
echo ""
|
|
echo "⚠️ Parallel download failed, retrying with single thread..."
|
|
make download -j1 V=s
|
|
fi
|
|
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
|
|
- name: Build firmware
|
|
run: |
|
|
cd openwrt
|
|
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "🔨 BUILDING FIRMWARE"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo ""
|
|
echo "📋 Build Information:"
|
|
echo " • Device: ${{ matrix.description }}"
|
|
echo " • Profile: ${{ matrix.profile }}"
|
|
echo " • Target: ${{ matrix.target }}/${{ matrix.subtarget }}"
|
|
echo " • OpenWrt: ${{ env.OPENWRT_VERSION }}"
|
|
echo " • CPU Cores: $(nproc)"
|
|
echo " • Estimated Time: 1-2 hours"
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo ""
|
|
|
|
START_TIME=$(date +%s)
|
|
|
|
if make -j$(nproc) V=s 2>&1 | tee build.log; then
|
|
END_TIME=$(date +%s)
|
|
DURATION=$((END_TIME - START_TIME))
|
|
MINUTES=$((DURATION / 60))
|
|
SECONDS=$((DURATION % 60))
|
|
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "✅ BUILD SUCCESSFUL"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo ""
|
|
echo "⏱️ Build Time: ${MINUTES}m ${SECONDS}s"
|
|
echo "📁 Output: bin/targets/${{ matrix.target }}/${{ matrix.subtarget }}/"
|
|
echo ""
|
|
echo "📦 Generated Files:"
|
|
ls -lh "bin/targets/${{ matrix.target }}/${{ matrix.subtarget }}/" 2>/dev/null | grep -v "^total" | grep -v "^d" | head -20 || echo " (no files found)"
|
|
echo ""
|
|
else
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "⚠️ PARALLEL BUILD FAILED - RETRYING WITH SINGLE THREAD"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo ""
|
|
echo "This is often caused by race conditions in parallel builds."
|
|
echo "Retrying with -j1 (single thread) for better stability..."
|
|
echo ""
|
|
|
|
if make -j1 V=s 2>&1 | tee build-retry.log; then
|
|
END_TIME=$(date +%s)
|
|
DURATION=$((END_TIME - START_TIME))
|
|
MINUTES=$((DURATION / 60))
|
|
SECONDS=$((DURATION % 60))
|
|
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "✅ BUILD SUCCESSFUL (after retry)"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo ""
|
|
echo "⏱️ Total Build Time: ${MINUTES}m ${SECONDS}s"
|
|
echo "📁 Output: bin/targets/${{ matrix.target }}/${{ matrix.subtarget }}/"
|
|
echo ""
|
|
echo "📦 Generated Files:"
|
|
ls -lh "bin/targets/${{ matrix.target }}/${{ matrix.subtarget }}/" 2>/dev/null | grep -v "^total" | grep -v "^d" | head -20 || echo " (no files found)"
|
|
echo ""
|
|
else
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "❌ BUILD FAILED"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo ""
|
|
echo "📋 Last 50 lines of build log:"
|
|
echo ""
|
|
tail -50 build-retry.log
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
- name: Prepare artifacts
|
|
id: prepare
|
|
run: |
|
|
mkdir -p artifacts
|
|
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "📦 Collecting Firmware Images"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
|
|
# List what was actually built
|
|
echo "🔍 Searching for firmware images in:"
|
|
echo " openwrt/bin/targets/${{ matrix.target }}/${{ matrix.subtarget }}/"
|
|
echo ""
|
|
|
|
if [[ -d "openwrt/bin/targets/${{ matrix.target }}/${{ matrix.subtarget }}" ]]; then
|
|
echo "📂 Directory contents:"
|
|
ls -lh "openwrt/bin/targets/${{ matrix.target }}/${{ matrix.subtarget }}/" | grep -v "^total" | grep -v "^d" || echo " (empty)"
|
|
echo ""
|
|
fi
|
|
|
|
# Copy firmware images (all common patterns)
|
|
IMG_COUNT=0
|
|
TARGET_DIR="openwrt/bin/targets/${{ matrix.target }}/${{ matrix.subtarget }}"
|
|
|
|
if [[ -d "$TARGET_DIR" ]]; then
|
|
# Find all firmware image files (not directories, not packages)
|
|
while IFS= read -r file; do
|
|
if [[ -f "$file" ]]; then
|
|
# Skip certain files
|
|
case "$(basename "$file")" in
|
|
*.ipk|*.manifest|*.json|sha256sums|*.buildinfo|packages)
|
|
continue
|
|
;;
|
|
*)
|
|
cp "$file" artifacts/
|
|
echo " ✅ $(basename "$file") ($(du -h "$file" | cut -f1))"
|
|
IMG_COUNT=$((IMG_COUNT + 1))
|
|
;;
|
|
esac
|
|
fi
|
|
done < <(find "$TARGET_DIR" -maxdepth 1 -type f 2>/dev/null)
|
|
else
|
|
echo "⚠️ Warning: Target directory not found: $TARGET_DIR"
|
|
fi
|
|
|
|
if [[ $IMG_COUNT -eq 0 ]]; then
|
|
echo ""
|
|
echo "⚠️ WARNING: No firmware images found!"
|
|
echo "This could indicate a build failure or unexpected output location."
|
|
fi
|
|
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "📦 Collecting SecuBox Packages"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
|
|
# Copy packages
|
|
mkdir -p artifacts/packages
|
|
PKG_COUNT=0
|
|
for pattern in "luci-app-*secubox*.ipk" "luci-app-*dashboard*.ipk" "luci-app-*guardian*.ipk" "luci-app-*modes*.ipk" "luci-app-*hub*.ipk"; do
|
|
while IFS= read -r file; do
|
|
if [[ -f "$file" ]]; then
|
|
cp "$file" artifacts/packages/
|
|
echo " ✅ $(basename "$file")"
|
|
PKG_COUNT=$((PKG_COUNT + 1))
|
|
fi
|
|
done < <(find openwrt/bin/packages -name "$pattern" 2>/dev/null)
|
|
done
|
|
|
|
# Generate checksums
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "🔐 Generating Checksums"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
|
|
cd artifacts
|
|
sha256sum *.* > SHA256SUMS 2>/dev/null || true
|
|
if [[ -d packages ]] && [[ -n "$(ls -A packages)" ]]; then
|
|
(cd packages && sha256sum *.ipk > SHA256SUMS 2>/dev/null || true)
|
|
fi
|
|
|
|
# Create info file
|
|
cat > BUILD_INFO.txt << EOF
|
|
SecuBox Firmware Build
|
|
=======================
|
|
Device: ${{ matrix.description }}
|
|
Profile: ${{ matrix.profile }}
|
|
Target: ${{ matrix.target }}/${{ matrix.subtarget }}
|
|
OpenWrt: ${{ env.OPENWRT_VERSION }}
|
|
SecuBox: ${{ github.event.inputs.include_secubox }}
|
|
Built: $(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
Commit: ${{ github.sha }}
|
|
|
|
Firmware Images: $IMG_COUNT
|
|
SecuBox Packages: $PKG_COUNT
|
|
EOF
|
|
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "📋 Artifact Summary"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "Device: ${{ matrix.description }}"
|
|
echo "Firmware images: $IMG_COUNT files"
|
|
echo "SecuBox packages: $PKG_COUNT files"
|
|
echo ""
|
|
echo "📁 Contents:"
|
|
ls -lh
|
|
|
|
# Export counts for summary
|
|
echo "img_count=$IMG_COUNT" >> $GITHUB_OUTPUT
|
|
echo "pkg_count=$PKG_COUNT" >> $GITHUB_OUTPUT
|
|
|
|
- name: Upload artifacts
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: secubox-${{ matrix.device }}-${{ env.OPENWRT_VERSION }}
|
|
path: artifacts/
|
|
retention-days: 30
|
|
|
|
- name: Generate build summary
|
|
if: always()
|
|
run: |
|
|
echo "# 🎯 Build Complete: ${{ matrix.description }}" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
echo "## 📊 Build Information" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Property | Value |" >> $GITHUB_STEP_SUMMARY
|
|
echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Device | ${{ matrix.description }} |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Profile | \`${{ matrix.profile }}\` |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Target | ${{ matrix.target }}/${{ matrix.subtarget }} |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| OpenWrt Version | ${{ env.OPENWRT_VERSION }} |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| SecuBox Included | ${{ github.event.inputs.include_secubox }} |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Build Time | $(date -u +%Y-%m-%d\ %H:%M:%S\ UTC) |" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
echo "## 📦 Generated Artifacts" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Type | Count | Files |" >> $GITHUB_STEP_SUMMARY
|
|
echo "|------|-------|-------|" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Firmware Images | ${{ steps.prepare.outputs.img_count }} | \`*.img.gz\`, \`*sysupgrade*\`, \`*factory*\` |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| SecuBox Packages | ${{ steps.prepare.outputs.pkg_count }} | \`luci-app-*.ipk\` |" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
echo "## 📥 Download Artifacts" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "**Artifact Name:** \`secubox-${{ matrix.device }}-${{ env.OPENWRT_VERSION }}\`" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "To download:" >> $GITHUB_STEP_SUMMARY
|
|
echo "1. Go to the **Summary** page of this workflow run" >> $GITHUB_STEP_SUMMARY
|
|
echo "2. Scroll to the **Artifacts** section at the bottom" >> $GITHUB_STEP_SUMMARY
|
|
echo "3. Click on \`secubox-${{ matrix.device }}-${{ env.OPENWRT_VERSION }}\` to download" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
if [[ -f artifacts/BUILD_INFO.txt ]]; then
|
|
echo "## 📄 Build Details" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
cat artifacts/BUILD_INFO.txt >> $GITHUB_STEP_SUMMARY
|
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
|
|
echo "## 📋 Firmware Files" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
ls -lh artifacts/*.{img.gz,bin} 2>/dev/null | awk '{print $9, "(" $5 ")"}' | sed 's|artifacts/||' || echo "No firmware images found"
|
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
if [[ -d artifacts/packages ]] && [[ -n "$(ls -A artifacts/packages 2>/dev/null)" ]]; then
|
|
echo "## 📦 SecuBox Packages" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
ls -1 artifacts/packages/*.ipk 2>/dev/null | xargs -I{} basename {} || echo "No packages"
|
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
|
|
# ============================================
|
|
# Create combined release for all devices
|
|
# ============================================
|
|
release:
|
|
needs: [setup, build-image]
|
|
runs-on: ubuntu-latest
|
|
if: github.event.inputs.device == 'all'
|
|
|
|
steps:
|
|
- name: Download all artifacts
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
path: firmware
|
|
pattern: secubox-*
|
|
|
|
- name: Organize release
|
|
run: |
|
|
mkdir -p release
|
|
|
|
for device_dir in firmware/secubox-*/; do
|
|
DEVICE=$(basename "$device_dir" | sed 's/secubox-//' | sed "s/-${{ env.OPENWRT_VERSION }}//")
|
|
echo "📦 Processing $DEVICE..."
|
|
|
|
# Create device archive
|
|
tar -czf "release/secubox-firmware-${DEVICE}.tar.gz" -C "$device_dir" .
|
|
done
|
|
|
|
# Global checksums
|
|
cd release
|
|
sha256sum *.tar.gz > SHA256SUMS
|
|
|
|
# Release notes
|
|
cat > RELEASE_NOTES.md << 'EOF'
|
|
# SecuBox Firmware Images
|
|
|
|
Pre-built firmware images for GlobalScale devices with SecuBox modules pre-installed.
|
|
|
|
## Included Devices
|
|
|
|
| Device | SoC | RAM | Description |
|
|
|--------|-----|-----|-------------|
|
|
| ESPRESSObin V7 | Armada 3720 | 1-2GB | Entry-level |
|
|
| ESPRESSObin Ultra | Armada 3720 | 1-2GB | WiFi + PoE |
|
|
| Sheeva64 | Armada 3720 | 1GB | Plug computer |
|
|
| MOCHAbin | Armada 7040 | 4-8GB | Quad-core + 10G |
|
|
|
|
## Pre-installed SecuBox Modules
|
|
|
|
- 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
|
|
|
|
## Installation
|
|
|
|
1. Download the appropriate firmware for your device
|
|
2. Flash using OpenWrt sysupgrade or manufacturer tools
|
|
3. Access LuCI at http://192.168.1.1
|
|
4. Navigate to Services → SecuBox
|
|
|
|
## Support
|
|
|
|
- [Documentation](https://cybermind.fr/docs/secubox)
|
|
- [CyberMind.fr](https://cybermind.fr)
|
|
EOF
|
|
|
|
- name: Create release
|
|
if: github.ref == 'refs/heads/main'
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
name: "SecuBox Firmware ${{ env.OPENWRT_VERSION }}"
|
|
tag_name: "firmware-${{ env.OPENWRT_VERSION }}-${{ github.run_number }}"
|
|
body_path: release/RELEASE_NOTES.md
|
|
files: |
|
|
release/*.tar.gz
|
|
release/SHA256SUMS
|
|
draft: true
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
# ============================================
|
|
# Final summary of all builds
|
|
# ============================================
|
|
summary:
|
|
needs: [setup, build-image]
|
|
runs-on: ubuntu-latest
|
|
if: always()
|
|
|
|
steps:
|
|
- name: Download all artifacts
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
path: all-artifacts
|
|
pattern: secubox-*
|
|
continue-on-error: true
|
|
|
|
- name: Generate final summary
|
|
run: |
|
|
echo "# 🏗️ SecuBox Firmware Build Summary" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
echo "## ⚙️ Build Configuration" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Property | Value |" >> $GITHUB_STEP_SUMMARY
|
|
echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY
|
|
echo "| OpenWrt Version | ${{ env.OPENWRT_VERSION }} |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| SecuBox Included | ${{ github.event.inputs.include_secubox }} |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Target Device | ${{ github.event.inputs.device }} |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Workflow Run | #${{ github.run_number }} |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Triggered by | ${{ github.event_name }} |" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
echo "## 📦 Generated Artifacts" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
if [[ -d all-artifacts ]]; then
|
|
ARTIFACT_COUNT=$(find all-artifacts -type d -mindepth 1 -maxdepth 1 | wc -l)
|
|
|
|
if [[ $ARTIFACT_COUNT -gt 0 ]]; then
|
|
echo "✅ **$ARTIFACT_COUNT artifact(s) available for download**" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Device | Artifact Name | Firmware Images | Packages |" >> $GITHUB_STEP_SUMMARY
|
|
echo "|--------|---------------|-----------------|----------|" >> $GITHUB_STEP_SUMMARY
|
|
|
|
for artifact_dir in all-artifacts/secubox-*/; do
|
|
if [[ -d "$artifact_dir" ]]; then
|
|
ARTIFACT_NAME=$(basename "$artifact_dir")
|
|
DEVICE=$(echo "$ARTIFACT_NAME" | sed 's/secubox-//' | sed "s/-${{ env.OPENWRT_VERSION }}//")
|
|
|
|
# Count files
|
|
IMG_COUNT=$(find "$artifact_dir" -maxdepth 1 \( -name "*.img.gz" -o -name "*.bin" -o -name "*sysupgrade*" -o -name "*factory*" \) 2>/dev/null | wc -l)
|
|
PKG_COUNT=$(find "$artifact_dir/packages" -name "*.ipk" 2>/dev/null | wc -l)
|
|
|
|
echo "| $DEVICE | \`$ARTIFACT_NAME\` | $IMG_COUNT | $PKG_COUNT |" >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
done
|
|
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "### 📥 How to Download" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "1. Navigate to the **Summary** tab of this workflow run" >> $GITHUB_STEP_SUMMARY
|
|
echo "2. Scroll to the **Artifacts** section at the bottom of the page" >> $GITHUB_STEP_SUMMARY
|
|
echo "3. Click on the artifact name to download the ZIP file" >> $GITHUB_STEP_SUMMARY
|
|
echo "4. Extract the ZIP to access firmware images and packages" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
echo "### 📋 Artifact Contents" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "Each artifact contains:" >> $GITHUB_STEP_SUMMARY
|
|
echo "- **Firmware images**: \`*.img.gz\`, \`*sysupgrade.bin\`, \`*factory.bin\`" >> $GITHUB_STEP_SUMMARY
|
|
echo "- **SecuBox packages**: \`luci-app-*.ipk\` (in \`packages/\` subdirectory)" >> $GITHUB_STEP_SUMMARY
|
|
echo "- **Checksums**: \`SHA256SUMS\` for verification" >> $GITHUB_STEP_SUMMARY
|
|
echo "- **Build info**: \`BUILD_INFO.txt\` with build details" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
# List detailed contents of first artifact as example
|
|
FIRST_ARTIFACT=$(find all-artifacts -type d -mindepth 1 -maxdepth 1 | head -1)
|
|
if [[ -n "$FIRST_ARTIFACT" ]]; then
|
|
echo "### 📄 Example: $(basename "$FIRST_ARTIFACT")" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
echo "Firmware Images:" >> $GITHUB_STEP_SUMMARY
|
|
find "$FIRST_ARTIFACT" -maxdepth 1 -type f \( -name "*.img.gz" -o -name "*.bin" \) -exec basename {} \; 2>/dev/null | sort || echo " (none)"
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
if [[ -d "$FIRST_ARTIFACT/packages" ]]; then
|
|
echo "SecuBox Packages:" >> $GITHUB_STEP_SUMMARY
|
|
find "$FIRST_ARTIFACT/packages" -name "*.ipk" -exec basename {} \; 2>/dev/null | sort || echo " (none)"
|
|
fi
|
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
|
|
echo "### 🔐 Verification" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "After downloading, verify file integrity:" >> $GITHUB_STEP_SUMMARY
|
|
echo '```bash' >> $GITHUB_STEP_SUMMARY
|
|
echo "# Extract artifact" >> $GITHUB_STEP_SUMMARY
|
|
echo "unzip secubox-*.zip" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "# Verify checksums" >> $GITHUB_STEP_SUMMARY
|
|
echo "sha256sum -c SHA256SUMS" >> $GITHUB_STEP_SUMMARY
|
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
|
|
else
|
|
echo "⚠️ **No artifacts were generated**" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "Check the build logs above for errors." >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
else
|
|
echo "⚠️ **No artifacts found**" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "This may indicate that all builds failed. Check individual job logs for details." >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "---" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "📚 For installation instructions, see the [SecuBox documentation](https://github.com/gkerma/secubox)" >> $GITHUB_STEP_SUMMARY
|