Files
ngit-grasp/.ngit/act/workflows/container_backfill.yaml
DanConwayDev 5fed50e5e3 ci(release): publish OCI container images
Motivation: Release images should be built, checked, published, and consumed through the same Nostr-native OCI path operators will use, without relying on an unreviewed local release procedure.

Approach: Add a checked-in container manifest, a Docker-to-OCI layout helper, automatic tag publication and pull verification, a safe exact-tag backfill workflow, and deployment CI that imports and runs the exact generated layout.

Correctness: Release tags come only from reviewed OCI index annotations; ordinary publication preserves prior tags; historical backfills cannot move latest or prerelease channels; generated images and temporary resources use bounded, validated names and cleanup.

Excluded scope: This change does not alter ngit-grasp runtime behavior, change package versions, create v3.0.2, publish a container, move a release tag, or run the heavyweight container build in the coding VM.

Validation: git diff --check; shellcheck on all container scripts; actionlint on all affected workflows; ngit parsing of .ngit/containers.yaml; canonical source and v3.0.1 tag resolution. The PR pipeline performs the full OCI build, import, and deployment test.

Assisted-by: Codex (GPT-5)
2026-09-10 15:30:13 +00:00

91 lines
3.1 KiB
YAML

on:
workflow_dispatch:
name: container release backfill
jobs:
linux-x86_64:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v5
- uses: danconwaydev/setup-ngit@v3
- uses: cachix/install-nix-action@v31
with:
nix_path: nixpkgs=channel:nixos-unstable
- name: Require the disposable guest container daemon
shell: bash
run: |
if [[ ! -S /var/run/docker.sock ]]; then
echo "container daemon socket is not available" >&2
echo "this workflow requires an ngit-ci operator opt-in" >&2
exit 1
fi
- name: Build exact release OCI layout
shell: bash
run: |
set -euo pipefail
case "$GITHUB_REF" in
refs/tags/v*) ;;
*)
echo "manual container publication requires a refs/tags/v* context" >&2
exit 1
;;
esac
version="${GITHUB_REF#refs/tags/v}"
if [[ -z "$version" || "$version" == *[!A-Za-z0-9._-]* ]]; then
echo "unsupported release version from tag: $GITHUB_REF" >&2
exit 1
fi
git fetch --depth=1 --no-tags \
https://ngit.dev/ngit-grasp.git "$GITHUB_REF"
revision="$(git rev-parse 'FETCH_HEAD^{commit}')"
source_directory="$RUNNER_TEMP/ngit-grasp-${revision}"
mkdir "$source_directory"
git archive FETCH_HEAD | tar -xf - -C "$source_directory"
source_version="$(nix eval --raw "path:${source_directory}#static.version")"
if [[ "$version" != "$source_version" ]]; then
echo "tag version $version does not match package version $source_version" >&2
exit 1
fi
layout="$PWD/artifacts/ngit-grasp"
CONTAINER_CONTEXT="$source_directory" \
CONTAINER_EXACT_ONLY=true \
nix shell nixpkgs#docker-client nixpkgs#jq nixpkgs#skopeo \
--command scripts/build-container-layout.sh \
"$version" "$revision" "$layout"
- name: Publish exact container tag
shell: bash
env:
NGIT_PUBLISHER_NBUNKSEC: ${{ secrets.NGIT_PUBLISHER_NBUNKSEC }}
run: |
set -euo pipefail
: "${NGIT_PUBLISHER_NBUNKSEC:?Set the NGIT_PUBLISHER_NBUNKSEC repository secret}"
umask 077
signer_file="$RUNNER_TEMP/ngit-container-nbunksec"
trap 'rm -f "$signer_file"' EXIT
printf '%s\n' "$NGIT_PUBLISHER_NBUNKSEC" > "$signer_file"
ngit container publish ngit-grasp \
--repo nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/relay.ngit.dev/ngit-grasp \
--manifest .ngit/containers.yaml \
--nbunksec-file "$signer_file" \
--defaults \
--repo-relay-only \
--json
- name: Pull and verify the published image
shell: bash
run: |
set -euo pipefail
version="${GITHUB_REF#refs/tags/v}"
nix shell nixpkgs#docker-client \
--command scripts/verify-published-container.sh "$version"