Skip to content

Add GitHub Actions workflows for plugin builds and releases #14

Add GitHub Actions workflows for plugin builds and releases

Add GitHub Actions workflows for plugin builds and releases #14

Workflow file for this run

name: Beta Build
on:
push:
branches:
- main
paths-ignore:
- '**.md'
- 'LICENSE'
- '.gitignore'
env:
GO_VERSION: '1.24'
NODE_VERSION: '20'
jobs:
build-frontend:
name: Build Frontend
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
cache-dependency-path: frontend/package-lock.json
- name: Install dependencies
working-directory: frontend
run: npm ci
- name: Build frontend
working-directory: frontend
run: npm run build
- name: Upload frontend artifact
uses: actions/upload-artifact@v4
with:
name: frontend-dist
path: frontend/dist
retention-days: 1
build-binaries:
name: Build ${{ matrix.name }}
runs-on: ubuntu-latest
needs: build-frontend
strategy:
matrix:
include:
- name: Linux x64
goos: linux
goarch: amd64
artifact: nettool-linux-amd64
- name: Linux x32
goos: linux
goarch: '386'
artifact: nettool-linux-386
- name: Linux Pi Zero (ARMv6)
goos: linux
goarch: arm
goarm: '6'
artifact: nettool-linux-arm6
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Install UPX (for compression)
run: |
sudo apt-get update
sudo apt-get install -y upx-ucl
- name: Download frontend artifact
uses: actions/download-artifact@v4
with:
name: frontend-dist
path: frontend/dist
- name: Get version info
id: version
run: |
SHORT_SHA=$(git rev-parse --short HEAD)
VERSION="beta-${SHORT_SHA}"
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "commit=$SHORT_SHA" >> $GITHUB_OUTPUT
echo "build_time=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_OUTPUT
- name: Build binary (hardened)
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
GOARM: ${{ matrix.goarm }}
CGO_ENABLED: '0'
run: |
# Maximum size reduction and security hardening flags
# -w: Omit DWARF symbol table (debug info)
# -s: Omit symbol table and debug information
# -buildid=: Remove build ID (reduces binary analysis)
# -trimpath: Remove file system paths from binary
# -extldflags "-static": Ensure static linking
LDFLAGS="-w -s -buildid= -extldflags '-static'"
LDFLAGS="$LDFLAGS -X main.Version=${{ steps.version.outputs.version }}"
LDFLAGS="$LDFLAGS -X main.BuildTime=${{ steps.version.outputs.build_time }}"
LDFLAGS="$LDFLAGS -X main.GitCommit=${{ steps.version.outputs.commit }}"
LDFLAGS="$LDFLAGS -X github.com/gin-gonic/gin.Mode=release"
LDFLAGS="$LDFLAGS -X github.com/NetScout-Go/NetTool/app/core.IntegrityEnabled=true"
# Build tags for static compilation and optimizations
# netgo: Use Go's network stack (no cgo)
# osusergo: Use Go's user lookup (no cgo)
BUILD_TAGS="netgo,osusergo"
# Additional GC flags for smaller binaries
export GOGC=off
echo "Building NetTool for ${{ matrix.name }} (hardened beta)..."
go build -a -trimpath -installsuffix cgo \
-tags "$BUILD_TAGS" \
-ldflags "$LDFLAGS" \
-gcflags=all="-l -B" \
-o nettool ./main.go
echo "Building CLI tool..."
go build -a -trimpath -installsuffix cgo \
-tags "$BUILD_TAGS" \
-ldflags "$LDFLAGS" \
-gcflags=all="-l -B" \
-o nettool-iterate ./app/cmd/iterate/main.go
echo "Initial binary sizes:"
ls -lh nettool nettool-iterate
- name: Strip binaries (additional size reduction)
run: |
# Strip for x86 targets
if [ "${{ matrix.goarch }}" = "amd64" ] || [ "${{ matrix.goarch }}" = "386" ]; then
strip --strip-all nettool 2>/dev/null || true
strip --strip-all nettool-iterate 2>/dev/null || true
echo "After strip:"
ls -lh nettool nettool-iterate
fi
- name: Compress binaries with UPX
run: |
# UPX compression for maximum size reduction
# --best: Best compression (slower)
# --lzma: Use LZMA compression (best ratio)
# Note: UPX may not work well with all ARM variants
echo "Compressing with UPX..."
if [ "${{ matrix.goarch }}" = "arm" ]; then
# ARM may have issues with UPX, use safer settings
upx --best nettool 2>/dev/null || echo "UPX failed for nettool (ARM), skipping"
upx --best nettool-iterate 2>/dev/null || echo "UPX failed for nettool-iterate (ARM), skipping"
else
# x86/x64 - use maximum compression
upx --best --lzma nettool 2>/dev/null || upx --best nettool 2>/dev/null || echo "UPX failed for nettool, skipping"
upx --best --lzma nettool-iterate 2>/dev/null || upx --best nettool-iterate 2>/dev/null || echo "UPX failed for nettool-iterate, skipping"
fi
echo "Final binary sizes after compression:"
ls -lh nettool nettool-iterate
- name: Generate checksums
id: checksums
run: |
# Generate SHA256 checksums for binaries
MAIN_HASH=$(sha256sum nettool | cut -d' ' -f1)
CLI_HASH=$(sha256sum nettool-iterate | cut -d' ' -f1)
echo "main_hash=$MAIN_HASH" >> $GITHUB_OUTPUT
echo "cli_hash=$CLI_HASH" >> $GITHUB_OUTPUT
# Create checksums file for the package
echo "$MAIN_HASH nettool" > SHA256SUMS
echo "$CLI_HASH nettool-iterate" >> SHA256SUMS
# Create platform-specific binary checksums JSON for aggregation
cat > binary-checksums.json << EOF
{
"platform": "${{ matrix.artifact }}",
"binaries": {
"nettool": "$MAIN_HASH",
"nettool-iterate": "$CLI_HASH"
}
}
EOF
echo "Generated checksums for ${{ matrix.artifact }}:"
cat SHA256SUMS
cat binary-checksums.json
- name: Prepare package
run: |
mkdir -p package/frontend/dist
mkdir -p package/app/plugins/plugins
cp nettool package/
cp nettool-iterate package/
cp SHA256SUMS package/
cp -r frontend/dist/* package/frontend/dist/
cp app/plugins/config.json.example package/app/plugins/
[ -f app/plugins/config.json ] && cp app/plugins/config.json package/app/plugins/ || true
[ -d app/plugins/plugins/demo_plugin ] && cp -r app/plugins/plugins/demo_plugin package/app/plugins/plugins/ || true
cp README.md package/ || true
cp LICENSE package/ || true
# Create install script with integrity verification
cat > package/install.sh << 'INSTALL_EOF'
#!/bin/bash
set -e
INSTALL_DIR="/opt/nettool"
SERVICE_FILE="/etc/systemd/system/nettool.service"
USER="nettool"
GROUP="nettool"
echo "🚀 Installing NetTool (Beta)..."
if [ "$EUID" -ne 0 ]; then
echo "❌ Please run as root (use sudo)"
exit 1
fi
# Verify checksums before installation
echo "🔐 Verifying binary integrity..."
if [ -f SHA256SUMS ]; then
if sha256sum -c SHA256SUMS --status 2>/dev/null; then
echo "✅ Checksums verified"
else
echo "⚠️ Checksum verification failed! Binaries may have been modified."
read -p "Continue anyway? (y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
else
echo "⚠️ No checksums file found, skipping verification"
fi
if ! getent group $GROUP >/dev/null; then
groupadd --system $GROUP
fi
if ! getent passwd $USER >/dev/null; then
useradd --system --gid $GROUP --shell /bin/false --home-dir $INSTALL_DIR $USER
fi
mkdir -p $INSTALL_DIR
cp -r . $INSTALL_DIR/
chown -R $USER:$GROUP $INSTALL_DIR
chmod +x $INSTALL_DIR/nettool $INSTALL_DIR/nettool-iterate
ln -sf $INSTALL_DIR/nettool /usr/local/bin/nettool
ln -sf $INSTALL_DIR/nettool-iterate /usr/local/bin/nettool-iterate
cat > $SERVICE_FILE << 'SERVICE_EOF'
[Unit]
Description=NetTool Network Analysis Server
After=network.target
[Service]
Type=simple
User=nettool
Group=nettool
WorkingDirectory=/opt/nettool
ExecStart=/opt/nettool/nettool --port=8080
Restart=always
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/nettool
CapabilityBoundingSet=CAP_NET_RAW CAP_NET_ADMIN
AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN
[Install]
WantedBy=multi-user.target
SERVICE_EOF
systemctl daemon-reload
systemctl enable nettool
echo "✅ Installation complete!"
echo " Start: sudo systemctl start nettool"
echo " Logs: sudo journalctl -u nettool -f"
echo " Web: http://localhost:8080"
echo ""
echo "🔐 Verify integrity anytime: nettool --integrity"
INSTALL_EOF
chmod +x package/install.sh
- name: Create archive
run: |
cd package
tar -czvf ../${{ matrix.artifact }}-beta.tar.gz .
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact }}
path: ${{ matrix.artifact }}-beta.tar.gz
retention-days: 7
- name: Upload checksums artifact
uses: actions/upload-artifact@v4
with:
name: checksums-${{ matrix.artifact }}
path: |
SHA256SUMS
binary-checksums.json
retention-days: 7
update-beta-release:
name: Update Beta Release
runs-on: ubuntu-latest
needs: build-binaries
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Get commit info
id: info
run: |
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
echo "sha_full=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
echo "date=$(date -u +%Y-%m-%d)" >> $GITHUB_OUTPUT
echo "time=$(date -u +%H:%M:%S)" >> $GITHUB_OUTPUT
echo "commit_msg=$(git log -1 --pretty=%s)" >> $GITHUB_OUTPUT
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Move artifacts
run: |
mkdir -p release-files
find artifacts -name "*.tar.gz" -exec mv {} release-files/ \;
ls -la release-files/
- name: Generate combined checksums
run: |
cd release-files
# Create archive checksums (for verifying downloaded tar.gz files)
echo "Creating archive checksums..."
sha256sum *.tar.gz > SHA256SUMS-archives
echo "Archive checksums:"
cat SHA256SUMS-archives
cd ..
# Collect all binary checksums from artifacts
echo "Collecting binary checksums from all platforms..."
mkdir -p binary-hashes
# Only copy platform-specific checksums (not the generic binary-checksums.json)
for dir in artifacts/checksums-*; do
platform=$(basename "$dir" | sed 's/checksums-//')
if [ -f "$dir/binary-checksums.json" ]; then
cp "$dir/binary-checksums.json" "binary-hashes/${platform}.json"
echo "Found checksums for: $platform"
fi
done
# Create combined binary checksums JSON with proper formatting
echo "Creating combined binary checksums..."
# Start JSON
echo '{' > release-files/binary-checksums.json
echo ' "version": "beta-${{ steps.info.outputs.sha_short }}",' >> release-files/binary-checksums.json
echo ' "build_time": "${{ steps.info.outputs.date }}T${{ steps.info.outputs.time }}Z",' >> release-files/binary-checksums.json
echo ' "description": "SHA256 hashes of binaries inside each platform package",' >> release-files/binary-checksums.json
echo ' "platforms": {' >> release-files/binary-checksums.json
# Add each platform
FIRST=true
for f in binary-hashes/nettool-*.json; do
if [ -f "$f" ]; then
PLATFORM=$(basename "$f" .json)
MAIN_HASH=$(grep -o '"nettool": "[^"]*"' "$f" | head -1 | cut -d'"' -f4)
CLI_HASH=$(grep -o '"nettool-iterate": "[^"]*"' "$f" | head -1 | cut -d'"' -f4)
if [ -n "$MAIN_HASH" ]; then
if [ "$FIRST" = true ]; then
FIRST=false
else
echo ',' >> release-files/binary-checksums.json
fi
echo " \"$PLATFORM\": {" >> release-files/binary-checksums.json
echo " \"nettool\": \"$MAIN_HASH\"," >> release-files/binary-checksums.json
echo " \"nettool-iterate\": \"$CLI_HASH\"" >> release-files/binary-checksums.json
echo -n " }" >> release-files/binary-checksums.json
fi
fi
done
# Close JSON
echo '' >> release-files/binary-checksums.json
echo ' }' >> release-files/binary-checksums.json
echo '}' >> release-files/binary-checksums.json
echo ""
echo "Binary checksums (for runtime verification):"
cat release-files/binary-checksums.json
# Validate JSON
echo ""
echo "Validating JSON..."
python3 -m json.tool release-files/binary-checksums.json > /dev/null && echo "✅ JSON is valid" || echo "❌ JSON is invalid"
# Move archive checksums to release
mv release-files/SHA256SUMS-archives release-files/SHA256SUMS
- name: Delete existing beta tag and release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Delete the release if it exists
gh release delete beta --yes || true
# Delete the tag if it exists
git push origin :refs/tags/beta || true
- name: Create Beta Release
uses: softprops/action-gh-release@v2
with:
tag_name: beta
name: "🧪 Beta Build (${{ steps.info.outputs.date }})"
body: |
## ⚠️ Beta Build - Use at Your Own Risk
This is an automatically generated build from the latest `main` branch commit.
**Build Info:**
- 📅 Date: ${{ steps.info.outputs.date }} ${{ steps.info.outputs.time }} UTC
- 🔖 Commit: [`${{ steps.info.outputs.sha_short }}`](https://github.com/${{ github.repository }}/commit/${{ steps.info.outputs.sha_full }})
- 💬 Message: ${{ steps.info.outputs.commit_msg }}
**🔐 Security Features:**
- Debug symbols stripped for smaller size
- Build paths removed for privacy
- Integrity verification enabled (`nettool --integrity`)
- SHA256 checksums included
**Downloads:**
| Platform | File |
|----------|------|
| Linux x64 | `nettool-linux-amd64-beta.tar.gz` |
| Linux x32 | `nettool-linux-386-beta.tar.gz` |
| Pi Zero (ARMv6) | `nettool-linux-arm6-beta.tar.gz` |
**Verify your download:**
```bash
# Download and verify checksums
curl -sL https://github.com/${{ github.repository }}/releases/download/beta/SHA256SUMS | sha256sum -c
# Or verify after installation
nettool --integrity
```
---
> 💡 For stable releases, check the [Releases](https://github.com/${{ github.repository }}/releases) page.
files: |
release-files/*.tar.gz
release-files/binary-checksums.json
release-files/SHA256SUMS
prerelease: true
draft: false
make_latest: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}