Initial commit: SecuBox v1.0.0
This commit is contained in:
commit
0981987c10
551
.github/workflows/build-openwrt-packages.yml
vendored
Normal file
551
.github/workflows/build-openwrt-packages.yml
vendored
Normal file
@ -0,0 +1,551 @@
|
||||
name: Build OpenWrt Packages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, master, develop]
|
||||
tags:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
branches: [main, master]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
openwrt_version:
|
||||
description: 'OpenWrt version'
|
||||
required: true
|
||||
default: '23.05.5'
|
||||
type: choice
|
||||
options:
|
||||
- '23.05.5'
|
||||
- '23.05.4'
|
||||
- '22.03.7'
|
||||
- 'SNAPSHOT'
|
||||
architectures:
|
||||
description: 'Architectures to build (comma-separated or "all")'
|
||||
required: false
|
||||
default: 'all'
|
||||
|
||||
env:
|
||||
OPENWRT_VERSION: ${{ github.event.inputs.openwrt_version || '23.05.5' }}
|
||||
|
||||
jobs:
|
||||
# ============================================
|
||||
# Determine build matrix
|
||||
# ============================================
|
||||
setup:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Determine version
|
||||
id: version
|
||||
run: |
|
||||
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
|
||||
VERSION="${{ github.ref_name }}"
|
||||
else
|
||||
VERSION="0.0.0-$(git rev-parse --short HEAD)"
|
||||
fi
|
||||
echo "version=${VERSION#v}" >> $GITHUB_OUTPUT
|
||||
echo "📦 Package version: ${VERSION#v}"
|
||||
|
||||
- name: Set build matrix
|
||||
id: set-matrix
|
||||
run: |
|
||||
# Full architecture matrix for OpenWrt
|
||||
# Format: target/subtarget -> SDK name mapping
|
||||
ALL_TARGETS=$(cat << 'EOF'
|
||||
{
|
||||
"include": [
|
||||
{
|
||||
"target": "x86-64",
|
||||
"arch": "x86_64",
|
||||
"sdk_name": "x86-64",
|
||||
"description": "x86 64-bit (PC, VM, containers)"
|
||||
},
|
||||
{
|
||||
"target": "x86-generic",
|
||||
"arch": "i386_pentium4",
|
||||
"sdk_name": "x86-generic",
|
||||
"description": "x86 32-bit (legacy PC)"
|
||||
},
|
||||
{
|
||||
"target": "aarch64-generic",
|
||||
"arch": "aarch64_generic",
|
||||
"sdk_name": "armsr-armv8",
|
||||
"description": "ARM 64-bit generic (RPi4, Rock64)"
|
||||
},
|
||||
{
|
||||
"target": "aarch64-cortex-a53",
|
||||
"arch": "aarch64_cortex-a53",
|
||||
"sdk_name": "mvebu-cortexa53",
|
||||
"description": "ARM Cortex-A53 (ESPRESSObin, Sheeva64)"
|
||||
},
|
||||
{
|
||||
"target": "aarch64-cortex-a72",
|
||||
"arch": "aarch64_cortex-a72",
|
||||
"sdk_name": "mvebu-cortexa72",
|
||||
"description": "ARM Cortex-A72 (MOCHAbin, MACCHIATObin)"
|
||||
},
|
||||
{
|
||||
"target": "arm-cortex-a7-neon",
|
||||
"arch": "arm_cortex-a7_neon-vfpv4",
|
||||
"sdk_name": "sunxi-cortexa7",
|
||||
"description": "ARM Cortex-A7 (Orange Pi, Banana Pi)"
|
||||
},
|
||||
{
|
||||
"target": "arm-cortex-a9-neon",
|
||||
"arch": "arm_cortex-a9_neon",
|
||||
"sdk_name": "mvebu-cortexa9",
|
||||
"description": "ARM Cortex-A9 (Linksys WRT, Turris)"
|
||||
},
|
||||
{
|
||||
"target": "arm-cortex-a15-neon",
|
||||
"arch": "arm_cortex-a15_neon-vfpv4",
|
||||
"sdk_name": "armvirt-32",
|
||||
"description": "ARM Cortex-A15 (QEMU ARM)"
|
||||
},
|
||||
{
|
||||
"target": "mips-24kc",
|
||||
"arch": "mips_24kc",
|
||||
"sdk_name": "ath79-generic",
|
||||
"description": "MIPS 24Kc (TP-Link, Ubiquiti)"
|
||||
},
|
||||
{
|
||||
"target": "mipsel-24kc",
|
||||
"arch": "mipsel_24kc",
|
||||
"sdk_name": "ramips-mt7621",
|
||||
"description": "MIPS Little-Endian (Xiaomi, GL.iNet)"
|
||||
},
|
||||
{
|
||||
"target": "mipsel-74kc",
|
||||
"arch": "mipsel_74kc",
|
||||
"sdk_name": "bcm47xx-mips74k",
|
||||
"description": "MIPS 74Kc (Broadcom routers)"
|
||||
},
|
||||
{
|
||||
"target": "mediatek-filogic",
|
||||
"arch": "aarch64_cortex-a53",
|
||||
"sdk_name": "mediatek-filogic",
|
||||
"description": "MediaTek Filogic (MT7981, MT7986)"
|
||||
},
|
||||
{
|
||||
"target": "qualcomm-ipq40xx",
|
||||
"arch": "arm_cortex-a7_neon-vfpv4",
|
||||
"sdk_name": "ipq40xx-generic",
|
||||
"description": "Qualcomm IPQ40xx (Google WiFi, Zyxel)"
|
||||
},
|
||||
{
|
||||
"target": "qualcomm-ipq806x",
|
||||
"arch": "arm_cortex-a15_neon-vfpv4",
|
||||
"sdk_name": "ipq806x-generic",
|
||||
"description": "Qualcomm IPQ806x (Netgear R7800)"
|
||||
},
|
||||
{
|
||||
"target": "rockchip-armv8",
|
||||
"arch": "aarch64_generic",
|
||||
"sdk_name": "rockchip-armv8",
|
||||
"description": "Rockchip (NanoPi R4S, R5S)"
|
||||
},
|
||||
{
|
||||
"target": "bcm27xx-bcm2711",
|
||||
"arch": "aarch64_cortex-a72",
|
||||
"sdk_name": "bcm27xx-bcm2711",
|
||||
"description": "Raspberry Pi 4"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
INPUT_ARCHS="${{ github.event.inputs.architectures }}"
|
||||
if [[ -z "$INPUT_ARCHS" || "$INPUT_ARCHS" == "all" ]]; then
|
||||
MATRIX="$ALL_TARGETS"
|
||||
else
|
||||
# Filter matrix based on input
|
||||
MATRIX=$(echo "$ALL_TARGETS" | jq -c --arg archs "$INPUT_ARCHS" '
|
||||
.include |= map(select(.target as $t | $archs | split(",") | map(gsub("^\\s+|\\s+$";"")) | any(. == $t or . == "all")))
|
||||
')
|
||||
fi
|
||||
|
||||
echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
|
||||
echo "📋 Build matrix:"
|
||||
echo "$MATRIX" | jq '.'
|
||||
|
||||
# ============================================
|
||||
# Build packages for each architecture
|
||||
# ============================================
|
||||
build:
|
||||
needs: setup
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.setup.outputs.matrix) }}
|
||||
|
||||
name: Build ${{ matrix.target }}
|
||||
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Free disk space
|
||||
run: |
|
||||
echo "🧹 Cleaning up disk space..."
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /usr/local/lib/android
|
||||
sudo rm -rf /opt/ghc
|
||||
sudo rm -rf /opt/hostedtoolcache/CodeQL
|
||||
sudo docker image prune --all --force
|
||||
df -h
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
build-essential clang flex bison g++ gawk \
|
||||
gcc-multilib g++-multilib gettext git libncurses5-dev \
|
||||
libssl-dev python3-distutils python3-setuptools rsync \
|
||||
swig unzip zlib1g-dev file wget curl jq
|
||||
|
||||
- name: Cache OpenWrt SDK
|
||||
uses: actions/cache@v4
|
||||
id: cache-sdk
|
||||
with:
|
||||
path: ~/sdk
|
||||
key: openwrt-sdk-${{ env.OPENWRT_VERSION }}-${{ matrix.sdk_name }}
|
||||
|
||||
- name: Download OpenWrt SDK
|
||||
if: steps.cache-sdk.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "📥 Downloading SDK for ${{ matrix.description }}..."
|
||||
|
||||
VERSION="${{ env.OPENWRT_VERSION }}"
|
||||
SDK_NAME="${{ matrix.sdk_name }}"
|
||||
|
||||
if [[ "$VERSION" == "SNAPSHOT" ]]; then
|
||||
BASE_URL="https://downloads.openwrt.org/snapshots/targets"
|
||||
else
|
||||
BASE_URL="https://downloads.openwrt.org/releases/${VERSION}/targets"
|
||||
fi
|
||||
|
||||
# Parse target/subtarget from sdk_name
|
||||
TARGET=$(echo "$SDK_NAME" | cut -d'-' -f1)
|
||||
SUBTARGET=$(echo "$SDK_NAME" | cut -d'-' -f2-)
|
||||
|
||||
SDK_URL="${BASE_URL}/${TARGET}/${SUBTARGET}"
|
||||
|
||||
echo "🔍 Looking for SDK at: $SDK_URL"
|
||||
|
||||
# Find SDK filename
|
||||
SDK_FILE=$(curl -sL "$SDK_URL/" | grep -oP 'openwrt-sdk[^"]+\.tar\.(xz|zst)' | head -1)
|
||||
|
||||
if [[ -z "$SDK_FILE" ]]; then
|
||||
echo "⚠️ SDK not found, trying alternative URL pattern..."
|
||||
SDK_FILE=$(curl -sL "$SDK_URL/sha256sums" | grep -oP 'openwrt-sdk[^\s]+' | head -1)
|
||||
fi
|
||||
|
||||
if [[ -z "$SDK_FILE" ]]; then
|
||||
echo "❌ Could not find SDK for ${{ matrix.target }}"
|
||||
echo "🔗 Checked: $SDK_URL"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "📦 Downloading: $SDK_FILE"
|
||||
wget -q --show-progress "${SDK_URL}/${SDK_FILE}" -O /tmp/sdk.tar.xz || \
|
||||
wget -q --show-progress "${SDK_URL}/${SDK_FILE}" -O /tmp/sdk.tar.zst
|
||||
|
||||
mkdir -p ~/sdk
|
||||
if [[ "$SDK_FILE" == *.zst ]]; then
|
||||
zstd -d /tmp/sdk.tar.zst -o /tmp/sdk.tar
|
||||
tar -xf /tmp/sdk.tar -C ~/sdk --strip-components=1
|
||||
else
|
||||
tar -xf /tmp/sdk.tar.xz -C ~/sdk --strip-components=1
|
||||
fi
|
||||
|
||||
echo "✅ SDK extracted to ~/sdk"
|
||||
|
||||
- name: Prepare SDK
|
||||
run: |
|
||||
cd ~/sdk
|
||||
|
||||
# Update feeds
|
||||
echo "📋 Updating feeds..."
|
||||
./scripts/feeds update -a
|
||||
./scripts/feeds install -a
|
||||
|
||||
# Configure SDK
|
||||
echo "⚙️ Configuring SDK..."
|
||||
make defconfig
|
||||
|
||||
- name: Copy packages to SDK
|
||||
run: |
|
||||
echo "📁 Copying SecuBox packages to SDK..."
|
||||
|
||||
# List of our packages
|
||||
PACKAGES=(
|
||||
"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"
|
||||
)
|
||||
|
||||
# Create package directory
|
||||
mkdir -p ~/sdk/package/secubox
|
||||
|
||||
# Copy each package if it exists
|
||||
for pkg in "${PACKAGES[@]}"; do
|
||||
if [[ -d "$GITHUB_WORKSPACE/$pkg" ]]; then
|
||||
echo " 📦 $pkg"
|
||||
cp -r "$GITHUB_WORKSPACE/$pkg" ~/sdk/package/secubox/
|
||||
else
|
||||
echo " ⚠️ $pkg not found in repository"
|
||||
fi
|
||||
done
|
||||
|
||||
# If packages are in a subdirectory
|
||||
if [[ -d "$GITHUB_WORKSPACE/packages" ]]; then
|
||||
cp -r "$GITHUB_WORKSPACE/packages/"* ~/sdk/package/secubox/ 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# List what we have
|
||||
echo "📋 Packages in SDK:"
|
||||
ls -la ~/sdk/package/secubox/ || echo " (empty)"
|
||||
|
||||
- name: Update package version
|
||||
run: |
|
||||
VERSION="${{ needs.setup.outputs.version }}"
|
||||
echo "📝 Setting package version to: $VERSION"
|
||||
|
||||
# Update Makefile version in each package
|
||||
for makefile in ~/sdk/package/secubox/*/Makefile; do
|
||||
if [[ -f "$makefile" ]]; then
|
||||
sed -i "s/PKG_VERSION:=.*/PKG_VERSION:=$VERSION/" "$makefile"
|
||||
sed -i "s/PKG_RELEASE:=.*/PKG_RELEASE:=1/" "$makefile"
|
||||
echo " ✅ Updated: $(dirname $makefile | xargs basename)"
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Build packages
|
||||
run: |
|
||||
cd ~/sdk
|
||||
|
||||
echo "🔨 Building SecuBox packages for ${{ matrix.description }}..."
|
||||
|
||||
# Enable our packages
|
||||
for pkg in ~/sdk/package/secubox/*/; do
|
||||
PKG_NAME=$(basename "$pkg")
|
||||
echo "CONFIG_PACKAGE_${PKG_NAME}=m" >> .config
|
||||
done
|
||||
|
||||
make defconfig
|
||||
|
||||
# Build with verbose output on error
|
||||
make package/secubox/compile V=s -j$(nproc) || {
|
||||
echo "❌ Build failed, retrying with single thread..."
|
||||
make package/secubox/compile V=s -j1
|
||||
}
|
||||
|
||||
# Generate package index
|
||||
make package/index V=s
|
||||
|
||||
- name: Collect artifacts
|
||||
id: collect
|
||||
run: |
|
||||
echo "📦 Collecting built packages..."
|
||||
|
||||
mkdir -p $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}
|
||||
|
||||
# Find and copy .ipk files
|
||||
find ~/sdk/bin -name "*.ipk" -exec cp {} $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}/ \;
|
||||
|
||||
# Copy package index
|
||||
find ~/sdk/bin -name "Packages*" -exec cp {} $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}/ \; 2>/dev/null || true
|
||||
|
||||
# List artifacts
|
||||
echo "📋 Built packages for ${{ matrix.target }}:"
|
||||
ls -la $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}/
|
||||
|
||||
# Count packages
|
||||
PKG_COUNT=$(find $GITHUB_WORKSPACE/artifacts/${{ matrix.target }} -name "*.ipk" | wc -l)
|
||||
echo "pkg_count=$PKG_COUNT" >> $GITHUB_OUTPUT
|
||||
|
||||
if [[ $PKG_COUNT -eq 0 ]]; then
|
||||
echo "⚠️ No packages built!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Create checksums
|
||||
run: |
|
||||
cd $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}
|
||||
sha256sum *.ipk > SHA256SUMS
|
||||
echo "✅ Checksums created"
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: packages-${{ matrix.target }}
|
||||
path: artifacts/${{ matrix.target }}/
|
||||
retention-days: 30
|
||||
|
||||
# ============================================
|
||||
# Create combined release
|
||||
# ============================================
|
||||
release:
|
||||
needs: [setup, build]
|
||||
runs-on: ubuntu-latest
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: packages
|
||||
pattern: packages-*
|
||||
|
||||
- name: Organize packages
|
||||
run: |
|
||||
echo "📁 Organizing release packages..."
|
||||
|
||||
VERSION="${{ needs.setup.outputs.version }}"
|
||||
mkdir -p release
|
||||
|
||||
# Create architecture-specific archives
|
||||
for arch_dir in packages/packages-*/; do
|
||||
ARCH=$(basename "$arch_dir" | sed 's/packages-//')
|
||||
echo "📦 Processing $ARCH..."
|
||||
|
||||
# Create tarball
|
||||
tar -czf "release/secubox-${VERSION}-${ARCH}.tar.gz" -C "$arch_dir" .
|
||||
|
||||
# Copy individual .ipk files to flat structure
|
||||
mkdir -p "release/ipk/${ARCH}"
|
||||
cp "$arch_dir"/*.ipk "release/ipk/${ARCH}/" 2>/dev/null || true
|
||||
done
|
||||
|
||||
# Create "all architectures" mega-archive
|
||||
tar -czf "release/secubox-${VERSION}-all-architectures.tar.gz" -C packages .
|
||||
|
||||
# Create release notes
|
||||
cat > release/RELEASE_NOTES.md << EOF
|
||||
# SecuBox $VERSION
|
||||
|
||||
## 📦 Packages Included
|
||||
|
||||
- luci-app-crowdsec-dashboard - CrowdSec Security Dashboard
|
||||
- luci-app-netdata-dashboard - Netdata Monitoring Dashboard
|
||||
- luci-app-netifyd-dashboard - Netifyd DPI Dashboard
|
||||
- luci-app-wireguard-dashboard - WireGuard VPN Dashboard
|
||||
- luci-app-network-modes - Network Mode Switcher
|
||||
- luci-app-client-guardian - NAC & Captive Portal
|
||||
- luci-app-system-hub - System Hub Control Center
|
||||
|
||||
## 🏗️ Supported Architectures
|
||||
|
||||
| Target | Architecture | Description |
|
||||
|--------|--------------|-------------|
|
||||
| x86-64 | x86_64 | PC, VMs, Containers |
|
||||
| aarch64-cortex-a53 | aarch64 | ESPRESSObin, Sheeva64 |
|
||||
| aarch64-cortex-a72 | aarch64 | MOCHAbin, RPi4 |
|
||||
| arm-cortex-a7 | arm | Orange Pi, Banana Pi |
|
||||
| arm-cortex-a9 | arm | Linksys WRT, Turris |
|
||||
| mips-24kc | mips | TP-Link, Ubiquiti |
|
||||
| mipsel-24kc | mipsel | Xiaomi, GL.iNet |
|
||||
| mediatek-filogic | aarch64 | MT7981, MT7986 |
|
||||
| qualcomm-ipq40xx | arm | Google WiFi |
|
||||
| rockchip-armv8 | aarch64 | NanoPi R4S, R5S |
|
||||
|
||||
## 📥 Installation
|
||||
|
||||
\`\`\`bash
|
||||
# Download package for your architecture
|
||||
opkg update
|
||||
opkg install luci-app-crowdsec-dashboard_${VERSION}_*.ipk
|
||||
# ... install other packages as needed
|
||||
\`\`\`
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
- [Documentation](https://cybermind.fr/docs/secubox)
|
||||
- [GitHub](https://github.com/gkerma)
|
||||
- [CyberMind.fr](https://cybermind.fr)
|
||||
|
||||
---
|
||||
Built with OpenWrt SDK ${{ env.OPENWRT_VERSION }}
|
||||
EOF
|
||||
|
||||
echo "✅ Release organized"
|
||||
ls -la release/
|
||||
|
||||
- name: Create global checksums
|
||||
run: |
|
||||
cd release
|
||||
sha256sum *.tar.gz > SHA256SUMS
|
||||
echo "✅ Global checksums created"
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
name: SecuBox ${{ needs.setup.outputs.version }}
|
||||
body_path: release/RELEASE_NOTES.md
|
||||
files: |
|
||||
release/*.tar.gz
|
||||
release/SHA256SUMS
|
||||
draft: false
|
||||
prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') || contains(github.ref, 'rc') }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# ============================================
|
||||
# Build status summary
|
||||
# ============================================
|
||||
summary:
|
||||
needs: [setup, build]
|
||||
runs-on: ubuntu-latest
|
||||
if: always()
|
||||
|
||||
steps:
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: packages
|
||||
pattern: packages-*
|
||||
continue-on-error: true
|
||||
|
||||
- name: Generate build summary
|
||||
run: |
|
||||
echo "# 📊 SecuBox Build Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Version:** ${{ needs.setup.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**OpenWrt:** ${{ env.OPENWRT_VERSION }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "## Build Results" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Architecture | Status | Packages |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|--------------|--------|----------|" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
for arch_dir in packages/packages-*/; do
|
||||
if [[ -d "$arch_dir" ]]; then
|
||||
ARCH=$(basename "$arch_dir" | sed 's/packages-//')
|
||||
PKG_COUNT=$(find "$arch_dir" -name "*.ipk" 2>/dev/null | wc -l)
|
||||
if [[ $PKG_COUNT -gt 0 ]]; then
|
||||
echo "| $ARCH | ✅ Success | $PKG_COUNT |" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "| $ARCH | ⚠️ No packages | 0 |" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "## 📦 Artifacts" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Download artifacts from the Actions tab above." >> $GITHUB_STEP_SUMMARY
|
||||
398
.github/workflows/build-secubox-images.yml
vendored
Normal file
398
.github/workflows/build-secubox-images.yml
vendored
Normal file
@ -0,0 +1,398 @@
|
||||
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 }}
|
||||
|
||||
jobs:
|
||||
# ============================================
|
||||
# Build firmware images for GlobalScale devices
|
||||
# ============================================
|
||||
build-image:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- device: espressobin-v7
|
||||
target: mvebu
|
||||
subtarget: cortexa53
|
||||
profile: globalscale_espressobin
|
||||
description: "ESPRESSObin V7 (1-2GB DDR4)"
|
||||
enabled: ${{ github.event.inputs.device == 'espressobin-v7' || github.event.inputs.device == 'all' }}
|
||||
|
||||
- device: espressobin-ultra
|
||||
target: mvebu
|
||||
subtarget: cortexa53
|
||||
profile: globalscale_espressobin-ultra
|
||||
description: "ESPRESSObin Ultra (PoE, WiFi)"
|
||||
enabled: ${{ github.event.inputs.device == 'espressobin-ultra' || github.event.inputs.device == 'all' }}
|
||||
|
||||
- device: sheeva64
|
||||
target: mvebu
|
||||
subtarget: cortexa53
|
||||
profile: globalscale_sheeva64
|
||||
description: "Sheeva64 (Plug computer)"
|
||||
enabled: ${{ github.event.inputs.device == 'sheeva64' || github.event.inputs.device == 'all' }}
|
||||
|
||||
- device: sheeva64-wifi
|
||||
target: mvebu
|
||||
subtarget: cortexa53
|
||||
profile: globalscale_sheeva64
|
||||
description: "Sheeva64 WiFi (802.11ac + BT)"
|
||||
enabled: ${{ github.event.inputs.device == 'sheeva64-wifi' || github.event.inputs.device == 'all' }}
|
||||
|
||||
- device: mochabin
|
||||
target: mvebu
|
||||
subtarget: cortexa72
|
||||
profile: globalscale_mochabin
|
||||
description: "MOCHAbin (Quad-core A72, 10G)"
|
||||
enabled: ${{ github.event.inputs.device == 'mochabin' || github.event.inputs.device == 'all' }}
|
||||
|
||||
name: ${{ matrix.description }}
|
||||
if: ${{ matrix.enabled != 'false' }}
|
||||
|
||||
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-distutils python3-setuptools 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
|
||||
./scripts/feeds update -a
|
||||
./scripts/feeds install -a
|
||||
|
||||
- name: Copy SecuBox packages
|
||||
if: ${{ github.event.inputs.include_secubox == 'true' }}
|
||||
run: |
|
||||
mkdir -p openwrt/package/secubox
|
||||
|
||||
for pkg in luci-app-*/; do
|
||||
if [[ -d "$pkg" ]]; then
|
||||
echo "📦 Adding $pkg"
|
||||
cp -r "$pkg" openwrt/package/secubox/
|
||||
fi
|
||||
done
|
||||
|
||||
- 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
|
||||
make defconfig
|
||||
|
||||
- name: Download packages
|
||||
run: |
|
||||
cd openwrt
|
||||
make download -j$(nproc) V=s || make download -j1 V=s
|
||||
|
||||
- name: Build firmware
|
||||
run: |
|
||||
cd openwrt
|
||||
|
||||
echo "🔨 Building firmware for ${{ matrix.description }}..."
|
||||
echo "⏱️ This may take 1-2 hours..."
|
||||
|
||||
make -j$(nproc) V=s 2>&1 | tee build.log || {
|
||||
echo "❌ Build failed, retrying with single thread..."
|
||||
make -j1 V=s 2>&1 | tee build-retry.log
|
||||
}
|
||||
|
||||
- name: Prepare artifacts
|
||||
run: |
|
||||
mkdir -p artifacts
|
||||
|
||||
# Copy firmware images
|
||||
find openwrt/bin/targets -name "*.img.gz" -exec cp {} artifacts/ \;
|
||||
find openwrt/bin/targets -name "*.bin" -exec cp {} artifacts/ \;
|
||||
find openwrt/bin/targets -name "*sysupgrade*" -exec cp {} artifacts/ \;
|
||||
find openwrt/bin/targets -name "*factory*" -exec cp {} artifacts/ \;
|
||||
|
||||
# Copy packages
|
||||
mkdir -p artifacts/packages
|
||||
find openwrt/bin/packages -name "luci-app-*secubox*.ipk" -exec cp {} artifacts/packages/ \; 2>/dev/null || true
|
||||
find openwrt/bin/packages -name "luci-app-*dashboard*.ipk" -exec cp {} artifacts/packages/ \; 2>/dev/null || true
|
||||
|
||||
# Generate checksums
|
||||
cd artifacts
|
||||
sha256sum * > SHA256SUMS 2>/dev/null || true
|
||||
|
||||
# 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 }}
|
||||
EOF
|
||||
|
||||
echo "📦 Artifacts:"
|
||||
ls -la
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: secubox-${{ matrix.device }}-${{ env.OPENWRT_VERSION }}
|
||||
path: artifacts/
|
||||
retention-days: 30
|
||||
|
||||
# ============================================
|
||||
# Create combined release for all devices
|
||||
# ============================================
|
||||
release:
|
||||
needs: 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 }}
|
||||
327
.github/workflows/test-validate.yml
vendored
Normal file
327
.github/workflows/test-validate.yml
vendored
Normal file
@ -0,0 +1,327 @@
|
||||
name: Test & Validate Packages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, master, develop]
|
||||
pull_request:
|
||||
branches: [main, master]
|
||||
|
||||
jobs:
|
||||
# ============================================
|
||||
# Lint and validate package structure
|
||||
# ============================================
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
name: Lint & Validate
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install validators
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y shellcheck jq
|
||||
|
||||
- name: Validate Makefile structure
|
||||
run: |
|
||||
echo "📋 Validating Makefile structure..."
|
||||
|
||||
ERRORS=0
|
||||
|
||||
for makefile in */Makefile; do
|
||||
if [[ -f "$makefile" ]]; then
|
||||
PKG=$(dirname "$makefile")
|
||||
echo " 🔍 Checking $PKG..."
|
||||
|
||||
# Required fields
|
||||
REQUIRED_FIELDS=(
|
||||
"PKG_NAME"
|
||||
"PKG_VERSION"
|
||||
"PKG_RELEASE"
|
||||
"PKG_LICENSE"
|
||||
"LUCI_TITLE"
|
||||
)
|
||||
|
||||
for field in "${REQUIRED_FIELDS[@]}"; do
|
||||
if ! grep -q "^${field}:=" "$makefile"; then
|
||||
echo " ❌ Missing: $field"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
# Check for include statements
|
||||
if ! grep -q "include.*luci.mk\|include.*package.mk" "$makefile"; then
|
||||
echo " ❌ Missing include statement (luci.mk or package.mk)"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $ERRORS -gt 0 ]]; then
|
||||
echo "❌ Found $ERRORS errors"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ All Makefiles valid"
|
||||
|
||||
- name: Validate JSON files
|
||||
run: |
|
||||
echo "📋 Validating JSON files..."
|
||||
|
||||
ERRORS=0
|
||||
|
||||
# Find all JSON files
|
||||
while IFS= read -r jsonfile; do
|
||||
echo " 🔍 Checking $jsonfile..."
|
||||
if ! jq empty "$jsonfile" 2>/dev/null; then
|
||||
echo " ❌ Invalid JSON"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
done < <(find . -name "*.json" -type f)
|
||||
|
||||
if [[ $ERRORS -gt 0 ]]; then
|
||||
echo "❌ Found $ERRORS JSON errors"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ All JSON files valid"
|
||||
|
||||
- name: Validate JavaScript syntax
|
||||
run: |
|
||||
echo "📋 Validating JavaScript files..."
|
||||
|
||||
# Install node for syntax check
|
||||
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
|
||||
sudo apt-get install -y nodejs
|
||||
|
||||
ERRORS=0
|
||||
|
||||
while IFS= read -r jsfile; do
|
||||
echo " 🔍 Checking $jsfile..."
|
||||
if ! node --check "$jsfile" 2>/dev/null; then
|
||||
echo " ❌ Syntax error"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
done < <(find . -name "*.js" -type f)
|
||||
|
||||
if [[ $ERRORS -gt 0 ]]; then
|
||||
echo "❌ Found $ERRORS JavaScript errors"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ All JavaScript files valid"
|
||||
|
||||
- name: Validate shell scripts
|
||||
run: |
|
||||
echo "📋 Validating shell scripts..."
|
||||
|
||||
ERRORS=0
|
||||
|
||||
# Check RPCD scripts
|
||||
while IFS= read -r script; do
|
||||
echo " 🔍 Checking $script..."
|
||||
if ! shellcheck -s sh "$script"; then
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
done < <(find . -path "*/rpcd/*" -type f -executable)
|
||||
|
||||
# Check init scripts
|
||||
while IFS= read -r script; do
|
||||
echo " 🔍 Checking $script..."
|
||||
if ! shellcheck -s sh "$script"; then
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
done < <(find . -path "*/init.d/*" -type f)
|
||||
|
||||
if [[ $ERRORS -gt 0 ]]; then
|
||||
echo "⚠️ Found $ERRORS shellcheck warnings (non-blocking)"
|
||||
fi
|
||||
echo "✅ Shell script validation complete"
|
||||
|
||||
- name: Check file permissions
|
||||
run: |
|
||||
echo "📋 Checking file permissions..."
|
||||
|
||||
ERRORS=0
|
||||
|
||||
# RPCD scripts should be executable
|
||||
while IFS= read -r script; do
|
||||
if [[ ! -x "$script" ]]; then
|
||||
echo " ❌ Not executable: $script"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
done < <(find . -path "*/usr/libexec/rpcd/*" -type f 2>/dev/null)
|
||||
|
||||
# Init scripts should be executable
|
||||
while IFS= read -r script; do
|
||||
if [[ ! -x "$script" ]]; then
|
||||
echo " ❌ Not executable: $script"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
done < <(find . -path "*/etc/init.d/*" -type f 2>/dev/null)
|
||||
|
||||
if [[ $ERRORS -gt 0 ]]; then
|
||||
echo "❌ Found $ERRORS permission errors"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ File permissions correct"
|
||||
|
||||
- name: Validate package structure
|
||||
run: |
|
||||
echo "📋 Validating package structure..."
|
||||
|
||||
for pkg in luci-app-*/; do
|
||||
if [[ -d "$pkg" ]]; then
|
||||
echo " 📦 Checking $pkg..."
|
||||
|
||||
# Required directories/files
|
||||
REQUIRED=(
|
||||
"Makefile"
|
||||
)
|
||||
|
||||
# Optional but recommended
|
||||
RECOMMENDED=(
|
||||
"htdocs/luci-static/resources"
|
||||
"root/usr/share/luci/menu.d"
|
||||
"root/usr/share/rpcd/acl.d"
|
||||
)
|
||||
|
||||
for req in "${REQUIRED[@]}"; do
|
||||
if [[ ! -e "${pkg}${req}" ]]; then
|
||||
echo " ❌ Missing required: $req"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
for rec in "${RECOMMENDED[@]}"; do
|
||||
if [[ ! -e "${pkg}${rec}" ]]; then
|
||||
echo " ⚠️ Missing recommended: $rec"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
echo "✅ Package structure valid"
|
||||
|
||||
# ============================================
|
||||
# Quick build test on x86_64
|
||||
# ============================================
|
||||
test-build:
|
||||
runs-on: ubuntu-latest
|
||||
name: Test Build (x86_64)
|
||||
needs: lint
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- 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-distutils rsync unzip zlib1g-dev wget
|
||||
|
||||
- name: Cache OpenWrt SDK
|
||||
uses: actions/cache@v4
|
||||
id: cache-sdk
|
||||
with:
|
||||
path: ~/sdk
|
||||
key: openwrt-sdk-23.05.5-x86-64-test
|
||||
|
||||
- name: Download OpenWrt SDK
|
||||
if: steps.cache-sdk.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
SDK_URL="https://downloads.openwrt.org/releases/23.05.5/targets/x86/64"
|
||||
SDK_FILE=$(curl -sL "$SDK_URL/" | grep -oP 'openwrt-sdk[^"]+\.tar\.xz' | head -1)
|
||||
|
||||
wget -q "${SDK_URL}/${SDK_FILE}" -O /tmp/sdk.tar.xz
|
||||
mkdir -p ~/sdk
|
||||
tar -xf /tmp/sdk.tar.xz -C ~/sdk --strip-components=1
|
||||
|
||||
- name: Prepare SDK
|
||||
run: |
|
||||
cd ~/sdk
|
||||
./scripts/feeds update -a
|
||||
./scripts/feeds install -a
|
||||
make defconfig
|
||||
|
||||
- name: Copy packages
|
||||
run: |
|
||||
mkdir -p ~/sdk/package/secubox
|
||||
|
||||
for pkg in luci-app-*/; do
|
||||
if [[ -d "$pkg" ]]; then
|
||||
cp -r "$pkg" ~/sdk/package/secubox/
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Build test
|
||||
run: |
|
||||
cd ~/sdk
|
||||
|
||||
# Enable packages
|
||||
for pkg in ~/sdk/package/secubox/*/; do
|
||||
PKG_NAME=$(basename "$pkg")
|
||||
echo "CONFIG_PACKAGE_${PKG_NAME}=m" >> .config
|
||||
done
|
||||
|
||||
make defconfig
|
||||
|
||||
# Build with timeout
|
||||
timeout 30m make package/secubox/compile V=s -j$(nproc) || {
|
||||
echo "⚠️ Build timeout or error"
|
||||
exit 1
|
||||
}
|
||||
|
||||
- name: Verify output
|
||||
run: |
|
||||
echo "📋 Built packages:"
|
||||
find ~/sdk/bin -name "*.ipk" -exec ls -la {} \;
|
||||
|
||||
PKG_COUNT=$(find ~/sdk/bin -name "*.ipk" | wc -l)
|
||||
echo "📦 Total packages built: $PKG_COUNT"
|
||||
|
||||
if [[ $PKG_COUNT -eq 0 ]]; then
|
||||
echo "❌ No packages were built!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ============================================
|
||||
# Generate documentation
|
||||
# ============================================
|
||||
docs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Generate Docs
|
||||
needs: lint
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Generate package list
|
||||
run: |
|
||||
echo "# SecuBox Packages" > PACKAGES.md
|
||||
echo "" >> PACKAGES.md
|
||||
echo "| Package | Version | Description |" >> PACKAGES.md
|
||||
echo "|---------|---------|-------------|" >> PACKAGES.md
|
||||
|
||||
for makefile in luci-app-*/Makefile; do
|
||||
if [[ -f "$makefile" ]]; then
|
||||
PKG_NAME=$(grep "^PKG_NAME:=" "$makefile" | cut -d'=' -f2)
|
||||
PKG_VERSION=$(grep "^PKG_VERSION:=" "$makefile" | cut -d'=' -f2)
|
||||
PKG_TITLE=$(grep "^LUCI_TITLE:=" "$makefile" | cut -d'=' -f2-)
|
||||
|
||||
echo "| $PKG_NAME | $PKG_VERSION | $PKG_TITLE |" >> PACKAGES.md
|
||||
fi
|
||||
done
|
||||
|
||||
echo "" >> PACKAGES.md
|
||||
echo "Generated: $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> PACKAGES.md
|
||||
|
||||
cat PACKAGES.md
|
||||
|
||||
- name: Upload docs
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: documentation
|
||||
path: PACKAGES.md
|
||||
232
README.md
Normal file
232
README.md
Normal file
@ -0,0 +1,232 @@
|
||||
# SecuBox OpenWrt CI/CD
|
||||
|
||||
[](https://github.com/gkerma/secubox/actions/workflows/build-openwrt-packages.yml)
|
||||
[](https://github.com/gkerma/secubox/actions/workflows/test-validate.yml)
|
||||
|
||||
## 🎯 Overview
|
||||
|
||||
Ce dépôt contient les workflows GitHub Actions pour compiler automatiquement les packages SecuBox LuCI pour **toutes les architectures OpenWrt supportées**.
|
||||
|
||||
## 📦 Packages Compilés
|
||||
|
||||
| Package | Description |
|
||||
|---------|-------------|
|
||||
| `luci-app-crowdsec-dashboard` | Dashboard CrowdSec |
|
||||
| `luci-app-netdata-dashboard` | Dashboard Netdata |
|
||||
| `luci-app-netifyd-dashboard` | Dashboard Netifyd DPI |
|
||||
| `luci-app-wireguard-dashboard` | Dashboard WireGuard VPN |
|
||||
| `luci-app-network-modes` | Modes réseau (Router/Bridge/AP) |
|
||||
| `luci-app-client-guardian` | NAC & Portail Captif |
|
||||
| `luci-app-system-hub` | Centre de contrôle unifié |
|
||||
|
||||
## 🏗️ Architectures Supportées
|
||||
|
||||
### ARM 64-bit (AArch64)
|
||||
|
||||
| Target | Architecture | Devices |
|
||||
|--------|--------------|---------|
|
||||
| `aarch64-cortex-a53` | Cortex-A53 | **ESPRESSObin**, **Sheeva64**, BananaPi R64 |
|
||||
| `aarch64-cortex-a72` | Cortex-A72 | **MOCHAbin**, Raspberry Pi 4, NanoPi R4S |
|
||||
| `aarch64-generic` | Generic ARMv8 | Rock64, Pine64, QEMU ARM64 |
|
||||
| `mediatek-filogic` | MT7981/MT7986 | GL.iNet MT3000, BananaPi R3 |
|
||||
| `rockchip-armv8` | RK3328/RK3399 | NanoPi R4S, R5S, FriendlyARM |
|
||||
| `bcm27xx-bcm2711` | BCM2711 | Raspberry Pi 4, Compute Module 4 |
|
||||
|
||||
### ARM 32-bit
|
||||
|
||||
| Target | Architecture | Devices |
|
||||
|--------|--------------|---------|
|
||||
| `arm-cortex-a7-neon` | Cortex-A7 | Orange Pi, BananaPi, Allwinner |
|
||||
| `arm-cortex-a9-neon` | Cortex-A9 | Linksys WRT, Turris Omnia |
|
||||
| `arm-cortex-a15-neon` | Cortex-A15 | QEMU ARM |
|
||||
| `qualcomm-ipq40xx` | IPQ40xx | Google WiFi, Zyxel NBG6617 |
|
||||
| `qualcomm-ipq806x` | IPQ806x | Netgear R7800, R7500 |
|
||||
|
||||
### MIPS
|
||||
|
||||
| Target | Architecture | Devices |
|
||||
|--------|--------------|---------|
|
||||
| `mips-24kc` | MIPS 24Kc | TP-Link Archer, Ubiquiti |
|
||||
| `mipsel-24kc` | MIPS LE 24Kc | Xiaomi, GL.iNet, Netgear |
|
||||
| `mipsel-74kc` | MIPS LE 74Kc | Broadcom BCM47xx |
|
||||
|
||||
### x86
|
||||
|
||||
| Target | Architecture | Devices |
|
||||
|--------|--------------|---------|
|
||||
| `x86-64` | x86_64 | PC, VMs, Docker, Proxmox |
|
||||
| `x86-generic` | i386 | Legacy PC, old Atom |
|
||||
|
||||
## 🚀 Utilisation
|
||||
|
||||
### Compilation Automatique
|
||||
|
||||
Les packages sont compilés automatiquement lors de :
|
||||
|
||||
1. **Push sur `main`/`master`** : Compilation de test
|
||||
2. **Pull Request** : Validation et test
|
||||
3. **Tag `v*`** : Création de release avec tous les packages
|
||||
|
||||
### Compilation Manuelle
|
||||
|
||||
1. Aller dans **Actions** → **Build OpenWrt Packages**
|
||||
2. Cliquer sur **Run workflow**
|
||||
3. Sélectionner :
|
||||
- **OpenWrt version** : 23.05.5, 22.03.7, ou SNAPSHOT
|
||||
- **Architectures** : `all` ou liste séparée par virgules
|
||||
|
||||
```
|
||||
# Exemples d'architectures
|
||||
all # Toutes les architectures
|
||||
x86-64 # Uniquement x86_64
|
||||
aarch64-cortex-a53,aarch64-cortex-a72 # GlobalScale devices
|
||||
mips-24kc,mipsel-24kc # MIPS routeurs
|
||||
```
|
||||
|
||||
### Téléchargement des Artifacts
|
||||
|
||||
1. Aller dans **Actions** → Sélectionner un workflow
|
||||
2. Cliquer sur le run souhaité
|
||||
3. Télécharger les **Artifacts** en bas de page
|
||||
|
||||
Les artifacts sont organisés par architecture :
|
||||
```
|
||||
packages-x86-64/
|
||||
├── luci-app-crowdsec-dashboard_1.0.0-1_all.ipk
|
||||
├── luci-app-netdata-dashboard_1.0.0-1_all.ipk
|
||||
├── ...
|
||||
└── SHA256SUMS
|
||||
```
|
||||
|
||||
## 📁 Structure du Dépôt
|
||||
|
||||
```
|
||||
secubox/
|
||||
├── .github/
|
||||
│ └── workflows/
|
||||
│ ├── build-openwrt-packages.yml # Build principal
|
||||
│ └── test-validate.yml # Tests & validation
|
||||
├── luci-app-crowdsec-dashboard/
|
||||
│ ├── Makefile
|
||||
│ ├── htdocs/luci-static/resources/
|
||||
│ │ ├── view/crowdsec/ # JavaScript views
|
||||
│ │ └── crowdsec/ # API & CSS
|
||||
│ └── root/
|
||||
│ ├── etc/config/ # UCI config
|
||||
│ └── usr/
|
||||
│ ├── libexec/rpcd/ # RPCD backend
|
||||
│ └── share/
|
||||
│ ├── luci/menu.d/ # Menu JSON
|
||||
│ └── rpcd/acl.d/ # ACL JSON
|
||||
├── luci-app-netdata-dashboard/
|
||||
├── luci-app-netifyd-dashboard/
|
||||
├── luci-app-wireguard-dashboard/
|
||||
├── luci-app-network-modes/
|
||||
├── luci-app-client-guardian/
|
||||
├── luci-app-system-hub/
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## 🔧 Créer un Nouveau Package
|
||||
|
||||
1. Copier le template :
|
||||
```bash
|
||||
cp -r templates/luci-app-template luci-app-nouveau
|
||||
```
|
||||
|
||||
2. Éditer `Makefile` :
|
||||
```makefile
|
||||
PKG_NAME:=luci-app-nouveau
|
||||
PKG_VERSION:=1.0.0
|
||||
LUCI_TITLE:=Mon Nouveau Dashboard
|
||||
LUCI_DEPENDS:=+luci-base +nouveau-backend
|
||||
```
|
||||
|
||||
3. Créer les fichiers requis :
|
||||
```bash
|
||||
luci-app-nouveau/
|
||||
├── Makefile
|
||||
├── htdocs/luci-static/resources/
|
||||
│ ├── view/nouveau/
|
||||
│ │ └── overview.js
|
||||
│ └── nouveau/
|
||||
│ ├── api.js
|
||||
│ └── dashboard.css
|
||||
└── root/
|
||||
└── usr/share/
|
||||
├── luci/menu.d/luci-app-nouveau.json
|
||||
└── rpcd/acl.d/luci-app-nouveau.json
|
||||
```
|
||||
|
||||
4. Commit et push :
|
||||
```bash
|
||||
git add luci-app-nouveau/
|
||||
git commit -m "feat: add luci-app-nouveau"
|
||||
git push
|
||||
```
|
||||
|
||||
## 🏷️ Créer une Release
|
||||
|
||||
```bash
|
||||
# Créer un tag versionné
|
||||
git tag -a v1.2.0 -m "Release 1.2.0"
|
||||
git push origin v1.2.0
|
||||
```
|
||||
|
||||
La release sera créée automatiquement avec :
|
||||
- Archives `.tar.gz` par architecture
|
||||
- Archive globale toutes architectures
|
||||
- Checksums SHA256
|
||||
- Notes de release générées
|
||||
|
||||
## ⚙️ Configuration CI
|
||||
|
||||
### Variables d'Environnement
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `OPENWRT_VERSION` | `23.05.5` | Version OpenWrt SDK |
|
||||
|
||||
### Secrets Requis
|
||||
|
||||
Aucun secret requis pour la compilation. Le `GITHUB_TOKEN` par défaut suffit pour créer les releases.
|
||||
|
||||
### Cache
|
||||
|
||||
Le SDK OpenWrt est mis en cache par architecture pour accélérer les builds suivants.
|
||||
|
||||
## 🧪 Tests & Validation
|
||||
|
||||
Le workflow `test-validate.yml` vérifie :
|
||||
|
||||
- ✅ Structure des Makefiles (champs requis)
|
||||
- ✅ Syntaxe JSON (menu, ACL)
|
||||
- ✅ Syntaxe JavaScript (views)
|
||||
- ✅ Scripts shell (shellcheck)
|
||||
- ✅ Permissions des fichiers
|
||||
- ✅ Build test sur x86_64
|
||||
|
||||
## 📊 Matrice de Compatibilité
|
||||
|
||||
| OpenWrt | Status | Notes |
|
||||
|---------|--------|-------|
|
||||
| 24.10.x | 🔜 Prévu | En attente release |
|
||||
| 23.05.x | ✅ Supporté | Recommandé |
|
||||
| 22.03.x | ✅ Supporté | LTS |
|
||||
| 21.02.x | ⚠️ Partiel | Fin de support |
|
||||
| SNAPSHOT | ✅ Supporté | Instable |
|
||||
|
||||
## 🔗 Liens
|
||||
|
||||
- [OpenWrt SDK Documentation](https://openwrt.org/docs/guide-developer/using_the_sdk)
|
||||
- [LuCI Development Guide](https://github.com/openwrt/luci/wiki)
|
||||
- [CyberMind.fr](https://cybermind.fr)
|
||||
- [SecuBox Project](https://cybermind.fr/secubox)
|
||||
|
||||
## 📄 License
|
||||
|
||||
Apache-2.0 © 2025 CyberMind.fr
|
||||
|
||||
---
|
||||
|
||||
**Made with ❤️ in France 🇫🇷**
|
||||
551
build-openwrt-packages.yml
Normal file
551
build-openwrt-packages.yml
Normal file
@ -0,0 +1,551 @@
|
||||
name: Build OpenWrt Packages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, master, develop]
|
||||
tags:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
branches: [main, master]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
openwrt_version:
|
||||
description: 'OpenWrt version'
|
||||
required: true
|
||||
default: '23.05.5'
|
||||
type: choice
|
||||
options:
|
||||
- '23.05.5'
|
||||
- '23.05.4'
|
||||
- '22.03.7'
|
||||
- 'SNAPSHOT'
|
||||
architectures:
|
||||
description: 'Architectures to build (comma-separated or "all")'
|
||||
required: false
|
||||
default: 'all'
|
||||
|
||||
env:
|
||||
OPENWRT_VERSION: ${{ github.event.inputs.openwrt_version || '23.05.5' }}
|
||||
|
||||
jobs:
|
||||
# ============================================
|
||||
# Determine build matrix
|
||||
# ============================================
|
||||
setup:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Determine version
|
||||
id: version
|
||||
run: |
|
||||
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
|
||||
VERSION="${{ github.ref_name }}"
|
||||
else
|
||||
VERSION="0.0.0-$(git rev-parse --short HEAD)"
|
||||
fi
|
||||
echo "version=${VERSION#v}" >> $GITHUB_OUTPUT
|
||||
echo "📦 Package version: ${VERSION#v}"
|
||||
|
||||
- name: Set build matrix
|
||||
id: set-matrix
|
||||
run: |
|
||||
# Full architecture matrix for OpenWrt
|
||||
# Format: target/subtarget -> SDK name mapping
|
||||
ALL_TARGETS=$(cat << 'EOF'
|
||||
{
|
||||
"include": [
|
||||
{
|
||||
"target": "x86-64",
|
||||
"arch": "x86_64",
|
||||
"sdk_name": "x86-64",
|
||||
"description": "x86 64-bit (PC, VM, containers)"
|
||||
},
|
||||
{
|
||||
"target": "x86-generic",
|
||||
"arch": "i386_pentium4",
|
||||
"sdk_name": "x86-generic",
|
||||
"description": "x86 32-bit (legacy PC)"
|
||||
},
|
||||
{
|
||||
"target": "aarch64-generic",
|
||||
"arch": "aarch64_generic",
|
||||
"sdk_name": "armsr-armv8",
|
||||
"description": "ARM 64-bit generic (RPi4, Rock64)"
|
||||
},
|
||||
{
|
||||
"target": "aarch64-cortex-a53",
|
||||
"arch": "aarch64_cortex-a53",
|
||||
"sdk_name": "mvebu-cortexa53",
|
||||
"description": "ARM Cortex-A53 (ESPRESSObin, Sheeva64)"
|
||||
},
|
||||
{
|
||||
"target": "aarch64-cortex-a72",
|
||||
"arch": "aarch64_cortex-a72",
|
||||
"sdk_name": "mvebu-cortexa72",
|
||||
"description": "ARM Cortex-A72 (MOCHAbin, MACCHIATObin)"
|
||||
},
|
||||
{
|
||||
"target": "arm-cortex-a7-neon",
|
||||
"arch": "arm_cortex-a7_neon-vfpv4",
|
||||
"sdk_name": "sunxi-cortexa7",
|
||||
"description": "ARM Cortex-A7 (Orange Pi, Banana Pi)"
|
||||
},
|
||||
{
|
||||
"target": "arm-cortex-a9-neon",
|
||||
"arch": "arm_cortex-a9_neon",
|
||||
"sdk_name": "mvebu-cortexa9",
|
||||
"description": "ARM Cortex-A9 (Linksys WRT, Turris)"
|
||||
},
|
||||
{
|
||||
"target": "arm-cortex-a15-neon",
|
||||
"arch": "arm_cortex-a15_neon-vfpv4",
|
||||
"sdk_name": "armvirt-32",
|
||||
"description": "ARM Cortex-A15 (QEMU ARM)"
|
||||
},
|
||||
{
|
||||
"target": "mips-24kc",
|
||||
"arch": "mips_24kc",
|
||||
"sdk_name": "ath79-generic",
|
||||
"description": "MIPS 24Kc (TP-Link, Ubiquiti)"
|
||||
},
|
||||
{
|
||||
"target": "mipsel-24kc",
|
||||
"arch": "mipsel_24kc",
|
||||
"sdk_name": "ramips-mt7621",
|
||||
"description": "MIPS Little-Endian (Xiaomi, GL.iNet)"
|
||||
},
|
||||
{
|
||||
"target": "mipsel-74kc",
|
||||
"arch": "mipsel_74kc",
|
||||
"sdk_name": "bcm47xx-mips74k",
|
||||
"description": "MIPS 74Kc (Broadcom routers)"
|
||||
},
|
||||
{
|
||||
"target": "mediatek-filogic",
|
||||
"arch": "aarch64_cortex-a53",
|
||||
"sdk_name": "mediatek-filogic",
|
||||
"description": "MediaTek Filogic (MT7981, MT7986)"
|
||||
},
|
||||
{
|
||||
"target": "qualcomm-ipq40xx",
|
||||
"arch": "arm_cortex-a7_neon-vfpv4",
|
||||
"sdk_name": "ipq40xx-generic",
|
||||
"description": "Qualcomm IPQ40xx (Google WiFi, Zyxel)"
|
||||
},
|
||||
{
|
||||
"target": "qualcomm-ipq806x",
|
||||
"arch": "arm_cortex-a15_neon-vfpv4",
|
||||
"sdk_name": "ipq806x-generic",
|
||||
"description": "Qualcomm IPQ806x (Netgear R7800)"
|
||||
},
|
||||
{
|
||||
"target": "rockchip-armv8",
|
||||
"arch": "aarch64_generic",
|
||||
"sdk_name": "rockchip-armv8",
|
||||
"description": "Rockchip (NanoPi R4S, R5S)"
|
||||
},
|
||||
{
|
||||
"target": "bcm27xx-bcm2711",
|
||||
"arch": "aarch64_cortex-a72",
|
||||
"sdk_name": "bcm27xx-bcm2711",
|
||||
"description": "Raspberry Pi 4"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
INPUT_ARCHS="${{ github.event.inputs.architectures }}"
|
||||
if [[ -z "$INPUT_ARCHS" || "$INPUT_ARCHS" == "all" ]]; then
|
||||
MATRIX="$ALL_TARGETS"
|
||||
else
|
||||
# Filter matrix based on input
|
||||
MATRIX=$(echo "$ALL_TARGETS" | jq -c --arg archs "$INPUT_ARCHS" '
|
||||
.include |= map(select(.target as $t | $archs | split(",") | map(gsub("^\\s+|\\s+$";"")) | any(. == $t or . == "all")))
|
||||
')
|
||||
fi
|
||||
|
||||
echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
|
||||
echo "📋 Build matrix:"
|
||||
echo "$MATRIX" | jq '.'
|
||||
|
||||
# ============================================
|
||||
# Build packages for each architecture
|
||||
# ============================================
|
||||
build:
|
||||
needs: setup
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.setup.outputs.matrix) }}
|
||||
|
||||
name: Build ${{ matrix.target }}
|
||||
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Free disk space
|
||||
run: |
|
||||
echo "🧹 Cleaning up disk space..."
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /usr/local/lib/android
|
||||
sudo rm -rf /opt/ghc
|
||||
sudo rm -rf /opt/hostedtoolcache/CodeQL
|
||||
sudo docker image prune --all --force
|
||||
df -h
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
build-essential clang flex bison g++ gawk \
|
||||
gcc-multilib g++-multilib gettext git libncurses5-dev \
|
||||
libssl-dev python3-distutils python3-setuptools rsync \
|
||||
swig unzip zlib1g-dev file wget curl jq
|
||||
|
||||
- name: Cache OpenWrt SDK
|
||||
uses: actions/cache@v4
|
||||
id: cache-sdk
|
||||
with:
|
||||
path: ~/sdk
|
||||
key: openwrt-sdk-${{ env.OPENWRT_VERSION }}-${{ matrix.sdk_name }}
|
||||
|
||||
- name: Download OpenWrt SDK
|
||||
if: steps.cache-sdk.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "📥 Downloading SDK for ${{ matrix.description }}..."
|
||||
|
||||
VERSION="${{ env.OPENWRT_VERSION }}"
|
||||
SDK_NAME="${{ matrix.sdk_name }}"
|
||||
|
||||
if [[ "$VERSION" == "SNAPSHOT" ]]; then
|
||||
BASE_URL="https://downloads.openwrt.org/snapshots/targets"
|
||||
else
|
||||
BASE_URL="https://downloads.openwrt.org/releases/${VERSION}/targets"
|
||||
fi
|
||||
|
||||
# Parse target/subtarget from sdk_name
|
||||
TARGET=$(echo "$SDK_NAME" | cut -d'-' -f1)
|
||||
SUBTARGET=$(echo "$SDK_NAME" | cut -d'-' -f2-)
|
||||
|
||||
SDK_URL="${BASE_URL}/${TARGET}/${SUBTARGET}"
|
||||
|
||||
echo "🔍 Looking for SDK at: $SDK_URL"
|
||||
|
||||
# Find SDK filename
|
||||
SDK_FILE=$(curl -sL "$SDK_URL/" | grep -oP 'openwrt-sdk[^"]+\.tar\.(xz|zst)' | head -1)
|
||||
|
||||
if [[ -z "$SDK_FILE" ]]; then
|
||||
echo "⚠️ SDK not found, trying alternative URL pattern..."
|
||||
SDK_FILE=$(curl -sL "$SDK_URL/sha256sums" | grep -oP 'openwrt-sdk[^\s]+' | head -1)
|
||||
fi
|
||||
|
||||
if [[ -z "$SDK_FILE" ]]; then
|
||||
echo "❌ Could not find SDK for ${{ matrix.target }}"
|
||||
echo "🔗 Checked: $SDK_URL"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "📦 Downloading: $SDK_FILE"
|
||||
wget -q --show-progress "${SDK_URL}/${SDK_FILE}" -O /tmp/sdk.tar.xz || \
|
||||
wget -q --show-progress "${SDK_URL}/${SDK_FILE}" -O /tmp/sdk.tar.zst
|
||||
|
||||
mkdir -p ~/sdk
|
||||
if [[ "$SDK_FILE" == *.zst ]]; then
|
||||
zstd -d /tmp/sdk.tar.zst -o /tmp/sdk.tar
|
||||
tar -xf /tmp/sdk.tar -C ~/sdk --strip-components=1
|
||||
else
|
||||
tar -xf /tmp/sdk.tar.xz -C ~/sdk --strip-components=1
|
||||
fi
|
||||
|
||||
echo "✅ SDK extracted to ~/sdk"
|
||||
|
||||
- name: Prepare SDK
|
||||
run: |
|
||||
cd ~/sdk
|
||||
|
||||
# Update feeds
|
||||
echo "📋 Updating feeds..."
|
||||
./scripts/feeds update -a
|
||||
./scripts/feeds install -a
|
||||
|
||||
# Configure SDK
|
||||
echo "⚙️ Configuring SDK..."
|
||||
make defconfig
|
||||
|
||||
- name: Copy packages to SDK
|
||||
run: |
|
||||
echo "📁 Copying SecuBox packages to SDK..."
|
||||
|
||||
# List of our packages
|
||||
PACKAGES=(
|
||||
"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"
|
||||
)
|
||||
|
||||
# Create package directory
|
||||
mkdir -p ~/sdk/package/secubox
|
||||
|
||||
# Copy each package if it exists
|
||||
for pkg in "${PACKAGES[@]}"; do
|
||||
if [[ -d "$GITHUB_WORKSPACE/$pkg" ]]; then
|
||||
echo " 📦 $pkg"
|
||||
cp -r "$GITHUB_WORKSPACE/$pkg" ~/sdk/package/secubox/
|
||||
else
|
||||
echo " ⚠️ $pkg not found in repository"
|
||||
fi
|
||||
done
|
||||
|
||||
# If packages are in a subdirectory
|
||||
if [[ -d "$GITHUB_WORKSPACE/packages" ]]; then
|
||||
cp -r "$GITHUB_WORKSPACE/packages/"* ~/sdk/package/secubox/ 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# List what we have
|
||||
echo "📋 Packages in SDK:"
|
||||
ls -la ~/sdk/package/secubox/ || echo " (empty)"
|
||||
|
||||
- name: Update package version
|
||||
run: |
|
||||
VERSION="${{ needs.setup.outputs.version }}"
|
||||
echo "📝 Setting package version to: $VERSION"
|
||||
|
||||
# Update Makefile version in each package
|
||||
for makefile in ~/sdk/package/secubox/*/Makefile; do
|
||||
if [[ -f "$makefile" ]]; then
|
||||
sed -i "s/PKG_VERSION:=.*/PKG_VERSION:=$VERSION/" "$makefile"
|
||||
sed -i "s/PKG_RELEASE:=.*/PKG_RELEASE:=1/" "$makefile"
|
||||
echo " ✅ Updated: $(dirname $makefile | xargs basename)"
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Build packages
|
||||
run: |
|
||||
cd ~/sdk
|
||||
|
||||
echo "🔨 Building SecuBox packages for ${{ matrix.description }}..."
|
||||
|
||||
# Enable our packages
|
||||
for pkg in ~/sdk/package/secubox/*/; do
|
||||
PKG_NAME=$(basename "$pkg")
|
||||
echo "CONFIG_PACKAGE_${PKG_NAME}=m" >> .config
|
||||
done
|
||||
|
||||
make defconfig
|
||||
|
||||
# Build with verbose output on error
|
||||
make package/secubox/compile V=s -j$(nproc) || {
|
||||
echo "❌ Build failed, retrying with single thread..."
|
||||
make package/secubox/compile V=s -j1
|
||||
}
|
||||
|
||||
# Generate package index
|
||||
make package/index V=s
|
||||
|
||||
- name: Collect artifacts
|
||||
id: collect
|
||||
run: |
|
||||
echo "📦 Collecting built packages..."
|
||||
|
||||
mkdir -p $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}
|
||||
|
||||
# Find and copy .ipk files
|
||||
find ~/sdk/bin -name "*.ipk" -exec cp {} $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}/ \;
|
||||
|
||||
# Copy package index
|
||||
find ~/sdk/bin -name "Packages*" -exec cp {} $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}/ \; 2>/dev/null || true
|
||||
|
||||
# List artifacts
|
||||
echo "📋 Built packages for ${{ matrix.target }}:"
|
||||
ls -la $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}/
|
||||
|
||||
# Count packages
|
||||
PKG_COUNT=$(find $GITHUB_WORKSPACE/artifacts/${{ matrix.target }} -name "*.ipk" | wc -l)
|
||||
echo "pkg_count=$PKG_COUNT" >> $GITHUB_OUTPUT
|
||||
|
||||
if [[ $PKG_COUNT -eq 0 ]]; then
|
||||
echo "⚠️ No packages built!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Create checksums
|
||||
run: |
|
||||
cd $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}
|
||||
sha256sum *.ipk > SHA256SUMS
|
||||
echo "✅ Checksums created"
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: packages-${{ matrix.target }}
|
||||
path: artifacts/${{ matrix.target }}/
|
||||
retention-days: 30
|
||||
|
||||
# ============================================
|
||||
# Create combined release
|
||||
# ============================================
|
||||
release:
|
||||
needs: [setup, build]
|
||||
runs-on: ubuntu-latest
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: packages
|
||||
pattern: packages-*
|
||||
|
||||
- name: Organize packages
|
||||
run: |
|
||||
echo "📁 Organizing release packages..."
|
||||
|
||||
VERSION="${{ needs.setup.outputs.version }}"
|
||||
mkdir -p release
|
||||
|
||||
# Create architecture-specific archives
|
||||
for arch_dir in packages/packages-*/; do
|
||||
ARCH=$(basename "$arch_dir" | sed 's/packages-//')
|
||||
echo "📦 Processing $ARCH..."
|
||||
|
||||
# Create tarball
|
||||
tar -czf "release/secubox-${VERSION}-${ARCH}.tar.gz" -C "$arch_dir" .
|
||||
|
||||
# Copy individual .ipk files to flat structure
|
||||
mkdir -p "release/ipk/${ARCH}"
|
||||
cp "$arch_dir"/*.ipk "release/ipk/${ARCH}/" 2>/dev/null || true
|
||||
done
|
||||
|
||||
# Create "all architectures" mega-archive
|
||||
tar -czf "release/secubox-${VERSION}-all-architectures.tar.gz" -C packages .
|
||||
|
||||
# Create release notes
|
||||
cat > release/RELEASE_NOTES.md << EOF
|
||||
# SecuBox $VERSION
|
||||
|
||||
## 📦 Packages Included
|
||||
|
||||
- luci-app-crowdsec-dashboard - CrowdSec Security Dashboard
|
||||
- luci-app-netdata-dashboard - Netdata Monitoring Dashboard
|
||||
- luci-app-netifyd-dashboard - Netifyd DPI Dashboard
|
||||
- luci-app-wireguard-dashboard - WireGuard VPN Dashboard
|
||||
- luci-app-network-modes - Network Mode Switcher
|
||||
- luci-app-client-guardian - NAC & Captive Portal
|
||||
- luci-app-system-hub - System Hub Control Center
|
||||
|
||||
## 🏗️ Supported Architectures
|
||||
|
||||
| Target | Architecture | Description |
|
||||
|--------|--------------|-------------|
|
||||
| x86-64 | x86_64 | PC, VMs, Containers |
|
||||
| aarch64-cortex-a53 | aarch64 | ESPRESSObin, Sheeva64 |
|
||||
| aarch64-cortex-a72 | aarch64 | MOCHAbin, RPi4 |
|
||||
| arm-cortex-a7 | arm | Orange Pi, Banana Pi |
|
||||
| arm-cortex-a9 | arm | Linksys WRT, Turris |
|
||||
| mips-24kc | mips | TP-Link, Ubiquiti |
|
||||
| mipsel-24kc | mipsel | Xiaomi, GL.iNet |
|
||||
| mediatek-filogic | aarch64 | MT7981, MT7986 |
|
||||
| qualcomm-ipq40xx | arm | Google WiFi |
|
||||
| rockchip-armv8 | aarch64 | NanoPi R4S, R5S |
|
||||
|
||||
## 📥 Installation
|
||||
|
||||
\`\`\`bash
|
||||
# Download package for your architecture
|
||||
opkg update
|
||||
opkg install luci-app-crowdsec-dashboard_${VERSION}_*.ipk
|
||||
# ... install other packages as needed
|
||||
\`\`\`
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
- [Documentation](https://cybermind.fr/docs/secubox)
|
||||
- [GitHub](https://github.com/gkerma)
|
||||
- [CyberMind.fr](https://cybermind.fr)
|
||||
|
||||
---
|
||||
Built with OpenWrt SDK ${{ env.OPENWRT_VERSION }}
|
||||
EOF
|
||||
|
||||
echo "✅ Release organized"
|
||||
ls -la release/
|
||||
|
||||
- name: Create global checksums
|
||||
run: |
|
||||
cd release
|
||||
sha256sum *.tar.gz > SHA256SUMS
|
||||
echo "✅ Global checksums created"
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
name: SecuBox ${{ needs.setup.outputs.version }}
|
||||
body_path: release/RELEASE_NOTES.md
|
||||
files: |
|
||||
release/*.tar.gz
|
||||
release/SHA256SUMS
|
||||
draft: false
|
||||
prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') || contains(github.ref, 'rc') }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# ============================================
|
||||
# Build status summary
|
||||
# ============================================
|
||||
summary:
|
||||
needs: [setup, build]
|
||||
runs-on: ubuntu-latest
|
||||
if: always()
|
||||
|
||||
steps:
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: packages
|
||||
pattern: packages-*
|
||||
continue-on-error: true
|
||||
|
||||
- name: Generate build summary
|
||||
run: |
|
||||
echo "# 📊 SecuBox Build Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Version:** ${{ needs.setup.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**OpenWrt:** ${{ env.OPENWRT_VERSION }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "## Build Results" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Architecture | Status | Packages |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|--------------|--------|----------|" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
for arch_dir in packages/packages-*/; do
|
||||
if [[ -d "$arch_dir" ]]; then
|
||||
ARCH=$(basename "$arch_dir" | sed 's/packages-//')
|
||||
PKG_COUNT=$(find "$arch_dir" -name "*.ipk" 2>/dev/null | wc -l)
|
||||
if [[ $PKG_COUNT -gt 0 ]]; then
|
||||
echo "| $ARCH | ✅ Success | $PKG_COUNT |" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "| $ARCH | ⚠️ No packages | 0 |" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "## 📦 Artifacts" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Download artifacts from the Actions tab above." >> $GITHUB_STEP_SUMMARY
|
||||
398
build-secubox-images.yml
Normal file
398
build-secubox-images.yml
Normal file
@ -0,0 +1,398 @@
|
||||
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 }}
|
||||
|
||||
jobs:
|
||||
# ============================================
|
||||
# Build firmware images for GlobalScale devices
|
||||
# ============================================
|
||||
build-image:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- device: espressobin-v7
|
||||
target: mvebu
|
||||
subtarget: cortexa53
|
||||
profile: globalscale_espressobin
|
||||
description: "ESPRESSObin V7 (1-2GB DDR4)"
|
||||
enabled: ${{ github.event.inputs.device == 'espressobin-v7' || github.event.inputs.device == 'all' }}
|
||||
|
||||
- device: espressobin-ultra
|
||||
target: mvebu
|
||||
subtarget: cortexa53
|
||||
profile: globalscale_espressobin-ultra
|
||||
description: "ESPRESSObin Ultra (PoE, WiFi)"
|
||||
enabled: ${{ github.event.inputs.device == 'espressobin-ultra' || github.event.inputs.device == 'all' }}
|
||||
|
||||
- device: sheeva64
|
||||
target: mvebu
|
||||
subtarget: cortexa53
|
||||
profile: globalscale_sheeva64
|
||||
description: "Sheeva64 (Plug computer)"
|
||||
enabled: ${{ github.event.inputs.device == 'sheeva64' || github.event.inputs.device == 'all' }}
|
||||
|
||||
- device: sheeva64-wifi
|
||||
target: mvebu
|
||||
subtarget: cortexa53
|
||||
profile: globalscale_sheeva64
|
||||
description: "Sheeva64 WiFi (802.11ac + BT)"
|
||||
enabled: ${{ github.event.inputs.device == 'sheeva64-wifi' || github.event.inputs.device == 'all' }}
|
||||
|
||||
- device: mochabin
|
||||
target: mvebu
|
||||
subtarget: cortexa72
|
||||
profile: globalscale_mochabin
|
||||
description: "MOCHAbin (Quad-core A72, 10G)"
|
||||
enabled: ${{ github.event.inputs.device == 'mochabin' || github.event.inputs.device == 'all' }}
|
||||
|
||||
name: ${{ matrix.description }}
|
||||
if: ${{ matrix.enabled != 'false' }}
|
||||
|
||||
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-distutils python3-setuptools 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
|
||||
./scripts/feeds update -a
|
||||
./scripts/feeds install -a
|
||||
|
||||
- name: Copy SecuBox packages
|
||||
if: ${{ github.event.inputs.include_secubox == 'true' }}
|
||||
run: |
|
||||
mkdir -p openwrt/package/secubox
|
||||
|
||||
for pkg in luci-app-*/; do
|
||||
if [[ -d "$pkg" ]]; then
|
||||
echo "📦 Adding $pkg"
|
||||
cp -r "$pkg" openwrt/package/secubox/
|
||||
fi
|
||||
done
|
||||
|
||||
- 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
|
||||
make defconfig
|
||||
|
||||
- name: Download packages
|
||||
run: |
|
||||
cd openwrt
|
||||
make download -j$(nproc) V=s || make download -j1 V=s
|
||||
|
||||
- name: Build firmware
|
||||
run: |
|
||||
cd openwrt
|
||||
|
||||
echo "🔨 Building firmware for ${{ matrix.description }}..."
|
||||
echo "⏱️ This may take 1-2 hours..."
|
||||
|
||||
make -j$(nproc) V=s 2>&1 | tee build.log || {
|
||||
echo "❌ Build failed, retrying with single thread..."
|
||||
make -j1 V=s 2>&1 | tee build-retry.log
|
||||
}
|
||||
|
||||
- name: Prepare artifacts
|
||||
run: |
|
||||
mkdir -p artifacts
|
||||
|
||||
# Copy firmware images
|
||||
find openwrt/bin/targets -name "*.img.gz" -exec cp {} artifacts/ \;
|
||||
find openwrt/bin/targets -name "*.bin" -exec cp {} artifacts/ \;
|
||||
find openwrt/bin/targets -name "*sysupgrade*" -exec cp {} artifacts/ \;
|
||||
find openwrt/bin/targets -name "*factory*" -exec cp {} artifacts/ \;
|
||||
|
||||
# Copy packages
|
||||
mkdir -p artifacts/packages
|
||||
find openwrt/bin/packages -name "luci-app-*secubox*.ipk" -exec cp {} artifacts/packages/ \; 2>/dev/null || true
|
||||
find openwrt/bin/packages -name "luci-app-*dashboard*.ipk" -exec cp {} artifacts/packages/ \; 2>/dev/null || true
|
||||
|
||||
# Generate checksums
|
||||
cd artifacts
|
||||
sha256sum * > SHA256SUMS 2>/dev/null || true
|
||||
|
||||
# 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 }}
|
||||
EOF
|
||||
|
||||
echo "📦 Artifacts:"
|
||||
ls -la
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: secubox-${{ matrix.device }}-${{ env.OPENWRT_VERSION }}
|
||||
path: artifacts/
|
||||
retention-days: 30
|
||||
|
||||
# ============================================
|
||||
# Create combined release for all devices
|
||||
# ============================================
|
||||
release:
|
||||
needs: 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 }}
|
||||
1
luci-app-client-guardian
Submodule
1
luci-app-client-guardian
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit ad209f3982d9722f5d9e9da90e4489176633a65c
|
||||
1
luci-app-crowdsec-dashboard
Submodule
1
luci-app-crowdsec-dashboard
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit f5920202d2b1c0652147c61e6b5c0a58c687c4ca
|
||||
1
luci-app-netdata-dashboard
Submodule
1
luci-app-netdata-dashboard
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 6dca2579d3ded391ee5158ccd6d31140239c4f6d
|
||||
1
luci-app-netifyd-dashboard
Submodule
1
luci-app-netifyd-dashboard
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 944342f7cf10a36ffd57f51f898f7a197e9167f2
|
||||
1
luci-app-network-modes
Submodule
1
luci-app-network-modes
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit f909422b1888a7b52fa7ed3a0d3a5a73010beef0
|
||||
1
luci-app-system-hub
Submodule
1
luci-app-system-hub
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 7ddc649872109f61e3e2bffc6900d11e3721bd2d
|
||||
1
luci-app-wireguard-dashboard
Submodule
1
luci-app-wireguard-dashboard
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 4f9120c0566bd0c649d3f7b607c6f91e97e5a0ba
|
||||
128
templates/Makefile.template
Normal file
128
templates/Makefile.template
Normal file
@ -0,0 +1,128 @@
|
||||
# SecuBox LuCI Application Makefile Template
|
||||
# Copyright (C) 2025 CyberMind.fr
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
# ============================================
|
||||
# Package Information
|
||||
# ============================================
|
||||
PKG_NAME:=luci-app-TEMPLATE-dashboard
|
||||
PKG_VERSION:=1.0.0
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
PKG_MAINTAINER:=Gandalf <contact@cybermind.fr>
|
||||
|
||||
# ============================================
|
||||
# LuCI Configuration
|
||||
# ============================================
|
||||
LUCI_TITLE:=LuCI TEMPLATE Dashboard
|
||||
LUCI_DESCRIPTION:=Dashboard for TEMPLATE on OpenWrt
|
||||
LUCI_DEPENDS:=+luci-base +TEMPLATE
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
# Optional: Extra dependencies
|
||||
# +luci-lib-jsonc +rpcd +uhttpd
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
# ============================================
|
||||
# Package Definition
|
||||
# ============================================
|
||||
define Package/$(PKG_NAME)
|
||||
SECTION:=luci
|
||||
CATEGORY:=LuCI
|
||||
SUBMENU:=3. Applications
|
||||
TITLE:=$(LUCI_TITLE)
|
||||
DEPENDS:=$(LUCI_DEPENDS)
|
||||
PKGARCH:=$(LUCI_PKGARCH)
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/description
|
||||
$(LUCI_DESCRIPTION)
|
||||
|
||||
Features:
|
||||
- Real-time status monitoring
|
||||
- Configuration management
|
||||
- Interactive dashboard
|
||||
- System integration
|
||||
endef
|
||||
|
||||
# ============================================
|
||||
# Installation
|
||||
# ============================================
|
||||
define Package/$(PKG_NAME)/install
|
||||
# JavaScript views
|
||||
$(INSTALL_DIR) $(1)/www/luci-static/resources/view/TEMPLATE
|
||||
$(INSTALL_DATA) ./htdocs/luci-static/resources/view/TEMPLATE/*.js \
|
||||
$(1)/www/luci-static/resources/view/TEMPLATE/
|
||||
|
||||
# API and CSS
|
||||
$(INSTALL_DIR) $(1)/www/luci-static/resources/TEMPLATE
|
||||
$(INSTALL_DATA) ./htdocs/luci-static/resources/TEMPLATE/*.js \
|
||||
$(1)/www/luci-static/resources/TEMPLATE/
|
||||
$(INSTALL_DATA) ./htdocs/luci-static/resources/TEMPLATE/*.css \
|
||||
$(1)/www/luci-static/resources/TEMPLATE/
|
||||
|
||||
# Menu configuration
|
||||
$(INSTALL_DIR) $(1)/usr/share/luci/menu.d
|
||||
$(INSTALL_DATA) ./root/usr/share/luci/menu.d/$(PKG_NAME).json \
|
||||
$(1)/usr/share/luci/menu.d/
|
||||
|
||||
# ACL configuration
|
||||
$(INSTALL_DIR) $(1)/usr/share/rpcd/acl.d
|
||||
$(INSTALL_DATA) ./root/usr/share/rpcd/acl.d/$(PKG_NAME).json \
|
||||
$(1)/usr/share/rpcd/acl.d/
|
||||
|
||||
# RPCD backend
|
||||
$(INSTALL_DIR) $(1)/usr/libexec/rpcd
|
||||
$(INSTALL_BIN) ./root/usr/libexec/rpcd/TEMPLATE \
|
||||
$(1)/usr/libexec/rpcd/
|
||||
|
||||
# UCI default config (optional)
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_CONF) ./root/etc/config/TEMPLATE \
|
||||
$(1)/etc/config/
|
||||
|
||||
# UCI defaults (optional - runs on first install)
|
||||
# $(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||
# $(INSTALL_BIN) ./root/etc/uci-defaults/$(PKG_NAME) \
|
||||
# $(1)/etc/uci-defaults/
|
||||
endef
|
||||
|
||||
# ============================================
|
||||
# Post-installation
|
||||
# ============================================
|
||||
define Package/$(PKG_NAME)/postinst
|
||||
#!/bin/sh
|
||||
[ -n "$${IPKG_INSTROOT}" ] || {
|
||||
# Reload rpcd to register new methods
|
||||
/etc/init.d/rpcd reload 2>/dev/null || true
|
||||
|
||||
# Clear LuCI cache
|
||||
rm -rf /tmp/luci-modulecache 2>/dev/null || true
|
||||
rm -rf /tmp/luci-indexcache* 2>/dev/null || true
|
||||
|
||||
echo "$(PKG_NAME) installed successfully"
|
||||
}
|
||||
exit 0
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/postrm
|
||||
#!/bin/sh
|
||||
[ -n "$${IPKG_INSTROOT}" ] || {
|
||||
# Reload rpcd
|
||||
/etc/init.d/rpcd reload 2>/dev/null || true
|
||||
|
||||
# Clear LuCI cache
|
||||
rm -rf /tmp/luci-modulecache 2>/dev/null || true
|
||||
rm -rf /tmp/luci-indexcache* 2>/dev/null || true
|
||||
}
|
||||
exit 0
|
||||
endef
|
||||
|
||||
# ============================================
|
||||
# Build
|
||||
# ============================================
|
||||
$(eval $(call BuildPackage,$(PKG_NAME)))
|
||||
327
test-validate.yml
Normal file
327
test-validate.yml
Normal file
@ -0,0 +1,327 @@
|
||||
name: Test & Validate Packages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, master, develop]
|
||||
pull_request:
|
||||
branches: [main, master]
|
||||
|
||||
jobs:
|
||||
# ============================================
|
||||
# Lint and validate package structure
|
||||
# ============================================
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
name: Lint & Validate
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install validators
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y shellcheck jq
|
||||
|
||||
- name: Validate Makefile structure
|
||||
run: |
|
||||
echo "📋 Validating Makefile structure..."
|
||||
|
||||
ERRORS=0
|
||||
|
||||
for makefile in */Makefile; do
|
||||
if [[ -f "$makefile" ]]; then
|
||||
PKG=$(dirname "$makefile")
|
||||
echo " 🔍 Checking $PKG..."
|
||||
|
||||
# Required fields
|
||||
REQUIRED_FIELDS=(
|
||||
"PKG_NAME"
|
||||
"PKG_VERSION"
|
||||
"PKG_RELEASE"
|
||||
"PKG_LICENSE"
|
||||
"LUCI_TITLE"
|
||||
)
|
||||
|
||||
for field in "${REQUIRED_FIELDS[@]}"; do
|
||||
if ! grep -q "^${field}:=" "$makefile"; then
|
||||
echo " ❌ Missing: $field"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
# Check for include statements
|
||||
if ! grep -q "include.*luci.mk\|include.*package.mk" "$makefile"; then
|
||||
echo " ❌ Missing include statement (luci.mk or package.mk)"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $ERRORS -gt 0 ]]; then
|
||||
echo "❌ Found $ERRORS errors"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ All Makefiles valid"
|
||||
|
||||
- name: Validate JSON files
|
||||
run: |
|
||||
echo "📋 Validating JSON files..."
|
||||
|
||||
ERRORS=0
|
||||
|
||||
# Find all JSON files
|
||||
while IFS= read -r jsonfile; do
|
||||
echo " 🔍 Checking $jsonfile..."
|
||||
if ! jq empty "$jsonfile" 2>/dev/null; then
|
||||
echo " ❌ Invalid JSON"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
done < <(find . -name "*.json" -type f)
|
||||
|
||||
if [[ $ERRORS -gt 0 ]]; then
|
||||
echo "❌ Found $ERRORS JSON errors"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ All JSON files valid"
|
||||
|
||||
- name: Validate JavaScript syntax
|
||||
run: |
|
||||
echo "📋 Validating JavaScript files..."
|
||||
|
||||
# Install node for syntax check
|
||||
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
|
||||
sudo apt-get install -y nodejs
|
||||
|
||||
ERRORS=0
|
||||
|
||||
while IFS= read -r jsfile; do
|
||||
echo " 🔍 Checking $jsfile..."
|
||||
if ! node --check "$jsfile" 2>/dev/null; then
|
||||
echo " ❌ Syntax error"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
done < <(find . -name "*.js" -type f)
|
||||
|
||||
if [[ $ERRORS -gt 0 ]]; then
|
||||
echo "❌ Found $ERRORS JavaScript errors"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ All JavaScript files valid"
|
||||
|
||||
- name: Validate shell scripts
|
||||
run: |
|
||||
echo "📋 Validating shell scripts..."
|
||||
|
||||
ERRORS=0
|
||||
|
||||
# Check RPCD scripts
|
||||
while IFS= read -r script; do
|
||||
echo " 🔍 Checking $script..."
|
||||
if ! shellcheck -s sh "$script"; then
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
done < <(find . -path "*/rpcd/*" -type f -executable)
|
||||
|
||||
# Check init scripts
|
||||
while IFS= read -r script; do
|
||||
echo " 🔍 Checking $script..."
|
||||
if ! shellcheck -s sh "$script"; then
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
done < <(find . -path "*/init.d/*" -type f)
|
||||
|
||||
if [[ $ERRORS -gt 0 ]]; then
|
||||
echo "⚠️ Found $ERRORS shellcheck warnings (non-blocking)"
|
||||
fi
|
||||
echo "✅ Shell script validation complete"
|
||||
|
||||
- name: Check file permissions
|
||||
run: |
|
||||
echo "📋 Checking file permissions..."
|
||||
|
||||
ERRORS=0
|
||||
|
||||
# RPCD scripts should be executable
|
||||
while IFS= read -r script; do
|
||||
if [[ ! -x "$script" ]]; then
|
||||
echo " ❌ Not executable: $script"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
done < <(find . -path "*/usr/libexec/rpcd/*" -type f 2>/dev/null)
|
||||
|
||||
# Init scripts should be executable
|
||||
while IFS= read -r script; do
|
||||
if [[ ! -x "$script" ]]; then
|
||||
echo " ❌ Not executable: $script"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
done < <(find . -path "*/etc/init.d/*" -type f 2>/dev/null)
|
||||
|
||||
if [[ $ERRORS -gt 0 ]]; then
|
||||
echo "❌ Found $ERRORS permission errors"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ File permissions correct"
|
||||
|
||||
- name: Validate package structure
|
||||
run: |
|
||||
echo "📋 Validating package structure..."
|
||||
|
||||
for pkg in luci-app-*/; do
|
||||
if [[ -d "$pkg" ]]; then
|
||||
echo " 📦 Checking $pkg..."
|
||||
|
||||
# Required directories/files
|
||||
REQUIRED=(
|
||||
"Makefile"
|
||||
)
|
||||
|
||||
# Optional but recommended
|
||||
RECOMMENDED=(
|
||||
"htdocs/luci-static/resources"
|
||||
"root/usr/share/luci/menu.d"
|
||||
"root/usr/share/rpcd/acl.d"
|
||||
)
|
||||
|
||||
for req in "${REQUIRED[@]}"; do
|
||||
if [[ ! -e "${pkg}${req}" ]]; then
|
||||
echo " ❌ Missing required: $req"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
for rec in "${RECOMMENDED[@]}"; do
|
||||
if [[ ! -e "${pkg}${rec}" ]]; then
|
||||
echo " ⚠️ Missing recommended: $rec"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
echo "✅ Package structure valid"
|
||||
|
||||
# ============================================
|
||||
# Quick build test on x86_64
|
||||
# ============================================
|
||||
test-build:
|
||||
runs-on: ubuntu-latest
|
||||
name: Test Build (x86_64)
|
||||
needs: lint
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- 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-distutils rsync unzip zlib1g-dev wget
|
||||
|
||||
- name: Cache OpenWrt SDK
|
||||
uses: actions/cache@v4
|
||||
id: cache-sdk
|
||||
with:
|
||||
path: ~/sdk
|
||||
key: openwrt-sdk-23.05.5-x86-64-test
|
||||
|
||||
- name: Download OpenWrt SDK
|
||||
if: steps.cache-sdk.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
SDK_URL="https://downloads.openwrt.org/releases/23.05.5/targets/x86/64"
|
||||
SDK_FILE=$(curl -sL "$SDK_URL/" | grep -oP 'openwrt-sdk[^"]+\.tar\.xz' | head -1)
|
||||
|
||||
wget -q "${SDK_URL}/${SDK_FILE}" -O /tmp/sdk.tar.xz
|
||||
mkdir -p ~/sdk
|
||||
tar -xf /tmp/sdk.tar.xz -C ~/sdk --strip-components=1
|
||||
|
||||
- name: Prepare SDK
|
||||
run: |
|
||||
cd ~/sdk
|
||||
./scripts/feeds update -a
|
||||
./scripts/feeds install -a
|
||||
make defconfig
|
||||
|
||||
- name: Copy packages
|
||||
run: |
|
||||
mkdir -p ~/sdk/package/secubox
|
||||
|
||||
for pkg in luci-app-*/; do
|
||||
if [[ -d "$pkg" ]]; then
|
||||
cp -r "$pkg" ~/sdk/package/secubox/
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Build test
|
||||
run: |
|
||||
cd ~/sdk
|
||||
|
||||
# Enable packages
|
||||
for pkg in ~/sdk/package/secubox/*/; do
|
||||
PKG_NAME=$(basename "$pkg")
|
||||
echo "CONFIG_PACKAGE_${PKG_NAME}=m" >> .config
|
||||
done
|
||||
|
||||
make defconfig
|
||||
|
||||
# Build with timeout
|
||||
timeout 30m make package/secubox/compile V=s -j$(nproc) || {
|
||||
echo "⚠️ Build timeout or error"
|
||||
exit 1
|
||||
}
|
||||
|
||||
- name: Verify output
|
||||
run: |
|
||||
echo "📋 Built packages:"
|
||||
find ~/sdk/bin -name "*.ipk" -exec ls -la {} \;
|
||||
|
||||
PKG_COUNT=$(find ~/sdk/bin -name "*.ipk" | wc -l)
|
||||
echo "📦 Total packages built: $PKG_COUNT"
|
||||
|
||||
if [[ $PKG_COUNT -eq 0 ]]; then
|
||||
echo "❌ No packages were built!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ============================================
|
||||
# Generate documentation
|
||||
# ============================================
|
||||
docs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Generate Docs
|
||||
needs: lint
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Generate package list
|
||||
run: |
|
||||
echo "# SecuBox Packages" > PACKAGES.md
|
||||
echo "" >> PACKAGES.md
|
||||
echo "| Package | Version | Description |" >> PACKAGES.md
|
||||
echo "|---------|---------|-------------|" >> PACKAGES.md
|
||||
|
||||
for makefile in luci-app-*/Makefile; do
|
||||
if [[ -f "$makefile" ]]; then
|
||||
PKG_NAME=$(grep "^PKG_NAME:=" "$makefile" | cut -d'=' -f2)
|
||||
PKG_VERSION=$(grep "^PKG_VERSION:=" "$makefile" | cut -d'=' -f2)
|
||||
PKG_TITLE=$(grep "^LUCI_TITLE:=" "$makefile" | cut -d'=' -f2-)
|
||||
|
||||
echo "| $PKG_NAME | $PKG_VERSION | $PKG_TITLE |" >> PACKAGES.md
|
||||
fi
|
||||
done
|
||||
|
||||
echo "" >> PACKAGES.md
|
||||
echo "Generated: $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> PACKAGES.md
|
||||
|
||||
cat PACKAGES.md
|
||||
|
||||
- name: Upload docs
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: documentation
|
||||
path: PACKAGES.md
|
||||
Loading…
Reference in New Issue
Block a user