Skip to content
Merged
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
22 changes: 18 additions & 4 deletions .github/workflows/ci-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ jobs:
outputs:
semver: ${{ steps.tag_semver.outputs.version }}
trunkver: ${{ steps.tag_trunkver.outputs.trunkver }}
image-artifact-name: ${{ steps.artifact_names.outputs.image-artifact-name }}
sbom-artifact-name: ${{ steps.artifact_names.outputs.sbom-artifact-name }}
permissions:
contents: read
env:
Expand All @@ -279,6 +281,18 @@ jobs:
with:
fetch-depth: 0

- id: artifact_names
name: Calculate artifact names
shell: bash
env:
IMAGE_ARTIFACT_NAME: ${{ env.IMAGE_ARTIFACT_NAME }}
SBOM_ARTIFACT_NAME: ${{ env.SBOM_ARTIFACT_NAME }}
run: |
set -euo pipefail

printf 'image-artifact-name=%s\n' "$IMAGE_ARTIFACT_NAME" >> "$GITHUB_OUTPUT"
printf 'sbom-artifact-name=%s\n' "$SBOM_ARTIFACT_NAME" >> "$GITHUB_OUTPUT"

- name: Build Docker image
uses: ./.github/actions/docker-build
with:
Expand Down Expand Up @@ -344,7 +358,7 @@ jobs:
env:
SEMVER_IMAGE_REF: ${{ needs.init.outputs.container-repository }}:${{ needs.container_build.outputs.semver }}
TRUNKVER_IMAGE_REF: ${{ needs.init.outputs.container-repository }}:${{ needs.container_build.outputs.trunkver }}
IMAGE_ARTIFACT_NAME: container-image-${{ github.run_id }}-${{ github.run_attempt }}
IMAGE_ARTIFACT_NAME: ${{ needs.container_build.outputs.image-artifact-name }}
REGISTRY: ${{ needs.init.outputs.container-registry }}
steps:
- name: Check out local actions
Expand Down Expand Up @@ -434,7 +448,7 @@ jobs:
STAGING_IMAGE_DIGEST: ${{ needs.container_publish.outputs.image-digest }}
DOCKERHUB_REPOSITORY: docker.io/${{ needs.init.outputs.dockerhub-repository }}
DOCKERHUB_REGISTRY: docker.io
IMAGE_ARTIFACT_NAME: container-image-${{ github.run_id }}-${{ github.run_attempt }}
IMAGE_ARTIFACT_NAME: ${{ needs.container_build.outputs.image-artifact-name }}
steps:
- name: Check out local actions
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand Down Expand Up @@ -543,7 +557,7 @@ jobs:
env:
IMAGE_REPOSITORY: docker.io/${{ needs.init.outputs.dockerhub-repository }}
IMAGE_DIGEST: ${{ needs.container_promote_dockerhub.outputs.image-digest }}
SBOM_ARTIFACT_NAME: container-sbom-${{ github.run_id }}-${{ github.run_attempt }}
SBOM_ARTIFACT_NAME: ${{ needs.container_build.outputs.sbom-artifact-name }}
steps:
- name: Check out local actions
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand Down Expand Up @@ -583,7 +597,7 @@ jobs:
env:
IMAGE_REPOSITORY: ${{ needs.init.outputs.container-repository }}
IMAGE_DIGEST: ${{ needs.container_publish.outputs.image-digest }}
SBOM_ARTIFACT_NAME: container-sbom-${{ github.run_id }}-${{ github.run_attempt }}
SBOM_ARTIFACT_NAME: ${{ needs.container_build.outputs.sbom-artifact-name }}
steps:
- name: Check out local actions
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,11 +217,11 @@ The saved image receives two tags:
- SemVer from `needs.build.outputs.version`, with one leading `v` removed. For example, `v2.0.0` becomes `2.0.0` for compatibility with the existing Docker Hub `1.4.0` naming.
- A [TrunkVer](https://trunkver.org/) generated once during the container build and reused for both registries.

Use a manually dispatched run with `publish_image: true` to publish the saved tarball to the `Staging` environment. The default staging repository is `jcr.codebelt.net/geekle/web-cdn-origin`; override `container_repository` when needed. Configure `JCR_USERNAME` and `JCR_PASSWORD` as `Staging` environment secrets.
Use a manually dispatched run with `publish_image: true` to publish the saved tarball to the `Staging` environment. The default staging repository is `jcr.codebelt.net/geekle/web-cdn-origin`; override `container_repository` when needed. Configure the exact `REGISTRY_USERNAME` and `REGISTRY_PASSWORD` secret names in the `Staging` environment. The values must be accepted by the selected container registry, so the same generic secret names work when `container_repository` is overridden.

To keep the exact same run artifact, set both `publish_image: true` and `promote_dockerhub: true` on the manual dispatch. The workflow publishes to Staging and then pauses at the protected `Production` environment, allowing you to verify JCR before approving Docker Hub publication. Configure required reviewers for `Production` and add `DOCKERHUB_USERNAME` and `DOCKERHUB_TOKEN` as its environment secrets. The default Docker Hub repository is `codebeltnet/web-cdn-origin`; override `dockerhub_repository` when needed. A run with `promote_dockerhub: false` intentionally stops after Staging; enabling it on a later run creates a new build artifact.
To keep the exact same run artifact, set both `publish_image: true` and `promote_dockerhub: true` on the manual dispatch. The workflow publishes to Staging and then pauses at the protected `Production` environment, allowing you to verify JCR before approving Docker Hub publication. Configure required reviewers for `Production` and add the exact `DOCKERHUB_USERNAME` and `DOCKERHUB_TOKEN` secret names to that environment. `DOCKERHUB_TOKEN` must be a Docker Hub access token with permission to push to the target namespace; a normal account password is not expected. The default Docker Hub repository is `codebeltnet/web-cdn-origin`; override `dockerhub_repository` when needed. A run with `promote_dockerhub: false` intentionally stops after Staging; enabling it on a later run creates a new build artifact.

This is a promotion of one immutable build artifact: the Docker Hub job downloads the same `docker save` tarball, uses `docker load`, retags it for Docker Hub, and pushes both tags. It does not rebuild or pull a new image. Digest gates verify that the SemVer and TrunkVer tags point to the same image in each registry and that the Docker Hub digest matches Staging. Attestation jobs publish GitHub build-provenance and SBOM attestations for the pushed digest, so each target registry must accept OCI attestation artifacts.
This is a promotion of one immutable build artifact: the Docker Hub job downloads the same `docker save` tarball, uses `docker load`, retags it for Docker Hub, and pushes both tags. It does not rebuild or pull a new image. The build job carries the image and SBOM artifact names to downstream jobs, so rerunning only a failed publish or attestation job reuses the artifact from the successful build attempt. Digest gates verify that the SemVer and TrunkVer tags point to the same image in each registry and that the Docker Hub digest matches Staging. Attestation jobs publish GitHub build-provenance and SBOM attestations for the pushed digest, so each target registry must accept OCI attestation artifacts.

## Kubernetes

Expand Down
Loading