Description
Contributing guidelines
- I've read the contributing guidelines and wholeheartedly agree
I've found a bug, and:
- The documentation does not mention anything about my problem
- There are no open or closed issues that are related to my problem
Description
I have a workflow that runs on PRs that can perform a push if the PR is from the same repository, but will otherwise just build.
I've observed that, even when push:
is false in this workflow, my run is attempting to push.
A test PR: WorldconVotingSystems/seattle-2025#35
Expected behaviour
I expect no push attempt to occur when CAN_PUSH_IMAGES is not true
(note: I actually expect this workflow to fail after the build step for related reasons, but my problem is that I'm trying to get to those and debug them, but it's failing early at a point that doesn't make sense to me)
Actual behaviour
Specifically, you can see that push: false
is set at the top, however the build is failing:
#27 ERROR: failed to push ghcr.io/worldconvotingsystems/seattle-2025: failed to authorize: failed to fetch anonymous token: unexpected status from GET request to https://ghcr.io/token?scope=repository%3Aworldconvotingsystems%2Fseattle-2025%3Apull%2Cpush&service=ghcr.io: 403 Forbidden
Repository URL
https://github.com/WorldconVotingSystems/seattle-2025/
Workflow run URL
https://github.com/WorldconVotingSystems/seattle-2025/actions/runs/14010277251/job/39229206566?pr=35
YAML workflow
name: Docker
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
on:
schedule:
- cron: "41 14 * * *"
push:
branches: ["main"]
# Publish semver tags as releases.
tags: ["v*.*.*"]
pull_request:
branches: ["main"]
env:
REGISTRY: ghcr.io
jobs:
prepare:
permissions: {}
runs-on: ubuntu-latest
steps:
- name: set the build step environment
run: |
# what even the fuck is this.
# here purely because of https://github.com/orgs/community/discussions/25768
registry_image=$REGISTRY/${{ github.repository }}
echo REGISTRY_IMAGE_LC="${registry_image,,}" >> "$GITHUB_ENV"
# Default to allowing push
echo "CAN_PUSH_IMAGES=true" >> "$GITHUB_ENV"
- name: Check for push image permissions
# if this is a pull request from another repository, then disable pushing
if: github.event.pull_request.head.repo.full_name != github.repository && github.event_name == 'pull_request'
run: |
echo "This is a pull request from an external repository. Disabling image push."
echo "CAN_PUSH_IMAGES=false" >> "$GITHUB_ENV"
- name: persist the push instruction
id: persist
run: |
echo "can_push_images=$CAN_PUSH_IMAGES" >> "$GITHUB_OUTPUT"
echo "registry_image=$REGISTRY_IMAGE_LC" >> "$GITHUB_OUTPUT"
outputs:
can_push_images: ${{ steps.persist.outputs.can_push_images }}
registry_image: ${{ steps.persist.outputs.registry_image }}
build:
runs-on: ubuntu-latest
needs: prepare
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
# we don't run this on ARM, no sense in building for it
# - linux/arm64
permissions:
contents: read
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
id-token: write
env:
CAN_PUSH_IMAGES: ${{ needs.prepare.outputs.can_push_images }}
REGISTRY_IMAGE: ${{ needs.prepare.outputs.registry_image }}
steps:
- name: Set up the platform
run: |
# set the platform pair for later
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> "$GITHUB_ENV"
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
# Set up BuildKit Docker container builder to be able to build
# multi-platform images and export cache
# https://github.com/docker/setup-buildx-action
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
if: env.CAN_PUSH_IMAGES == 'true'
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
with:
images: ${{ env.REGISTRY_IMAGE }}
tags: |
type=ref,event=branch
type=ref,event=tag
type=ref,event=pr
type=semver,pattern={{version}}
type=sha
- name: Build and push by digest
id: build
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0
with:
context: .
push: ${{ env.CAN_PUSH_IMAGES == 'true' }}
platforms: ${{ matrix.platform }}
labels: ${{ steps.meta.outputs.labels }}
outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
runs-on: ubuntu-latest
permissions:
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
id-token: write
needs:
- prepare
- build
env:
CAN_PUSH_IMAGES: ${{ needs.prepare.outputs.can_push_images }}
REGISTRY_IMAGE: ${{ needs.prepare.outputs.registry_image }}
steps:
- name: Download digests
uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4.1.9
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
- name: Login to Docker Hub
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
- name: Docker meta
id: meta
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
with:
images: ${{ env.REGISTRY_IMAGE }}
- name: Create manifest list and push
working-directory: /tmp/digests
if: ${{ env.CAN_PUSH_IMAGES }}
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)
- name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }}
outputs:
version: ${{ steps.meta.outputs.version }}
validate:
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
env:
NOMNOM_VERSION: ${{ needs.merge.outputs.version }}
needs:
- merge
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: copy the environment
run: |
cp deploy/staging/.env.template deploy/staging/.env
- name: pull the staging images
run: |
docker compose -f deploy/staging/compose.yml -p staging pull
- name: start the staging environment
run: |
docker compose -f deploy/staging/compose.yml -p staging up --wait
- name: attempt to read the home page from the website
run: |
curl -s -o /dev/null \
-H Host:nomnom-staging.seattlein2025.org \
-w "%{http_code}" \
http://localhost:8000/ >> /tmp/status_code
- name: check the status code
run: |
status_code=$(cat /tmp/status_code)
if [ "$status_code" != "200" ]; then
echo "The status code was not 200. It was $status_code."
exit 1
fi
notify:
runs-on: ubuntu-latest
needs:
- validate
- merge
steps:
- uses: umahmood/pushover-actions@5da31193f672e7418804bdb51836bdf20f393c8f # v1.1.0
env:
PUSHOVER_TOKEN: ${{ secrets.PUSHOVER_API_KEY }}
PUSHOVER_USER: ${{ secrets.PUSHOVER_USER_KEY }}
with:
status: ${{ job.status }}
title: Seattle Image Updates
message: |-
The Seattle docker image has been updated: ${{ needs.merge.outputs.version }}
Workflow logs
BuildKit logs
Additional info
No response