Files
DDI/.gitea/workflows/ci.yml
T
sir_melonchenandClaude Opus 5.5 306efd2990 ci: build packages, sign releases and check names
The release dry run builds and inspects the packages and proves signing
and verification with a throwaway key; the release workflow signs
SHA256SUMS when RELEASE_SIGNING_KEY is set and checks the signature with
the installer's public key. The shell job runs the brand check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 00:41:13 +02:00

220 lines
7.7 KiB
YAML

# SPDX-License-Identifier: Apache-2.0
#
# Continuous integration (ADR 0003). Runs on Gitea Actions with
# GitHub-Actions-compatible syntax. External actions are pinned by commit SHA.
name: ci
on:
push:
branches: [main]
pull_request:
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
go:
name: Go (lint, test, vuln)
runs-on: ubuntu-latest
services:
postgres:
image: postgres:17.11-alpine
env:
POSTGRES_USER: ddi
POSTGRES_PASSWORD: ddi-ci-only
POSTGRES_DB: ddi_test
options: >-
--health-cmd "pg_isready -U ddi -d ddi_test"
--health-interval 5s
--health-timeout 3s
--health-retries 20
env:
# Database tests must run in CI instead of being skipped.
DDI_TEST_DATABASE_URL: postgres://ddi:ddi-ci-only@postgres:5432/ddi_test?sslmode=disable
DDI_REQUIRE_DB_TESTS: "1"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
cache: false
- name: Install tools
run: scripts/ci/install-tools.sh
- name: Ensure C toolchain for the race detector
run: |
if ! command -v gcc >/dev/null; then
apt-get update -qq && apt-get install -y -qq --no-install-recommends gcc libc6-dev
fi
- name: Lint
run: make lint-go
- name: Test
run: make test-go
- name: Coverage summary
run: go tool cover -func=coverage.txt | tail -n 1
- name: Vulnerability scan
run: go tool govulncheck ./...
proto:
name: Protobuf
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Install tools
run: scripts/ci/install-tools.sh
- name: Lint and format
run: make lint-proto
- name: Generated code is up to date
run: buf generate && git diff --exit-code -- proto/gen
web:
name: Web (lint, test, audit, build)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: "24"
- name: Install dependencies
run: make web-deps
- name: API types are up to date with the OpenAPI spec
run: cd web && npm run gen:api && git diff --exit-code -- src/api/schema.d.ts
- name: Lint, format, typecheck
run: make lint-web
- name: Test
run: make test-web
- name: Audit
run: cd web && npm audit --audit-level=high
- name: Build
run: cd web && npm run build
shell:
name: Shell and licence headers
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Install tools
run: scripts/ci/install-tools.sh
- name: shellcheck
run: make lint-shell
- name: SPDX headers
run: make lint-spdx
- name: No hard-coded product names (ADR 0018)
run: make lint-brand
release-dry-run:
name: Release build (dry run)
runs-on: ubuntu-latest
services:
postgres:
image: postgres:17.11-alpine
env:
POSTGRES_USER: ddi
POSTGRES_PASSWORD: ddi-ci-only
POSTGRES_DB: ddi
options: >-
--health-cmd "pg_isready -U ddi -d ddi"
--health-interval 5s
--health-timeout 3s
--health-retries 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
cache: false
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: "24"
- name: Install nfpm
run: scripts/ci/install-tools.sh "$HOME/.local/bin" nfpm
- name: Build release artefacts and packages
run: make release PACKAGES=1
- name: Verify checksums
run: cd dist && sha256sum -c SHA256SUMS
- name: Inspect packages
run: |
ls -l dist/*.deb dist/*.rpm
# 3 binaries x 2 architectures x (deb, rpm)
test "$(ls dist/*.deb dist/*.rpm | wc -l)" -eq 12
for deb in dist/*_amd64.deb; do
dpkg-deb --info "$deb" >/dev/null
dpkg-deb --contents "$deb" >contents.txt
grep -q ' ./usr/bin/' contents.txt
grep -q ' ./usr/lib/systemd/system/.*\.service$' contents.txt
grep -q ' ./usr/share/doc/.*/LICENSE$' contents.txt
done
- name: Release signature (throwaway key)
run: |
command -v openssl >/dev/null || (apt-get update -qq && apt-get install -y -qq openssl)
scripts/sign-release.sh selftest
umask 077
key="$(mktemp)"
openssl genpkey -algorithm ed25519 -out "$key"
RELEASE_SIGNING_KEY="$(cat "$key")" scripts/sign-release.sh sign dist/SHA256SUMS
scripts/sign-release.sh public-key "$key" >"$key.pub"
scripts/sign-release.sh verify dist/SHA256SUMS dist/SHA256SUMS.sig "$key.pub"
rm -f "$key" "$key.pub" dist/SHA256SUMS.sig
- name: Smoke test of the released server binary
env:
DDI_DATABASE_URL: postgres://ddi:ddi-ci-only@postgres:5432/ddi?sslmode=disable
run: scripts/ci/smoke-server.sh dist
# Needs a runner with access to a Docker daemon (see docs/adr/0003).
e2e:
name: End-to-end (server, agents, BIND, Kea)
runs-on: ubuntu-latest
env:
# The Docker daemon may be shared: unique compose project.
COMPOSE_PROJECT_NAME: ddi-e2e-${{ github.run_id }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
cache: false
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: "24"
- name: API change reaches BIND and Kea through the agents
run: make test-e2e
# Needs a runner with access to a Docker daemon (see docs/adr/0003).
integration:
name: Integration (real BIND and Kea)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
cache: false
- name: Generated configuration and agent roles against real BIND and Kea
run: make test-integration
# Needs a runner with access to a Docker daemon (see docs/adr/0003).
dev-environment:
name: Development environment (compose)
runs-on: ubuntu-latest
env:
# The Docker daemon may be shared: unique project, random host ports.
COMPOSE_PROJECT_NAME: ddi-ci-${{ github.run_id }}
DDI_DEV_PG_PORT: ""
DDI_DEV_DNS_PORT: ""
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Validate compose file
run: docker compose -f deploy/compose/compose.dev.yaml config -q
- name: Start
run: make dev-up
- name: Smoke test
run: make dev-smoke
- name: Logs
if: always()
run: docker compose -f deploy/compose/compose.dev.yaml logs --no-color
- name: Stop
if: always()
run: docker compose -f deploy/compose/compose.dev.yaml down -v