- Add ninja-build to package build workflow (build-openwrt-packages.yml) - Add ninja-build to image build workflow (build-secubox-images.yml) - Update secubox-tools/README.md with ninja-build dependency - Update secubox-tools/local-build.sh dependency check and install instructions - Ninja is required by OpenWrt build system for some compilation tasks This resolves missing ninja errors in GitHub Actions builds.
1031 lines
45 KiB
YAML
1031 lines
45 KiB
YAML
name: Build SecuBox Images (GlobalScale)
|
|
|
|
on:
|
|
# Manual trigger
|
|
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: '24.10.5'
|
|
type: choice
|
|
options:
|
|
- '25.12.0-rc1'
|
|
- '24.10.5'
|
|
- '23.05.5'
|
|
- '23.05.4'
|
|
- 'SNAPSHOT'
|
|
include_secubox:
|
|
description: 'Include SecuBox packages'
|
|
required: true
|
|
type: boolean
|
|
default: true
|
|
|
|
# Automatic trigger on version tags
|
|
push:
|
|
tags:
|
|
- 'v*.*.*'
|
|
- 'v*.*.*-*'
|
|
|
|
env:
|
|
# Use input if manual trigger, otherwise default to 24.10.5 for tag triggers
|
|
OPENWRT_VERSION: ${{ github.event.inputs.openwrt_version || '24.10.5' }}
|
|
|
|
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: |
|
|
# If triggered by tag, build all devices; otherwise use input
|
|
DEVICE="${{ github.event.inputs.device || 'all' }}"
|
|
|
|
echo "🎯 Building for device: $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 ninja-build
|
|
|
|
- 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
|
|
|
|
echo "🔄 Updating feeds..."
|
|
if ! ./scripts/feeds update -a 2>&1 | tee feed-update.log; then
|
|
echo "⚠️ Feed update had errors:"
|
|
tail -30 feed-update.log
|
|
echo "Continuing anyway..."
|
|
fi
|
|
|
|
echo "📦 Installing feeds..."
|
|
if ! ./scripts/feeds install -a 2>&1 | tee feed-install.log; then
|
|
echo "⚠️ Feed install had warnings, checking directories..."
|
|
fi
|
|
|
|
# Verify feeds were created
|
|
echo "🔍 Verifying feeds..."
|
|
for feed in packages luci; do
|
|
if [[ -d "feeds/$feed" ]]; then
|
|
FEED_SIZE=$(du -sh "feeds/$feed" 2>/dev/null | cut -f1 || echo "?")
|
|
echo " ✅ feeds/$feed ($FEED_SIZE)"
|
|
else
|
|
echo " ❌ feeds/$feed missing!"
|
|
ls -la feeds/ || echo "feeds directory doesn't exist"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
- name: Copy SecuBox packages
|
|
if: ${{ github.event.inputs.include_secubox == 'true' || github.event_name == 'push' }}
|
|
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/
|
|
|
|
# Fix Makefile include path for direct package integration
|
|
# Change from ../../luci.mk to $(TOPDIR)/feeds/luci/luci.mk
|
|
if [[ -f "openwrt/package/secubox/$PKG_NAME/Makefile" ]]; then
|
|
sed -i 's|include.*luci\.mk|include $(TOPDIR)/feeds/luci/luci.mk|' "openwrt/package/secubox/$PKG_NAME/Makefile"
|
|
echo " ✓ Fixed Makefile include path"
|
|
fi
|
|
|
|
PKG_COUNT=$((PKG_COUNT + 1))
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo "📊 Total: $PKG_COUNT SecuBox packages copied and fixed"
|
|
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 building (REQUIRED for firmware generation)
|
|
CONFIG_TARGET_MULTI_PROFILE=n
|
|
CONFIG_TARGET_ALL_PROFILES=n
|
|
CONFIG_TARGET_PER_DEVICE_ROOTFS=y
|
|
|
|
# Image settings
|
|
CONFIG_TARGET_ROOTFS_SQUASHFS=y
|
|
CONFIG_TARGET_ROOTFS_EXT4FS=y
|
|
CONFIG_TARGET_KERNEL_PARTSIZE=32
|
|
CONFIG_TARGET_ROOTFS_PARTSIZE=512
|
|
|
|
# Disable GDB in toolchain (fixes build issues)
|
|
# CONFIG_GDB is not set
|
|
CONFIG_BUILD_LOG=y
|
|
|
|
# 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' || github.event_name == 'push' }}
|
|
run: |
|
|
cd openwrt
|
|
|
|
cat >> .config << EOF
|
|
# SecuBox packages - Core
|
|
CONFIG_PACKAGE_luci-app-secubox=y
|
|
CONFIG_PACKAGE_luci-app-system-hub=y
|
|
|
|
# SecuBox packages - Security & Monitoring
|
|
CONFIG_PACKAGE_crowdsec=y
|
|
CONFIG_PACKAGE_crowdsec-firewall-bouncer=y
|
|
CONFIG_PACKAGE_luci-app-crowdsec-dashboard=y
|
|
CONFIG_PACKAGE_netdata=y
|
|
CONFIG_PACKAGE_luci-app-netdata-dashboard=y
|
|
|
|
# SecuBox packages - Network Intelligence
|
|
CONFIG_PACKAGE_netifyd=y
|
|
CONFIG_PACKAGE_luci-app-netifyd-dashboard=y
|
|
CONFIG_PACKAGE_luci-app-network-modes=y
|
|
|
|
# SecuBox packages - VPN & Access Control
|
|
CONFIG_PACKAGE_wireguard-tools=y
|
|
CONFIG_PACKAGE_kmod-wireguard=y
|
|
CONFIG_PACKAGE_luci-app-wireguard-dashboard=y
|
|
CONFIG_PACKAGE_qrencode=y
|
|
CONFIG_PACKAGE_luci-app-client-guardian=y
|
|
CONFIG_PACKAGE_luci-app-auth-guardian=y
|
|
|
|
# SecuBox packages - Bandwidth & Traffic
|
|
CONFIG_PACKAGE_luci-app-bandwidth-manager=y
|
|
CONFIG_PACKAGE_luci-app-traffic-shaper=y
|
|
CONFIG_PACKAGE_luci-app-media-flow=y
|
|
|
|
# SecuBox packages - Performance & Services
|
|
CONFIG_PACKAGE_luci-app-cdn-cache=y
|
|
CONFIG_PACKAGE_luci-app-vhost-manager=y
|
|
CONFIG_PACKAGE_luci-app-ksm-manager=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
|
|
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "⚙️ Running make defconfig"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
|
|
make defconfig
|
|
|
|
- name: Verify device profile configuration
|
|
run: |
|
|
cd openwrt
|
|
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "🔍 Verifying Device Profile Configuration"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo ""
|
|
echo "Target device: ${{ matrix.description }}"
|
|
echo "Profile: ${{ matrix.profile }}"
|
|
echo ""
|
|
|
|
# Check if device profile is properly set
|
|
if grep -q "CONFIG_TARGET_${{ matrix.target }}_${{ matrix.subtarget }}_DEVICE_${{ matrix.profile }}=y" .config; then
|
|
echo "✅ Device profile correctly configured"
|
|
else
|
|
echo "❌ ERROR: Device profile not found in .config!"
|
|
echo ""
|
|
echo "Searching for profile in available profiles..."
|
|
if [[ -f "target/${{ matrix.target }}/${{ matrix.subtarget }}/target.mk" ]]; then
|
|
echo "Available profiles in target/${{ matrix.target }}/${{ matrix.subtarget }}:"
|
|
find "target/${{ matrix.target }}/${{ matrix.subtarget }}" -name "*.mk" -exec grep -l "DEVICE_NAME" {} \; | head -10
|
|
fi
|
|
exit 1
|
|
fi
|
|
|
|
# Verify image building is enabled
|
|
echo ""
|
|
echo "Checking image generation settings..."
|
|
if grep -q "CONFIG_TARGET_ROOTFS_SQUASHFS=y" .config; then
|
|
echo "✅ SQUASHFS image generation enabled"
|
|
else
|
|
echo "⚠️ SQUASHFS not enabled"
|
|
fi
|
|
|
|
if grep -q "CONFIG_TARGET_ROOTFS_EXT4FS=y" .config; then
|
|
echo "✅ EXT4 image generation enabled"
|
|
else
|
|
echo "⚠️ EXT4 not enabled"
|
|
fi
|
|
|
|
# Show relevant config
|
|
echo ""
|
|
echo "📋 Relevant configuration:"
|
|
grep "^CONFIG_TARGET_" .config | head -20
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
|
|
- 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)
|
|
|
|
# Ensure staging directories exist to prevent opkg lock file errors
|
|
mkdir -p build_dir/target-*/root*/tmp 2>/dev/null || true
|
|
|
|
# Build with explicit profile specification to ensure images are generated
|
|
if make -j$(nproc) PROFILE="${{ matrix.profile }}" 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 ""
|
|
|
|
# Ensure staging directories exist before retry
|
|
mkdir -p build_dir/target-*/root*/tmp 2>/dev/null || true
|
|
|
|
if make -j1 PROFILE="${{ matrix.profile }}" 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 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "⚠️ WARNING: No firmware images found!"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo ""
|
|
echo "🔍 Diagnostic Information:"
|
|
echo ""
|
|
|
|
# Check if target directory structure exists
|
|
if [[ -d "openwrt/bin/targets" ]]; then
|
|
echo "📂 Available targets:"
|
|
find openwrt/bin/targets -type d -mindepth 2 -maxdepth 2 2>/dev/null | sed 's|openwrt/bin/targets/||' || echo " (none)"
|
|
echo ""
|
|
fi
|
|
|
|
# Check build log for errors
|
|
if [[ -f "openwrt/build.log" ]]; then
|
|
echo "📋 Checking build log for errors..."
|
|
if grep -i "error\|failed\|cannot" openwrt/build.log | tail -10 | grep -v "warning" > /tmp/errors.txt 2>/dev/null; then
|
|
echo "Recent errors found:"
|
|
cat /tmp/errors.txt
|
|
else
|
|
echo " No obvious errors in build log"
|
|
fi
|
|
echo ""
|
|
fi
|
|
|
|
# Check if device profile was actually built
|
|
echo "🎯 Checking if device profile was built:"
|
|
if [[ -d "$TARGET_DIR" ]]; then
|
|
ALL_FILES=$(find "$TARGET_DIR" -type f 2>/dev/null | wc -l)
|
|
echo " Total files in target directory: $ALL_FILES"
|
|
|
|
if [[ $ALL_FILES -gt 0 ]]; then
|
|
echo " Files present:"
|
|
ls -lh "$TARGET_DIR" | grep -v "^total" | grep -v "^d"
|
|
fi
|
|
else
|
|
echo " ❌ Target directory doesn't exist: $TARGET_DIR"
|
|
fi
|
|
echo ""
|
|
|
|
echo "💡 This usually means:"
|
|
echo " 1. Device profile not properly selected in .config"
|
|
echo " 2. Build completed but only packages were built, not images"
|
|
echo " 3. Device profile name doesn't match OpenWrt version ${{ env.OPENWRT_VERSION }}"
|
|
echo ""
|
|
echo "🔧 Suggested actions:"
|
|
echo " 1. Check the 'Verify device profile configuration' step output"
|
|
echo " 2. Verify profile '${{ matrix.profile }}' exists for OpenWrt ${{ env.OPENWRT_VERSION }}"
|
|
echo " 3. Check if CONFIG_TARGET options are properly set in .config"
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
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
|
|
SECUBOX_INCLUDED="${{ github.event.inputs.include_secubox }}"
|
|
if [[ "${{ github.event_name }}" == "push" ]]; then
|
|
SECUBOX_INCLUDED="true (auto)"
|
|
fi
|
|
|
|
cat > BUILD_INFO.txt << EOF
|
|
SecuBox Firmware Build
|
|
=======================
|
|
Device: ${{ matrix.description }}
|
|
Profile: ${{ matrix.profile }}
|
|
Target: ${{ matrix.target }}/${{ matrix.subtarget }}
|
|
OpenWrt: ${{ env.OPENWRT_VERSION }}
|
|
SecuBox: ${SECUBOX_INCLUDED:-true}
|
|
Built: $(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
Commit: ${{ github.sha }}
|
|
EOF
|
|
|
|
if [[ "${{ github.event_name }}" == "push" ]]; then
|
|
echo "Tag: ${{ github.ref_name }}" >> BUILD_INFO.txt
|
|
fi
|
|
|
|
cat >> BUILD_INFO.txt << EOF
|
|
|
|
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: Save build logs and config
|
|
if: always()
|
|
run: |
|
|
mkdir -p artifacts/logs
|
|
|
|
# Save .config file
|
|
if [[ -f openwrt/.config ]]; then
|
|
cp openwrt/.config artifacts/logs/dotconfig
|
|
echo "✅ Saved .config as dotconfig"
|
|
fi
|
|
|
|
# Save build logs
|
|
if [[ -f openwrt/build.log ]]; then
|
|
cp openwrt/build.log artifacts/logs/
|
|
echo "✅ Saved build.log"
|
|
fi
|
|
|
|
if [[ -f openwrt/build-retry.log ]]; then
|
|
cp openwrt/build-retry.log artifacts/logs/
|
|
echo "✅ Saved build-retry.log"
|
|
fi
|
|
|
|
# Save make output
|
|
if [[ -f openwrt/logs ]]; then
|
|
cp -r openwrt/logs artifacts/logs/make-logs 2>/dev/null || true
|
|
fi
|
|
|
|
echo ""
|
|
echo "📋 Logs saved to artifacts/logs/ for debugging"
|
|
|
|
- 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 || 'true (auto)' }} |" >> $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' || github.event_name == 'push'
|
|
|
|
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
|
|
|
|
**Security & Access Control:**
|
|
- luci-app-auth-guardian - Authentication & session manager
|
|
- luci-app-client-guardian - NAC & captive portal
|
|
- luci-app-crowdsec-dashboard - CrowdSec security monitoring
|
|
- luci-app-ksm-manager - Key storage & HSM
|
|
- luci-app-netifyd-dashboard - Deep packet inspection
|
|
|
|
**Monitoring & Analytics:**
|
|
- luci-app-media-flow - Media traffic detection
|
|
- luci-app-netdata-dashboard - System monitoring
|
|
|
|
**Network Management:**
|
|
- luci-app-bandwidth-manager - QoS & bandwidth quotas
|
|
- luci-app-cdn-cache - CDN proxy cache
|
|
- luci-app-network-modes - Network mode configuration
|
|
- luci-app-traffic-shaper - Advanced traffic shaping
|
|
- luci-app-wireguard-dashboard - WireGuard VPN
|
|
|
|
**System & Services:**
|
|
- luci-app-secubox - Central management hub
|
|
- luci-app-system-hub - System control center
|
|
- luci-app-vhost-manager - Virtual host manager
|
|
|
|
## 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: startsWith(github.ref, 'refs/tags/v')
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
name: "SecuBox Firmware ${{ github.ref_name }}"
|
|
tag_name: ${{ github.ref_name }}
|
|
body_path: release/RELEASE_NOTES.md
|
|
files: |
|
|
release/*.tar.gz
|
|
release/SHA256SUMS
|
|
draft: false
|
|
prerelease: ${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') || contains(github.ref_name, 'rc') }}
|
|
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 || 'true (auto)' }} |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Target Device | ${{ github.event.inputs.device || 'all (auto)' }} |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Workflow Run | #${{ github.run_number }} |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Triggered by | ${{ github.event_name }} |" >> $GITHUB_STEP_SUMMARY
|
|
|
|
# Add tag info if triggered by tag
|
|
if [[ "${{ github.event_name }}" == "push" ]] && [[ -n "${{ github.ref_name }}" ]]; then
|
|
echo "| Git Tag | \`${{ github.ref_name }}\` |" >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
|
|
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
|