diff --git a/.github/workflows/publish-images.yml b/.github/workflows/publish-images.yml new file mode 100644 index 00000000..69e65bf7 --- /dev/null +++ b/.github/workflows/publish-images.yml @@ -0,0 +1,97 @@ +name: Publish Images to VCR + +on: + workflow_dispatch: + push: + branches: [main] + paths: + - images/** + - .github/workflows/publish-images.yml + +permissions: + contents: read + +concurrency: + group: publish-images-vcr + cancel-in-progress: false + +jobs: + prepare: + if: github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.images.outputs.matrix }} + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Generate image matrix + id: images + uses: docker/bake-action/subaction/matrix@v7 + with: + workdir: images + target: default + + publish: + name: Publish ${{ matrix.target }} + if: github.ref == 'refs/heads/main' + needs: prepare + runs-on: ubuntu-latest + timeout-minutes: 60 + env: + STAGING_SUFFIX: -staging-${{ github.run_id }} + permissions: + contents: read + id-token: write + strategy: + fail-fast: false + matrix: + include: ${{ fromJSON(needs.prepare.outputs.matrix) }} + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to VCR with OIDC + uses: vercel/vcr-action/login@v1 + with: + team: ${{ vars.VERCEL_TEAM_ID }} + + - name: Build and push staging tags + id: bake + uses: docker/bake-action@v7 + with: + source: images + targets: ${{ matrix.target }} + vars: | + TAG_SUFFIX=${{ env.STAGING_SUFFIX }} + PUSH=true + + - name: Select a staging tag for this image + id: staging + env: + STAGING_IMAGES: ${{ fromJSON(steps.bake.outputs.metadata)[matrix.target]['image.name'] }} + run: echo "image=${STAGING_IMAGES%%,*}" >> "$GITHUB_OUTPUT" + + - name: Wait for image optimization + id: optimized + uses: vercel/vcr-action/wait-for-optimized-image@v1 + timeout-minutes: 11 + with: + image: ${{ steps.staging.outputs.image }} + timeout-seconds: 600 + + - name: Promote the optimized image to its final tags + env: + STAGING_IMAGES: ${{ fromJSON(steps.bake.outputs.metadata)[matrix.target]['image.name'] }} + DIGEST: ${{ steps.optimized.outputs.digest }} + run: | + IFS=, read -r -a images <<< "$STAGING_IMAGES" + for image in "${images[@]}"; do + docker buildx imagetools create \ + --prefer-index=false \ + --tag "${image%"$STAGING_SUFFIX"}" \ + "${image%:*}@$DIGEST" + done diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 69b89af0..7c15b46b 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -51,6 +51,8 @@ jobs: with: source: images targets: ${{ matrix.target }} + push: false + vars: PUSH=false publish: @@ -101,4 +103,4 @@ jobs: permissions: contents: read steps: - - run: echo "Done" \ No newline at end of file + - run: echo "Done" diff --git a/images/docker-bake.hcl b/images/docker-bake.hcl index 9050463d..de8195fa 100644 --- a/images/docker-bake.hcl +++ b/images/docker-bake.hcl @@ -2,6 +2,14 @@ variable "REGISTRY" { default = "vcr.vercel.com/vercel/sandbox" } +variable "TAG_SUFFIX" { + default = "" +} + +variable "PUSH" { + default = false +} + group "default" { targets = ["runtimes", "vmi"] } @@ -16,15 +24,19 @@ group "vmi" { target "_common" { platforms = ["linux/amd64"] + attest = [ + "type=provenance,disabled=true", + "type=sbom,disabled=true" + ] output = [ - "type=image,oci-mediatypes=true,compression=zstd,compression-level=3,force-compression=true" + "type=image,push=${PUSH},oci-mediatypes=true,compression=zstd,compression-level=3,force-compression=true" ] } target "ubuntu" { inherits = ["_common"] context = "ubuntu" - tags = ["${REGISTRY}/ubuntu:latest"] + tags = ["${REGISTRY}/ubuntu:latest${TAG_SUFFIX}"] } target "node" { @@ -49,8 +61,8 @@ target "node" { inherits = ["_common"] context = "node" tags = [ - "${REGISTRY}/node:${node.major}", - "${REGISTRY}/node:${node.version}", + "${REGISTRY}/node:${node.major}${TAG_SUFFIX}", + "${REGISTRY}/node:${node.version}${TAG_SUFFIX}", ] contexts = { @@ -65,7 +77,7 @@ target "node" { target "python" { inherits = ["_common"] context = "python" - tags = ["${REGISTRY}/python:3.14"] + tags = ["${REGISTRY}/python:3.14${TAG_SUFFIX}"] contexts = { base = "target:ubuntu" @@ -79,7 +91,7 @@ target "python" { target "universal" { inherits = ["_common"] context = "universal" - tags = ["${REGISTRY}/universal:latest"] + tags = ["${REGISTRY}/universal:latest${TAG_SUFFIX}"] contexts = { base = "target:ubuntu" @@ -94,7 +106,7 @@ target "universal" { target "arch" { inherits = ["_common"] context = "arch" - tags = ["${REGISTRY}/arch:latest"] + tags = ["${REGISTRY}/arch:latest${TAG_SUFFIX}"] } target "al-builder-base" { @@ -138,8 +150,8 @@ target "al-node" { context = "al-node" dockerfile = "Dockerfile" tags = [ - "${REGISTRY}/node:al-${node.major}", - "${REGISTRY}/node:al-${node.version}", + "${REGISTRY}/node:al-${node.major}${TAG_SUFFIX}", + "${REGISTRY}/node:al-${node.version}${TAG_SUFFIX}", ] contexts = { @@ -157,7 +169,7 @@ target "al-python" { inherits = ["_common"] context = "al-python" dockerfile = "Dockerfile" - tags = ["${REGISTRY}/python:al-3.13.1"] + tags = ["${REGISTRY}/python:al-3.13.1${TAG_SUFFIX}"] contexts = { builder-base = "target:al-builder-base"