Add signed runtime distribution pipeline
This commit is contained in:
@@ -0,0 +1,243 @@
|
||||
name: Runtime Distribution
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: Release version without leading v
|
||||
required: true
|
||||
type: string
|
||||
python_image:
|
||||
description: Digest-pinned multi-architecture Python 3.12 slim image
|
||||
required: true
|
||||
type: string
|
||||
nginx_image:
|
||||
description: Digest-pinned multi-architecture nginx-unprivileged image
|
||||
required: true
|
||||
type: string
|
||||
postgres_image:
|
||||
description: Digest-pinned PostgreSQL image
|
||||
required: true
|
||||
type: string
|
||||
redis_image:
|
||||
description: Digest-pinned Redis image
|
||||
required: true
|
||||
type: string
|
||||
load_balancer_image:
|
||||
description: Digest-pinned HAProxy image
|
||||
required: true
|
||||
type: string
|
||||
garage_image:
|
||||
description: Digest-pinned Garage image
|
||||
required: true
|
||||
type: string
|
||||
test_mail_image:
|
||||
description: Digest-pinned GreenMail image
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
publish-runtime:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
|
||||
with:
|
||||
path: govoplan
|
||||
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065
|
||||
with:
|
||||
python-version: "3.12"
|
||||
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
|
||||
with:
|
||||
node-version: "22"
|
||||
- name: Use HTTPS for GovOPlaN repositories
|
||||
run: |
|
||||
git config --global --add url."https://git.add-ideas.de/GovOPlaN/govoplan".insteadOf "git@git.add-ideas.de:GovOPlaN/govoplan"
|
||||
git config --global --add url."https://git.add-ideas.de/GovOPlaN/govoplan".insteadOf "ssh://git@git.add-ideas.de/GovOPlaN/govoplan"
|
||||
- name: Bootstrap release sources
|
||||
working-directory: govoplan
|
||||
run: python tools/repo/bootstrap-repositories.py --parent .. --transport public-https --exclude-repo addideas-govoplan-website
|
||||
- name: Build release wheel roots and WebUI
|
||||
working-directory: govoplan
|
||||
run: |
|
||||
python -m venv .runtime-build
|
||||
.runtime-build/bin/python -m pip install --upgrade pip wheel cryptography
|
||||
mkdir -p runtime-output/local-wheels
|
||||
.runtime-build/bin/python -m pip wheel --no-deps --wheel-dir runtime-output/local-wheels --requirement requirements-release.txt
|
||||
bash tools/release/install-webui-release-dependencies.sh ../govoplan-core/webui
|
||||
npm --prefix ../govoplan-core/webui run build
|
||||
.runtime-build/bin/python tools/release/prepare-runtime-context.py \
|
||||
--wheelhouse runtime-output/local-wheels \
|
||||
--web-dist ../govoplan-core/webui/dist \
|
||||
--output runtime-output/common \
|
||||
--required-module tenancy \
|
||||
--required-module organizations \
|
||||
--required-module identity \
|
||||
--required-module idm \
|
||||
--required-module access \
|
||||
--required-module admin \
|
||||
--required-module dashboard \
|
||||
--required-module policy \
|
||||
--required-module audit \
|
||||
--required-module docs \
|
||||
--required-module ops
|
||||
- name: Resolve architecture-specific offline wheelhouses
|
||||
working-directory: govoplan
|
||||
run: |
|
||||
mkdir -p runtime-output/wheels-amd64 runtime-output/wheels-arm64
|
||||
cp runtime-output/local-wheels/*.whl runtime-output/wheels-amd64/
|
||||
cp runtime-output/local-wheels/*.whl runtime-output/wheels-arm64/
|
||||
.runtime-build/bin/python -m pip download --only-binary=:all: \
|
||||
--platform manylinux_2_17_x86_64 --platform manylinux2014_x86_64 \
|
||||
--implementation cp --python-version 3.12 --abi cp312 \
|
||||
--find-links runtime-output/local-wheels \
|
||||
--dest runtime-output/wheels-amd64 \
|
||||
--requirement runtime-output/common/requirements-runtime.txt
|
||||
.runtime-build/bin/python -m pip download --only-binary=:all: \
|
||||
--platform manylinux_2_17_aarch64 --platform manylinux2014_aarch64 \
|
||||
--implementation cp --python-version 3.12 --abi cp312 \
|
||||
--find-links runtime-output/local-wheels \
|
||||
--dest runtime-output/wheels-arm64 \
|
||||
--requirement runtime-output/common/requirements-runtime.txt
|
||||
.runtime-build/bin/python tools/release/prepare-runtime-context.py \
|
||||
--wheelhouse runtime-output/wheels-amd64 \
|
||||
--web-dist ../govoplan-core/webui/dist \
|
||||
--output runtime-output/context-amd64
|
||||
.runtime-build/bin/python tools/release/prepare-runtime-context.py \
|
||||
--wheelhouse runtime-output/wheels-arm64 \
|
||||
--web-dist ../govoplan-core/webui/dist \
|
||||
--output runtime-output/context-arm64
|
||||
cmp runtime-output/context-amd64/composition.json runtime-output/context-arm64/composition.json
|
||||
- name: Build one-file deployer
|
||||
working-directory: govoplan
|
||||
run: python tools/deployment/build-deployer-zipapp.py --output runtime-output/govoplan-deploy.pyz
|
||||
- name: Authenticate OCI publication
|
||||
working-directory: govoplan
|
||||
env:
|
||||
REGISTRY_USERNAME: ${{ secrets.GOVOPLAN_REGISTRY_USERNAME }}
|
||||
REGISTRY_TOKEN: ${{ secrets.GOVOPLAN_REGISTRY_TOKEN }}
|
||||
run: |
|
||||
test -n "$REGISTRY_USERNAME"
|
||||
test -n "$REGISTRY_TOKEN"
|
||||
printf '%s' "$REGISTRY_TOKEN" | docker login git.add-ideas.de --username "$REGISTRY_USERNAME" --password-stdin
|
||||
docker buildx create --name govoplan-runtime --use
|
||||
- name: Build and publish architecture images
|
||||
working-directory: govoplan
|
||||
env:
|
||||
VERSION: ${{ inputs.version }}
|
||||
PYTHON_IMAGE: ${{ inputs.python_image }}
|
||||
NGINX_IMAGE: ${{ inputs.nginx_image }}
|
||||
run: |
|
||||
COMPOSITION_SHA256="$(sha256sum runtime-output/context-amd64/composition.json | cut -d' ' -f1)"
|
||||
for ARCH in amd64 arm64; do
|
||||
docker buildx build --platform "linux/$ARCH" --push \
|
||||
--file tools/release/runtime/Dockerfile.api \
|
||||
--build-arg "PYTHON_IMAGE=$PYTHON_IMAGE" \
|
||||
--build-arg "GOVOPLAN_RELEASE_VERSION=$VERSION" \
|
||||
--build-arg "GOVOPLAN_COMPOSITION_SHA256=$COMPOSITION_SHA256" \
|
||||
--tag "git.add-ideas.de/govoplan/runtime-api:$VERSION-$ARCH" \
|
||||
"runtime-output/context-$ARCH"
|
||||
docker buildx build --platform "linux/$ARCH" --push \
|
||||
--file tools/release/runtime/Dockerfile.web \
|
||||
--build-arg "NGINX_IMAGE=$NGINX_IMAGE" \
|
||||
--build-arg "GOVOPLAN_RELEASE_VERSION=$VERSION" \
|
||||
--build-arg "GOVOPLAN_COMPOSITION_SHA256=$COMPOSITION_SHA256" \
|
||||
--tag "git.add-ideas.de/govoplan/runtime-web:$VERSION-$ARCH" \
|
||||
"runtime-output/context-$ARCH"
|
||||
done
|
||||
docker buildx imagetools create \
|
||||
--tag "git.add-ideas.de/govoplan/runtime-api:$VERSION" \
|
||||
"git.add-ideas.de/govoplan/runtime-api:$VERSION-amd64" \
|
||||
"git.add-ideas.de/govoplan/runtime-api:$VERSION-arm64"
|
||||
docker buildx imagetools create \
|
||||
--tag "git.add-ideas.de/govoplan/runtime-web:$VERSION" \
|
||||
"git.add-ideas.de/govoplan/runtime-web:$VERSION-amd64" \
|
||||
"git.add-ideas.de/govoplan/runtime-web:$VERSION-arm64"
|
||||
docker buildx imagetools inspect "git.add-ideas.de/govoplan/runtime-api:$VERSION" --raw > runtime-output/api-index.json
|
||||
docker buildx imagetools inspect "git.add-ideas.de/govoplan/runtime-web:$VERSION" --raw > runtime-output/web-index.json
|
||||
API_DIGEST="sha256:$(sha256sum runtime-output/api-index.json | cut -d' ' -f1)"
|
||||
WEB_DIGEST="sha256:$(sha256sum runtime-output/web-index.json | cut -d' ' -f1)"
|
||||
python tools/release/resolve-oci-platforms.py --repository git.add-ideas.de/govoplan/runtime-api --index-digest "$API_DIGEST" --index runtime-output/api-index.json --output runtime-output/api-metadata.json
|
||||
python tools/release/resolve-oci-platforms.py --repository git.add-ideas.de/govoplan/runtime-web --index-digest "$WEB_DIGEST" --index runtime-output/web-index.json --output runtime-output/web-metadata.json
|
||||
- name: Generate and sign distribution evidence
|
||||
working-directory: govoplan
|
||||
env:
|
||||
VERSION: ${{ inputs.version }}
|
||||
SOURCE_COMMIT: ${{ gitea.sha }}
|
||||
SIGNING_KEY: ${{ secrets.RUNTIME_DISTRIBUTION_SIGNING_KEY }}
|
||||
SIGNING_KEY_ID: ${{ secrets.RUNTIME_DISTRIBUTION_SIGNING_KEY_ID }}
|
||||
TRUSTED_KEYRING: ${{ secrets.RUNTIME_DISTRIBUTION_KEYRING }}
|
||||
POSTGRES_IMAGE: ${{ inputs.postgres_image }}
|
||||
REDIS_IMAGE: ${{ inputs.redis_image }}
|
||||
LOAD_BALANCER_IMAGE: ${{ inputs.load_balancer_image }}
|
||||
GARAGE_IMAGE: ${{ inputs.garage_image }}
|
||||
TEST_MAIL_IMAGE: ${{ inputs.test_mail_image }}
|
||||
run: |
|
||||
test -n "$SIGNING_KEY"
|
||||
test -n "$SIGNING_KEY_ID"
|
||||
test -n "$TRUSTED_KEYRING"
|
||||
printf '%s\n' "$SIGNING_KEY" > runtime-output/signing-key.pem
|
||||
printf '%s\n' "$TRUSTED_KEYRING" > runtime-output/distribution-keyring.json
|
||||
chmod 600 runtime-output/signing-key.pem
|
||||
ARTIFACT_BASE="https://git.add-ideas.de/GovOPlaN/govoplan/releases/download/v$VERSION"
|
||||
python tools/release/finalize-runtime-distribution.py \
|
||||
--composition runtime-output/context-amd64/composition.json \
|
||||
--api-metadata runtime-output/api-metadata.json \
|
||||
--web-metadata runtime-output/web-metadata.json \
|
||||
--deployer runtime-output/govoplan-deploy.pyz \
|
||||
--deployer-url "$ARTIFACT_BASE/govoplan-deploy.pyz" \
|
||||
--artifact-base-url "$ARTIFACT_BASE" \
|
||||
--source-commit "$SOURCE_COMMIT" \
|
||||
--version "$VERSION" \
|
||||
--sequence "$(date -u +%Y%m%d%H%M)" \
|
||||
--dependency "postgres=$POSTGRES_IMAGE" \
|
||||
--dependency "redis=$REDIS_IMAGE" \
|
||||
--dependency "load_balancer=$LOAD_BALANCER_IMAGE" \
|
||||
--dependency "garage=$GARAGE_IMAGE" \
|
||||
--dependency "test_mail=$TEST_MAIL_IMAGE" \
|
||||
--output-directory runtime-output/evidence \
|
||||
--descriptor runtime-output/distribution-descriptor.json
|
||||
python tools/release/generate-runtime-distribution.py \
|
||||
--descriptor runtime-output/distribution-descriptor.json \
|
||||
--signing-key "$SIGNING_KEY_ID=runtime-output/signing-key.pem" \
|
||||
--output runtime-output/distribution-manifest.json
|
||||
openssl pkeyutl -sign -inkey runtime-output/signing-key.pem -rawin \
|
||||
-in runtime-output/govoplan-deploy.pyz \
|
||||
-out runtime-output/govoplan-deploy.pyz.sig
|
||||
sha256sum runtime-output/govoplan-deploy.pyz > runtime-output/govoplan-deploy.pyz.sha256
|
||||
sha256sum runtime-output/distribution-manifest.json > runtime-output/distribution-manifest.json.sha256
|
||||
rm runtime-output/signing-key.pem
|
||||
- name: Verify the published bundle contract with the zipapp
|
||||
working-directory: govoplan
|
||||
env:
|
||||
VERSION: ${{ inputs.version }}
|
||||
run: |
|
||||
MANIFEST_SHA256="$(cut -d' ' -f1 runtime-output/distribution-manifest.json.sha256)"
|
||||
python runtime-output/govoplan-deploy.pyz init \
|
||||
--directory runtime-output/acceptance-install \
|
||||
--non-interactive --module-set base
|
||||
python runtime-output/govoplan-deploy.pyz verify-release \
|
||||
--directory runtime-output/acceptance-install \
|
||||
--manifest runtime-output/distribution-manifest.json \
|
||||
--manifest-sha256 "$MANIFEST_SHA256" \
|
||||
--trusted-keyring runtime-output/distribution-keyring.json \
|
||||
--adopt
|
||||
- name: Publish immutable Gitea release assets
|
||||
working-directory: govoplan
|
||||
env:
|
||||
VERSION: ${{ inputs.version }}
|
||||
GITEA_RELEASE_TOKEN: ${{ secrets.GOVOPLAN_RELEASE_TOKEN }}
|
||||
run: |
|
||||
python tools/release/publish-runtime-release.py \
|
||||
--tag "v$VERSION" \
|
||||
--title "GovOPlaN v$VERSION runtime distribution" \
|
||||
--asset runtime-output/govoplan-deploy.pyz \
|
||||
--asset runtime-output/govoplan-deploy.pyz.sig \
|
||||
--asset runtime-output/govoplan-deploy.pyz.sha256 \
|
||||
--asset runtime-output/distribution-manifest.json \
|
||||
--asset runtime-output/distribution-manifest.json.sha256 \
|
||||
--asset runtime-output/distribution-keyring.json \
|
||||
--asset runtime-output/context-amd64/composition.json \
|
||||
--asset runtime-output/evidence/api-sbom.cdx.json \
|
||||
--asset runtime-output/evidence/web-sbom.cdx.json \
|
||||
--asset runtime-output/evidence/api-provenance.json \
|
||||
--asset runtime-output/evidence/web-provenance.json
|
||||
Reference in New Issue
Block a user