Files
swarm-house/.github/workflows/release.yaml
T
eSlider 826cef0c3e
CI & Release / Verify documentation (push) Skipped
CI & Release / Verify simulator (push) Skipped
CI & Release / Trivy scan (push) Skipped
CI & Release / Semantic Release (push) Skipped
CI & Release / Verify documentation (pull_request) Successful in 4s
CI & Release / Verify simulator (pull_request) Successful in 11s
CI & Release / Trivy scan (pull_request) Successful in 8s
CI & Release / Semantic Release (pull_request) Skipped
fix: drop PyYAML dep so verify job pytest passes
Store doc rules in bin/docs_rules.json (stdlib json). test_check_docs no
longer fails in the simulator job that only installs simulator/requirements.txt.
2026-07-10 11:02:55 +01:00

204 lines
7.5 KiB
YAML

# Swarm House - Gitea Actions
# docs-verify: markdown links, glossary anchors, readability rules (every push/PR)
# verify: compile check, virtual-drone smoke flight, SQL gate tests (every push/PR)
# scan: Trivy vulnerability + misconfiguration scan
# release: semantic version bump (conventional commits), tag, Gitea release
# with a fleet release manifest + source bundle
name: CI & Release
on:
push:
branches: [main]
paths-ignore:
- 'docs/**'
- 'README.md'
- 'AGENTS.md'
pull_request:
branches: [main]
jobs:
docs-verify:
name: Verify documentation
runs-on: ubuntu-latest
container: python:3.12-bookworm
steps:
- name: Checkout
run: |
git init .
git remote add origin https://${{ gitea.actor }}:${{ gitea.token }}@git.produktor.io/${{ gitea.repository }}.git
git fetch --depth=50 origin "${{ gitea.ref }}"
git checkout FETCH_HEAD
- name: Fetch base branch for ADR immutability
run: git fetch --depth=1 origin main
- name: ADR immutability (no edits to accepted records)
run: python bin/check_adrs.py --base origin/main
- name: Documentation rules (links, glossary, readability)
run: python bin/check_docs.py
verify:
name: Verify simulator
runs-on: ubuntu-latest
container: python:3.12-bookworm
steps:
- name: Checkout
run: |
git init .
git remote add origin https://${{ gitea.actor }}:${{ gitea.token }}@git.produktor.io/${{ gitea.repository }}.git
git fetch --depth=50 origin "${{ gitea.ref }}"
git checkout FETCH_HEAD
- name: Install dependencies
run: pip install --quiet -r simulator/requirements.txt
- name: Unit tests (TDD gate)
working-directory: simulator
run: pytest tests/ -q
- name: Compile check
run: python -m compileall -q simulator/virtual_drone simulator/monitoring simulator/explorer
- name: Smoke flight
working-directory: simulator
run: |
DRONE_ID=ci-01 FLIGHT_ID=ci-smoke DURATION_S=10 SPEEDUP=10 DATA_DIR=./data \
python -m virtual_drone.main
python - <<'EOF'
import duckdb
rows = duckdb.sql("""
SELECT count(*) FROM read_parquet(
'data/dataset=telemetry/**/*.parquet',
hive_partitioning=true, union_by_name=true)
""").fetchone()[0]
assert rows > 0, "smoke flight produced no telemetry"
print(f"smoke flight OK: {rows} telemetry rows")
EOF
scan:
name: Trivy scan
runs-on: ubuntu-latest
container: python:3.12-bookworm
needs: verify
steps:
- name: Checkout
run: |
git init .
git remote add origin https://${{ gitea.actor }}:${{ gitea.token }}@git.produktor.io/${{ gitea.repository }}.git
git fetch --depth=1 origin "${{ gitea.ref }}"
git checkout FETCH_HEAD
- name: Install Trivy
run: |
TRIVY_VER="0.72.0"
curl -fsSL "https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VER}/trivy_${TRIVY_VER}_Linux-64bit.tar.gz" \
| tar -xz -C /usr/local/bin trivy
trivy --version
- name: Dependency vulnerabilities
run: trivy fs --scanners vuln --severity HIGH,CRITICAL --exit-code 1 .
- name: Dockerfile and Compose misconfigurations
run: trivy config --severity HIGH,CRITICAL --exit-code 0 .
release:
name: Semantic Release
runs-on: ubuntu-latest
container: python:3.12-bookworm
needs: [docs-verify, verify, scan]
if: gitea.event_name == 'push'
permissions:
contents: write
steps:
- name: Checkout (full history for tags)
run: |
git clone https://${{ gitea.actor }}:${{ gitea.token }}@git.produktor.io/${{ gitea.repository }}.git .
git checkout ${{ gitea.sha }}
git fetch --tags
- name: Determine version bump (conventional commits)
id: version
run: |
LATEST_TAG=$(git tag -l 'v*' --sort=-v:refname | head -1)
[ -z "$LATEST_TAG" ] && LATEST_TAG="v0.0.0"
echo "Latest tag: $LATEST_TAG"
VER="${LATEST_TAG#v}"
MAJOR=$(echo "$VER" | cut -d. -f1)
MINOR=$(echo "$VER" | cut -d. -f2)
PATCH=$(echo "$VER" | cut -d. -f3)
MSG=$(git log -1 --format='%s%n%b' ${{ gitea.sha }})
echo "Commit: $(git log -1 --format='%s' ${{ gitea.sha }})"
if echo "$MSG" | grep -qE '^[a-z]+(\(.+\))?!:|BREAKING CHANGE'; then
MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0; BUMP="major"
elif echo "$MSG" | grep -qE '^feat(\(.+\))?:'; then
MINOR=$((MINOR + 1)); PATCH=0; BUMP="minor"
else
PATCH=$((PATCH + 1)); BUMP="patch"
fi
NEW_TAG="v${MAJOR}.${MINOR}.${PATCH}"
echo "Bump: $BUMP -> $NEW_TAG"
echo "new_tag=${NEW_TAG}" >> "$GITHUB_OUTPUT"
echo "bump_type=${BUMP}" >> "$GITHUB_OUTPUT"
- name: Build fleet release manifest and source bundle
run: |
TAG="${{ steps.version.outputs.new_tag }}"
mkdir -p .tmp
tar --exclude='.git' --exclude='.tmp' --exclude='simulator/data' \
--exclude='var/t1' --exclude='var/t3' \
--exclude='simulator/.venv' --exclude='prototype/node_modules' \
-czf ".tmp/swarm-house-${TAG}.tar.gz" .
cat > .tmp/manifest.yaml <<EOF
# Fleet release manifest (docs/11-cicd-delivery.md)
release: ${TAG}
commit: ${{ gitea.sha }}
built_at: $(date -u +%Y-%m-%dT%H:%M:%SZ)
artifacts:
- name: swarm-house-${TAG}.tar.gz
sha256: $(sha256sum ".tmp/swarm-house-${TAG}.tar.gz" | cut -d' ' -f1)
components:
simulator: python-3.12
explorer: python-3.12
prototype: vite-react
EOF
cat .tmp/manifest.yaml
- name: Create tag
run: |
git config user.name "Gitea Actions"
git config user.email "actions@git.produktor.io"
git tag -a "${{ steps.version.outputs.new_tag }}" \
-m "Release ${{ steps.version.outputs.new_tag }} (${{ steps.version.outputs.bump_type }})"
git push https://${{ gitea.actor }}:${{ gitea.token }}@git.produktor.io/${{ gitea.repository }}.git \
"${{ steps.version.outputs.new_tag }}"
- name: Create Gitea Release
run: |
TAG="${{ steps.version.outputs.new_tag }}"
BUMP="${{ steps.version.outputs.bump_type }}"
API="https://git.produktor.io/api/v1/repos/${{ gitea.repository }}/releases"
TOKEN="${{ gitea.token }}"
RELEASE=$(curl -sf -X POST "$API" \
-H "Authorization: token $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"tag_name\":\"$TAG\",\"name\":\"Swarm House $TAG\",\"body\":\"**${BUMP}** release \`${TAG}\` — verified (smoke flight, SQL gate) and scanned (Trivy). Includes the fleet release manifest.\"}")
RELEASE_ID=$(echo "$RELEASE" | grep -o '"id":[0-9]*' | head -1 | cut -d: -f2)
echo "Created release ID: $RELEASE_ID"
for f in .tmp/*; do
FNAME=$(basename "$f")
curl -sf -X POST "$API/$RELEASE_ID/assets?name=$FNAME" \
-H "Authorization: token $TOKEN" \
-H "Content-Type: application/octet-stream" \
--data-binary "@$f"
echo "Uploaded: $FNAME"
done