333 lines
14 KiB
YAML
333 lines
14 KiB
YAML
name: gcp-leoclean-nosend-release
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: read
|
|
id-token: write
|
|
|
|
concurrency:
|
|
group: gcp-leoclean-nosend-release-main
|
|
cancel-in-progress: false
|
|
|
|
env:
|
|
PROJECT_ID: teleo-501523
|
|
REGION: europe-west6
|
|
ARTIFACT_REPOSITORY: teleo
|
|
IMAGE_REPOSITORY: europe-west6-docker.pkg.dev/teleo-501523/teleo/leoclean-nosend-staging
|
|
WORKLOAD_IDENTITY_PROVIDER: projects/785938879453/locations/global/workloadIdentityPools/github-actions/providers/living-ip-github
|
|
ARTIFACT_SERVICE_ACCOUNT: sa-artifact-builder@teleo-501523.iam.gserviceaccount.com
|
|
|
|
jobs:
|
|
publish:
|
|
name: Build, smoke, and publish exact no-send release
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 90
|
|
steps:
|
|
- name: Require manual main dispatch
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
test "${GITHUB_EVENT_NAME}" = "workflow_dispatch"
|
|
test "${GITHUB_REF}" = "refs/heads/main"
|
|
test "${GITHUB_REF_TYPE}" = "branch"
|
|
test "${GITHUB_REPOSITORY}" = "living-ip/teleo-infrastructure"
|
|
test "${GITHUB_WORKFLOW_REF}" = \
|
|
"living-ip/teleo-infrastructure/.github/workflows/gcp-leoclean-nosend-release.yml@refs/heads/main"
|
|
|
|
- name: Check out exact dispatched revision
|
|
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
|
|
with:
|
|
fetch-depth: 0
|
|
persist-credentials: false
|
|
ref: ${{ github.sha }}
|
|
|
|
- name: Verify exact clean main revision
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
test "$(git rev-parse --verify HEAD)" = "${GITHUB_SHA}"
|
|
test "$(git rev-parse --verify refs/remotes/origin/main^{commit})" = "${GITHUB_SHA}"
|
|
test -z "$(git status --porcelain=v1 --untracked-files=all)"
|
|
|
|
- name: Initialize private release paths
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
release_root="${RUNNER_TEMP}/leoclean-nosend-release"
|
|
install -d -m 0700 "${release_root}"
|
|
{
|
|
echo "RELEASE_ROOT=${release_root}"
|
|
echo "RUNTIME_ARTIFACT=${release_root}/runtime-artifact"
|
|
echo "RUNTIME_RECEIPT=${release_root}/evidence/runtime-receipt.json"
|
|
echo "OCI_SMOKE_RECEIPT=${release_root}/evidence/oci-smoke.json"
|
|
echo "IMAGE_CONTEXT=${release_root}/image-context"
|
|
echo "BUILD_PUSH_RECEIPT=${release_root}/receipts/build-push-receipt.json"
|
|
echo "PUBLISH_OUTCOME=${release_root}/evidence/publish-outcome.json"
|
|
echo "RELEASE_BUNDLE=${release_root}/final/release-v3"
|
|
echo "DOCKER_CONFIG=${release_root}/docker-config"
|
|
} >>"${GITHUB_ENV}"
|
|
|
|
- name: Set up exact Python
|
|
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065
|
|
with:
|
|
python-version: "3.11.9"
|
|
|
|
- name: Install exact no-send build tools
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
python -m pip install --disable-pip-version-check 'uv==0.9.30' 'PyYAML==6.0.3'
|
|
test "$(uv --version | awk '{print $2}')" = "0.9.30"
|
|
test "$(command -v docker)" = "/usr/bin/docker"
|
|
|
|
- name: Verify fixed staging package target
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
python - <<'PY'
|
|
import os
|
|
|
|
from ops import gcp_leoclean_nosend_package as package
|
|
|
|
assert package.PROJECT == "teleo-501523"
|
|
assert package.PLATFORM == "linux/amd64"
|
|
assert os.environ["IMAGE_REPOSITORY"] == package.IMAGE_REPOSITORY
|
|
assert package.IMAGE_REPOSITORY == "europe-west6-docker.pkg.dev/teleo-501523/teleo/leoclean-nosend-staging"
|
|
PY
|
|
|
|
- name: Pull digest-pinned OCI bases
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
docker pull --platform=linux/amd64 \
|
|
"ghcr.io/astral-sh/uv:0.9.30@sha256:538e0b39736e7feae937a65983e49d2ab75e1559d35041f9878b7b7e51de91e4"
|
|
docker pull --platform=linux/amd64 \
|
|
"docker.io/library/python:3.11.9-slim-bookworm@sha256:8fb099199b9f2d70342674bd9dbccd3ed03a258f26bbd1d556822c6dfc60c317"
|
|
docker pull --platform=linux/amd64 \
|
|
"docker.io/library/postgres:16.14-bookworm@sha256:92620daddcd947f8d5ab5ba66e848702fe443d87fed30c4cea8e389fd78dfc55"
|
|
|
|
- name: Compile and release-verify exact runtime artifact
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
install -d -m 0700 "${RELEASE_ROOT}" "${RELEASE_ROOT}/evidence"
|
|
LEOCLEAN_NOSEND_RESULTS_DIR="${RELEASE_ROOT}/evidence" \
|
|
LEOCLEAN_NOSEND_RECEIPT="${RUNTIME_RECEIPT}" \
|
|
LEOCLEAN_NOSEND_ARTIFACT_OUTPUT="${RUNTIME_ARTIFACT}" \
|
|
scripts/run_leoclean_nosend_runtime_canary.sh
|
|
|
|
- name: Smoke exact no-send OCI surface
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
python scripts/run_gcp_leoclean_nosend_oci_smoke.py \
|
|
--repo-root "${GITHUB_WORKSPACE}" \
|
|
--artifact "${RUNTIME_ARTIFACT}" \
|
|
--runtime-receipt "${RUNTIME_RECEIPT}" \
|
|
--output "${OCI_SMOKE_RECEIPT}"
|
|
|
|
- name: Prepare exact candidate context
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
identity_contract="${RELEASE_ROOT}/identity-runtime-contract.json"
|
|
identity_manifest="${RELEASE_ROOT}/identity-manifest.json"
|
|
identity_bundle="${RELEASE_ROOT}/identity"
|
|
|
|
python ops/gcp_leoclean_nosend_package.py identity-contract \
|
|
--repo-root "${GITHUB_WORKSPACE}" \
|
|
--artifact "${RUNTIME_ARTIFACT}" \
|
|
--receipt "${RUNTIME_RECEIPT}" \
|
|
--output "${identity_contract}"
|
|
python ops/gcp_leoclean_nosend_package.py generate-identity-manifest \
|
|
--repo-root "${GITHUB_WORKSPACE}" \
|
|
--artifact "${RUNTIME_ARTIFACT}" \
|
|
--receipt "${RUNTIME_RECEIPT}" \
|
|
--database-fingerprint fixtures/working-leo/leo-identity-v1/leo-database-fingerprint-v1.json \
|
|
--constitution fixtures/working-leo/leo-identity-v1/leo-constitution-v1.json \
|
|
--database-identity fixtures/working-leo/leo-identity-v1/leo-database-identity-v1.json \
|
|
--identity-source-root "${GITHUB_WORKSPACE}" \
|
|
--output "${identity_manifest}"
|
|
python ops/gcp_leoclean_nosend_package.py compile-identity \
|
|
--repo-root "${GITHUB_WORKSPACE}" \
|
|
--artifact "${RUNTIME_ARTIFACT}" \
|
|
--receipt "${RUNTIME_RECEIPT}" \
|
|
--identity-manifest "${identity_manifest}" \
|
|
--identity-source-root "${GITHUB_WORKSPACE}" \
|
|
--output "${identity_bundle}"
|
|
python ops/gcp_leoclean_nosend_package.py prepare \
|
|
--repo-root "${GITHUB_WORKSPACE}" \
|
|
--artifact "${RUNTIME_ARTIFACT}" \
|
|
--receipt "${RUNTIME_RECEIPT}" \
|
|
--identity "${identity_bundle}" \
|
|
--identity-source-root "${GITHUB_WORKSPACE}" \
|
|
--output "${IMAGE_CONTEXT}"
|
|
|
|
python - "${OCI_SMOKE_RECEIPT}" "${IMAGE_CONTEXT}/image-input.json" "${GITHUB_SHA}" <<'PY'
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
smoke = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
|
|
image_input = json.loads(Path(sys.argv[2]).read_text(encoding="utf-8"))
|
|
revision = sys.argv[3]
|
|
assert smoke["status"] == "pass"
|
|
assert smoke["cleanup"]["status"] == "pass"
|
|
assert smoke["teleo_git_head"] == revision
|
|
assert image_input["runtime"]["teleo_git_head"] == revision
|
|
assert smoke["input_sha256"] == image_input["input_sha256"]
|
|
assert smoke["identity_sha256"] == image_input["identity"]["bundle_sha256"]
|
|
PY
|
|
|
|
- name: Initialize pre-mutation publish outcome
|
|
id: init_outcome
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
install -d -m 0700 "$(dirname "${PUBLISH_OUTCOME}")"
|
|
python ops/gcp_leoclean_nosend_package.py init-outcome \
|
|
--image-input "${IMAGE_CONTEXT}/image-input.json" \
|
|
--output-journal "${PUBLISH_OUTCOME}"
|
|
|
|
- name: Authenticate to Google Cloud through WIF
|
|
id: auth
|
|
uses: google-github-actions/auth@c200f3691d83b41bf9bbd8638997a462592937ed
|
|
with:
|
|
workload_identity_provider: ${{ env.WORKLOAD_IDENTITY_PROVIDER }}
|
|
service_account: ${{ env.ARTIFACT_SERVICE_ACCOUNT }}
|
|
create_credentials_file: true
|
|
export_environment_variables: true
|
|
|
|
- name: Set up exact gcloud
|
|
uses: google-github-actions/setup-gcloud@e427ad8a34f8676edf47cf7d7925499adf3eb74f
|
|
with:
|
|
version: "550.0.0"
|
|
|
|
- name: Require immutable fixed Artifact Registry repository
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
repository_readback="${RUNNER_TEMP}/leoclean-nosend-repository.json"
|
|
umask 077
|
|
test "$(gcloud auth list --filter=status:ACTIVE --format='value(account)')" = \
|
|
"${ARTIFACT_SERVICE_ACCOUNT}"
|
|
gcloud artifacts repositories describe "${ARTIFACT_REPOSITORY}" \
|
|
--project "${PROJECT_ID}" \
|
|
--location "${REGION}" \
|
|
--format json >"${repository_readback}"
|
|
python - "${repository_readback}" <<'PY'
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
repository = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
|
|
assert repository["name"] == (
|
|
"projects/teleo-501523/locations/europe-west6/repositories/teleo"
|
|
)
|
|
assert repository["format"] == "DOCKER"
|
|
assert repository["dockerConfig"]["immutableTags"] is True
|
|
PY
|
|
rm -f -- "${repository_readback}"
|
|
|
|
- name: Configure private Artifact Registry Docker auth
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
install -d -m 0700 "${DOCKER_CONFIG}"
|
|
gcloud auth configure-docker "${REGION}-docker.pkg.dev" --quiet
|
|
test -f "${DOCKER_CONFIG}/config.json"
|
|
test ! -L "${DOCKER_CONFIG}/config.json"
|
|
chmod 0600 "${DOCKER_CONFIG}/config.json"
|
|
|
|
- name: Build and push one immutable candidate
|
|
id: build_push
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
install -d -m 0700 "$(dirname "${BUILD_PUSH_RECEIPT}")"
|
|
python ops/gcp_leoclean_nosend_package.py build-push \
|
|
--repo-root "${GITHUB_WORKSPACE}" \
|
|
--image-context "${IMAGE_CONTEXT}" \
|
|
--docker-binary /usr/bin/docker \
|
|
--docker-host unix:///var/run/docker.sock \
|
|
--docker-config "${DOCKER_CONFIG}" \
|
|
--gcloud-binary "$(command -v gcloud)" \
|
|
--output-receipt "${BUILD_PUSH_RECEIPT}" \
|
|
--outcome-journal "${PUBLISH_OUTCOME}" \
|
|
--execute-staging-push
|
|
|
|
- name: Finalize and validate release v3 bundle
|
|
id: finalize
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
install -d -m 0700 "$(dirname "${RELEASE_BUNDLE}")"
|
|
python ops/gcp_leoclean_nosend_package.py finalize \
|
|
--image-input "${IMAGE_CONTEXT}/image-input.json" \
|
|
--build-push-receipt "${BUILD_PUSH_RECEIPT}" \
|
|
--docker-binary /usr/bin/docker \
|
|
--docker-host unix:///var/run/docker.sock \
|
|
--docker-config "${DOCKER_CONFIG}" \
|
|
--output-bundle "${RELEASE_BUNDLE}"
|
|
python ops/gcp_leoclean_nosend_package.py validate \
|
|
--release "${RELEASE_BUNDLE}/release.json"
|
|
|
|
python - "${BUILD_PUSH_RECEIPT}" "${RELEASE_BUNDLE}/release.json" "${OCI_SMOKE_RECEIPT}" "${GITHUB_SHA}" <<'PY'
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
receipt = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
|
|
release = json.loads(Path(sys.argv[2]).read_text(encoding="utf-8"))
|
|
smoke = json.loads(Path(sys.argv[3]).read_text(encoding="utf-8"))
|
|
revision = sys.argv[4]
|
|
assert receipt["schema"] == "livingip.leocleanNoSendBuildPushReceipt.v1"
|
|
assert release["schema"] == "livingip.leocleanNoSendRelease.v3"
|
|
assert release["build_push_receipt"] == receipt
|
|
assert release["image_input"]["runtime"]["teleo_git_head"] == revision
|
|
assert release["image_input"]["input_sha256"] == smoke["input_sha256"]
|
|
assert release["image"]["reference"].startswith(
|
|
"europe-west6-docker.pkg.dev/teleo-501523/teleo/leoclean-nosend-staging@sha256:"
|
|
)
|
|
PY
|
|
|
|
- name: Remove ephemeral Docker authentication
|
|
id: cleanup
|
|
if: always()
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
rm -rf -- "${DOCKER_CONFIG}"
|
|
test ! -e "${DOCKER_CONFIG}"
|
|
test ! -L "${DOCKER_CONFIG}"
|
|
|
|
- name: Finalize publish outcome
|
|
if: always() && steps.init_outcome.outcome == 'success'
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
python ops/gcp_leoclean_nosend_package.py complete-outcome \
|
|
--image-input "${IMAGE_CONTEXT}/image-input.json" \
|
|
--outcome-journal "${PUBLISH_OUTCOME}" \
|
|
--build-push-receipt "${BUILD_PUSH_RECEIPT}" \
|
|
--release "${RELEASE_BUNDLE}/release.json" \
|
|
--build-outcome "${{ steps.build_push.outcome }}" \
|
|
--finalize-outcome "${{ steps.finalize.outcome }}" \
|
|
--cleanup-outcome "${{ steps.cleanup.outcome }}"
|
|
|
|
- name: Upload exact available build and release evidence
|
|
if: always()
|
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
|
|
with:
|
|
name: leoclean-nosend-release-${{ github.sha }}
|
|
path: |
|
|
${{ runner.temp }}/leoclean-nosend-release/evidence/runtime-receipt.json
|
|
${{ runner.temp }}/leoclean-nosend-release/evidence/oci-smoke.json
|
|
${{ runner.temp }}/leoclean-nosend-release/evidence/publish-outcome.json
|
|
${{ runner.temp }}/leoclean-nosend-release/receipts/build-push-receipt.json
|
|
${{ runner.temp }}/leoclean-nosend-release/final/release-v3/release.json
|
|
${{ runner.temp }}/leoclean-nosend-release/final/release-v3/leoclean-gcp-nosend.service
|
|
if-no-files-found: warn
|
|
retention-days: 30
|