Files
cnpg-postgres-containers/.github/actions/copy-images

Copy Images Action

This composite GitHub Action copies a set of container images from a testing registry to a production registry, and signs them using Cosign. It requires as input Bake's build result metadata, which is the output provided by the bake-action.


How it works

The action assumes a consistent naming convention between your testing and production registries.

  • A production image is named like ghcr.io/org/image
  • The corresponding testing image must include a suffix, e.g. ghcr.io/org/image-testing

You can customize this suffix with the inputs.test_registry_suffix input.

The action proceeds as follows:

  1. It retrieves all image references from inputs.bake_build_metadata
  2. It generates a list of destination images by stripping out the test_registry_suffix from each image
  3. Each image is copied to the destination registry using Skopeo copy. The digest of the image is preserved.
  4. Each production image is signed using Cosign

Requirements

This composite action requires the calling workflows GITHUB_TOKEN to have the following permissions:

permissions:
  contents: read
  packages: write
  id-token: write # needed by Cosign for signing the images with GitHub OIDC Token

Inputs

Name Description Required Default
bake_build_metadata The JSON build result metadata generated by Bake Yes
registry_user The user used to authenticate to the registry Yes
registry_token The token used to authenticate to the registry Yes
test_registry_suffix The suffix of the testing images No -testing

Note: The JSON build result metadata is provided by bake-action as an output, see bake-action outputs. Alternatively, if you are using docker buildx bake via commandline, you can write your build metadata to a file by using --metadata-file, and then provide the content of that file as input.bake_build_metadata.


Usage

Example usage:

jobs:
  copytoproduction:
    runs-on: ubuntu-latest
    needs:
      - testbuild
    permissions:
      contents: read
      packages: write
      id-token: write
    steps:
      - name: Copy to production
        uses: cloudnative-pg/postgres-containers/.github/actions/copy-images@main
        with:
          bake_build_metadata: "${{ needs.testbuild.outputs.metadata }}"
          registry_user: ${{ github.actor }}
          registry_token: ${{ secrets.GITHUB_TOKEN }}

Example workflow:

jobs:
  # Building and pushing to a testing registry
  testbuild:
    runs-on: ubuntu-latest
    outputs:
      metadata: ${{ steps.build.outputs.metadata }}
    steps:
      ...
      - uses: docker/bake-action@v6
        id: build
        with:
          push: true

  # Here's when you'd want to have one or
  # multiple jobs to scan and test your images
  scan-images:
    ...

  # If the tests passed, we promote the images to the production repo
  copytoproduction:
    runs-on: ubuntu-latest
    needs:
      - testbuild
      - scan-images
    permissions:
      contents: read
      packages: write
      id-token: write
    steps:
      - name: Copy to production
        uses: cloudnative-pg/postgres-containers/.github/actions/copy-images@main
        with:
          bake_build_metadata: "${{ needs.testbuild.outputs.metadata }}"
          registry_user: ${{ github.actor }}
          registry_token: ${{ secrets.GITHUB_TOKEN }}