Watch
1
0
Fork
You've already forked RedFlag
0
RedFlag/.gitea/workflows/ci.yml
Fimeg ff2f30f47a v0.2.9.3: device classification + ARM support — Pixel 3 lands
DEVICE-002: ARM machine-ID fallback — device-tree model + /etc/machine-id
combo, then /proc/cpuinfo Serial (all-zero rejected), before the weak
hostname fallback. Hardware-bound IDs on DMI-less devices.

DEVICE-001: agent detects device_type (server/desktop/phone/tablet) from
/sys signals — system battery (scope=Device peripherals excluded, UPS
excluded), DRM connector state, framebuffer min-dimension for phone/tablet
split. Reports device_type/device_model/os_distro in registration and
system-info paths.

SERVER-001: migration 061 — device_type, device_type_manual (operator
override, never agent-written), device_model, os_distro on agents.
effective_device_type computed into every serialized agent.

SERVER-002: PUT /admin/agents/:id/device-type — set/clear override,
enum-validated, journaled.

WEB-001: device-type icons + fleet filter, device model in list, detail
header badge with reclassify dropdown, os_distro surfaced.

INSTALL-003: arm64 install path unblocked — helper (required manifest
component) now cross-built aarch64-unknown-linux-musl via rust-lld in the
server image, signed at boot (helperArches += arm64), listed in the release
manifest. Install template already handled uname -m and pacman.

Plus in-flight: desktop tray wiring, enrollment page polish, CI workflow
updates, RAF session-broker/pacman-scanner docs, native installer scaffold.
2026-07-06 18:21:23 -04:00

259 lines
10 KiB
YAML

name: ci
on:
push:
branches: [main, public]
pull_request:
branches: [main, public]
jobs:
go-vet:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: agent/go.mod
cache: true
- name: go vet (server)
run: cd server && go vet ./...
- name: go vet (agent)
run: cd agent && go vet ./...
go-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: agent/go.mod
cache: true
- name: go test -race (server)
run: cd server && go test -race -count=1 ./...
- name: go test -race (agent)
run: cd agent && go test -race -count=1 ./...
rust-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
with:
components: clippy
- name: cargo test
run: cd helper && cargo test
- name: cargo clippy
run: cd helper && cargo clippy -- -D warnings
# Cross-compile check: does it build for every target platform?
# Tests run only on native linux-amd64 above; this catches portability
# regressions (cfg(target_os), FFI, path assumptions) without needing
# a runner per OS.
cross-compile:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- goos: linux
goarch: arm64
rust_target: aarch64-unknown-linux-gnu
linker: gcc-aarch64-linux-gnu
use_zigbuild: false
skip_helper: false
- goos: windows
goarch: amd64
rust_target: ""
linker: gcc-mingw-w64-x86-64
use_zigbuild: false
skip_helper: true
- goos: darwin
goarch: arm64
rust_target: aarch64-apple-darwin
linker: ""
use_zigbuild: true
skip_helper: false
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: agent/go.mod
cache: true
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
with:
targets: ${{ matrix.rust_target }}
- name: Install cross-linker
if: matrix.linker != ''
run: sudo apt-get update && sudo apt-get install -y ${{ matrix.linker }}
- name: Install cargo-zigbuild
if: matrix.use_zigbuild
run: pip3 install --break-system-packages cargo-zigbuild
- name: Cross-compile Go (server)
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
CGO_ENABLED: "0"
run: cd server && go build -o /dev/null ./cmd/server/
- name: Cross-compile Go (agent)
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
CGO_ENABLED: "0"
run: cd agent && go build -o /dev/null ./cmd/agent/
- name: Cross-compile Rust (helper)
if: "!matrix.skip_helper"
run: |
cd helper
if [ "${{ matrix.use_zigbuild }}" = "true" ]; then
cargo zigbuild --release --target ${{ matrix.rust_target }}
else
cargo build --release --target ${{ matrix.rust_target }}
fi
web-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 20
cache: npm
cache-dependency-path: web/package-lock.json
# npm run build = tsc && vite build — type errors and bundling failures
# both surface here, not at release time.
- name: Build web UI
run: cd web && npm ci && npm run build
installer-integrity:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: agent/go.mod
cache: true
- name: Install template integrity
run: cd server && go test -run 'TestInstallTemplateRenders|TestFreshInstallConfigKeys|TestInstallTemplateScriptletSyntax' -v -count=1 ./internal/services/
# Dependency vulnerability scanning — RedFlag held to the supply-chain standard
# it enforces on the fleet. Tools installed directly (no third-party actions) so
# the socket-mounted runner's surface stays small. Go is reachability-gated via a
# documented allowlist (.govulncheck-allow, mirrored in SECURITY.md); npm gates the
# production tree and treats dev-only advisories as warnings; cargo gates outright.
dep-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: agent/go.mod
cache: true
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 20
cache: npm
cache-dependency-path: web/package-lock.json
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
# Provenance first: record the substrate even if a later scan fails the job.
# "Are we using hacked programs to build it?" — this is how we SEE the answer.
# Floor enforcement (fail on an out-of-date engine/toolchain) is the next layer.
- name: Record build substrate
run: |
{
echo "## Build substrate"
echo '```'
echo "go: $(go version)"
echo "rustc: $(rustc --version)"
echo "cargo: $(cargo --version)"
echo "node: $(node --version)"
echo "npm: $(npm --version)"
echo "docker: $(docker version --format '{{.Server.Version}}' 2>&1 || echo 'no engine reachable')"
echo "runner: ${RUNNER_NAME:-unknown} / $(uname -srm)"
echo '```'
} | tee -a "${GITHUB_STEP_SUMMARY:-/dev/stdout}"
# Scanners run latest on purpose — an old scanner misses new advisories.
- name: Install scanners
run: |
go install golang.org/x/vuln/cmd/govulncheck@latest
cargo install cargo-audit --locked
# One audited script gates Go (reachability + allowlist), web (prod tree),
# and the Rust helper. release.yml runs the same script with --posture-out
# to emit the attested posture — CI and release can't drift on the verdict.
- name: Dependency gate
run: scripts/dep-scan.sh
no-ai-attribution:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0
- name: Check commit messages for AI attribution
run: |
# Check all commits in the push/PR range.
# On push: compare against the base branch.
# On PR: compare against the PR base.
if [ "${{ github.event_name }}" = "pull_request" ]; then
RANGE="${{ github.event.pull_request.base.sha }}..${{ github.sha }}"
else
RANGE="${{ github.event.before }}..${{ github.sha }}"
# First push — no before sha. Check last 10 commits.
if [ "${{ github.event.before }}" = "0000000000000000000000000000000000000000" ]; then
RANGE="HEAD~10..HEAD"
fi
fi
PATTERNS="Co-Authored-By:.*[Cc]laude|Co-Authored-By:.*OpenAI|Co-Authored-By:.*ChatGPT|Co-Authored-By:.*Copilot|Co-Authored-By:.*Letta|Co-Authored-By:.*Cursor|Generated by|Generated with|AI-assisted|Auto-generated by"
FAIL=0
while IFS= read -r msg; do
if echo "$msg" | grep -qiE "$PATTERNS"; then
echo "::error::AI attribution found in commit: $msg"
FAIL=1
fi
done < <(git log --format='%s%n%b' $RANGE 2>/dev/null)
if [ "$FAIL" -eq 1 ]; then
echo "::error::Commits contain AI attribution lines. Remove them before merging."
exit 1
fi
echo "No AI attribution found in commits."
action-pins:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Check for floating action refs
run: |
if grep -rE 'uses:.*@(v[0-9]+|stable|main|master)(\s|$)' .gitea/workflows/; then
echo "::error::Floating action refs found — run scripts/update-action-pins.sh"
exit 1
fi
echo "All action refs are SHA-pinned."
# Push public to Codeberg when all checks pass. The .profile README is
# rendered by the profile-engine repo — single writer, do not stamp it here.
# Requires CODEBERG_TOKEN secret in the repo settings.
sync-codeberg:
runs-on: ubuntu-latest
needs: [go-vet, go-test, rust-test, cross-compile, web-build, installer-integrity, dep-scan, no-ai-attribution, action-pins]
if: github.ref == 'refs/heads/public'
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0
- name: Push public to Codeberg
run: |
if [ -z "${{ secrets.CODEBERG_TOKEN }}" ]; then
echo "[INFO] [sync] CODEBERG_TOKEN not set — skipping codeberg push"
exit 0
fi
git remote add codeberg-ci "https://${{ secrets.CODEBERG_TOKEN }}@codeberg.org/Fimeg/RedFlag.git"
git push codeberg-ci public:public
echo "Pushed public to codeberg.org/Fimeg/RedFlag"