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: - '24.10.5' - '25.12.0-rc1' - '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<> $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 # Copy luci-app-* packages 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 # Copy luci-theme-secubox if [[ -d "luci-theme-secubox" ]]; then echo " โœ… luci-theme-secubox" cp -r luci-theme-secubox openwrt/package/secubox/ if [[ -f "openwrt/package/secubox/luci-theme-secubox/Makefile" ]]; then sed -i 's|include.*luci\.mk|include $(TOPDIR)/feeds/luci/luci.mk|' "openwrt/package/secubox/luci-theme-secubox/Makefile" echo " โœ“ Fixed Makefile include path" fi PKG_COUNT=$((PKG_COUNT + 1)) fi # Copy package/secubox/secubox-app if [[ -d "package/secubox/secubox-app" ]]; then echo " โœ… secubox-app" cp -r package/secubox/secubox-app openwrt/package/secubox/ PKG_COUNT=$((PKG_COUNT + 1)) fi 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 CONFIG_PACKAGE_luci-theme-secubox=y # DNS Server (fix conflict: use dnsmasq-full only) # CONFIG_PACKAGE_dnsmasq is not set CONFIG_PACKAGE_dnsmasq-full=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_secubox-app=y CONFIG_PACKAGE_luci-app-secubox=y CONFIG_PACKAGE_luci-app-system-hub=y # SecuBox packages - Security & Monitoring # CONFIG_PACKAGE_luci-app-crowdsec-dashboard is not set (requires crowdsec backend - compile fails) CONFIG_PACKAGE_luci-app-netdata-dashboard=y # SecuBox packages - Network Intelligence 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 is not set (not stable yet) # SecuBox packages - Bandwidth & Traffic CONFIG_PACKAGE_luci-app-bandwidth-manager=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 # SecuBox packages - Disabled (require compilation/not ready) # CONFIG_PACKAGE_secubox-app-crowdsec is not set (requires Go 1.23+ - fails in firmware build) # CONFIG_PACKAGE_luci-app-ksm-manager is not set (not stable) # CONFIG_PACKAGE_luci-app-traffic-shaper is not set (not stable) 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