Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/workflows/internal-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ jobs:
type=sha,prefix=sha-,format=long

- name: Build and push image
id: build
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a
with:
context: .
Expand All @@ -71,3 +72,22 @@ jobs:
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=codex-lb-internal
cache-to: type=gha,mode=max,scope=codex-lb-internal

- name: Request CHEK Beijing mirror

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Allow retrying the mirror dispatch after GHCR publication

If the GHCR push succeeds but this repository-dispatch request fails—for example because of a transient GitHub API error or an expired/mis-scoped GH_PAT—rerunning the workflow exits at the existing-tag guard before reaching this step. The affected commit therefore cannot be re-dispatched through this workflow, leaving its Beijing mirror absent even though its immutable source image exists; handle an existing GHCR tag as a recovery path by resolving its digest and reissuing the dispatch without rebuilding or overwriting it.

Useful? React with 👍 / 👎.

env:
GH_PAT: ${{ secrets.GH_PAT }}
IMAGE_DIGEST: ${{ steps.build.outputs.digest }}
run: |
test -n "${GH_PAT}"
test -n "${IMAGE_DIGEST}"
payload=$(jq -nc \
--arg sha "${GITHUB_SHA}" \
--arg digest "${IMAGE_DIGEST}" \
'{event_type:"codex-lb-image-published",client_payload:{sha:$sha,digest:$digest}}')
curl --fail-with-body --silent --show-error \
--request POST \
--header "Accept: application/vnd.github+json" \
--header "Authorization: Bearer ${GH_PAT}" \
--header "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/chekdata/ops-bootstrap/dispatches \
--data "${payload}"
13 changes: 8 additions & 5 deletions openspec/changes/publish-chek-internal-images/proposal.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,21 @@ repository-owned image publisher.
## What Changes

- Add a focused GitHub Actions workflow that publishes the fork to
`ghcr.io/chekdata/codex-lb` after a push to `main` or an explicit manual run.
`ghcr.io/chekdata/codex-lb`, then requests an authenticated mirror into
CHEK's Beijing production registry after a push to `main` or an explicit
manual run.
- Publish both supported Linux architectures in one manifest.
- Publish an immutable full-SHA tag for GitOps while granting the workflow only
read-content and write-package access; do not publish a mutable `main` tag.
- Fail closed before building when the full-SHA tag already exists or the
registry cannot prove that it is absent.
- Keep production registry credentials in the private operations repository;
the public fork sends only the reviewed commit SHA and built image digest.
- Serialize all runs for the same commit across branch and tag aliases so the
absence check and first publication cannot race.

## Impact

- Affected capability: `github-automation`
- Affected automation: `.github/workflows/internal-image.yml`
- Production manifests can pin a reviewed `sha-*` image without depending on
upstream publishing permissions or abbreviated-tag collisions.
- Production manifests can pin a reviewed `sha-*` image from the in-region
registry without giving its public source repository production registry
credentials or depending on cross-region runtime pulls.
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,25 @@
### Requirement: CHEK fork publishes internally owned container images

The `chekdata/codex-lb` repository SHALL build and publish a container image to
`ghcr.io/chekdata/codex-lb` after changes land on `main` and when an operator
explicitly dispatches the workflow. The published manifest MUST support
`linux/amd64` and `linux/arm64`, MUST include an immutable `sha-<full-commit>`
tag, and MUST NOT publish a mutable `main` tag. Production GitOps consumers
MUST be able to select the immutable tag.

Before publishing, the workflow MUST prove that the full-SHA tag does not
already exist. It MUST fail without building when the tag exists and MUST fail
closed when a registry or network error prevents that absence check. It MUST
NOT overwrite a previously published full-SHA tag. Runs selecting the same
commit through different branch or tag refs MUST be serialized by the full
commit SHA and MUST NOT cancel the run that currently owns publication.
`ghcr.io/chekdata/codex-lb`, then request an authenticated private operations
workflow to mirror that image into CHEK's Beijing production registry, after
changes land on `main` and when an operator explicitly dispatches the workflow.
Each published manifest MUST support `linux/amd64` and `linux/arm64`, MUST
include an immutable `sha-<full-commit>` tag, and MUST NOT publish a mutable
`main` tag. Production GitOps consumers MUST be able to select the immutable
in-region tag.

Before publishing, the source workflow MUST prove that the GHCR full-SHA tag
does not already exist and MUST fail closed when a registry or network error
prevents that absence check. It MUST NOT overwrite a previously published
full-SHA tag. After the build succeeds, it MUST dispatch only the selected full
commit SHA and resulting image digest to the private operations repository;
production registry write credentials MUST NOT be configured in the public
fork. The private mirror workflow MUST verify that the selected commit belongs
to the `main` history and MUST use repository-scoped, temporary registry
credentials. Runs selecting the same commit through different branch or tag
refs MUST be serialized by the full commit SHA and MUST NOT cancel the run that
currently owns publication.

The workflow MUST use pinned action revisions and MUST limit its repository
permissions to reading contents and writing packages. Pull request events MUST
Expand All @@ -24,6 +31,8 @@ NOT publish images.

- **WHEN** a reviewed commit lands on `main`
- **THEN** the workflow publishes `ghcr.io/chekdata/codex-lb:sha-<full-commit>`
- **AND** it requests the private operations workflow to mirror that exact SHA
and digest to CHEK's Beijing production registry
- **AND** the image manifest supports `linux/amd64` and `linux/arm64`
- **AND** the run does not publish a mutable `main` tag

Expand All @@ -40,16 +49,23 @@ NOT publish images.
- **THEN** the workflow builds and publishes the selected commit with its
immutable full-SHA tag

#### Scenario: Repeated publication cannot change an immutable tag
#### Scenario: Production credentials stay private

- **GIVEN** the selected commit's full-SHA tag already exists in GHCR
- **WHEN** the workflow is rerun or manually dispatched for that commit
- **THEN** it fails before the image build
- **AND** the existing tag is not overwritten
- **WHEN** the public fork publishes a reviewed image
- **THEN** it sends only the full commit SHA and built digest to the private
operations repository
- **AND** the public fork does not receive production registry write credentials

#### Scenario: Private mirror validates production provenance

- **WHEN** the private operations workflow receives a mirror request
- **THEN** it verifies the commit belongs to the `chekdata/codex-lb` main history
- **AND** it verifies the GHCR tag resolves to the dispatched digest
- **AND** it uses temporary registry credentials scoped to `prod/codex-lb`

#### Scenario: Registry uncertainty fails closed

- **GIVEN** the workflow cannot determine whether the full-SHA tag exists
- **GIVEN** the workflow cannot determine whether either full-SHA tag exists
- **WHEN** the pre-publish check encounters a registry or network error
- **THEN** the workflow fails without publishing

Expand Down
8 changes: 7 additions & 1 deletion openspec/changes/publish-chek-internal-images/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@
- [x] 1.4 Refuse to overwrite an existing full-SHA tag and fail closed when its
registry state cannot be confirmed
- [x] 1.5 Serialize publication by full commit SHA across branch and tag refs
- [x] 1.6 Request a private operations workflow to mirror the reviewed GHCR
SHA and digest into CHEK's Beijing production registry
- [x] 1.7 Keep production registry credentials out of the public fork
- [x] 1.8 Require main-history provenance and scoped temporary credentials in
the private mirror workflow

## 2. Verification

- [x] 2.1 Validate the workflow YAML and repository action policy
- [x] 2.2 Run strict OpenSpec validation
- [ ] 2.3 Merge the focused PR and verify the first main-branch image manifest
- [x] 2.3 Merge the focused GHCR PR and verify the first main-branch image manifest
- [ ] 2.4 Merge the Beijing registry enhancement and verify both manifests
Loading