diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index c734ecb..92b3ec0 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -20,11 +20,28 @@ jobs: - name: Clone repository uses: actions/checkout@v4 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Setup Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Docker Metadata - id: meta + - name: Docker Metadata for Google Artifact Registry build + id: metagar + uses: docker/metadata-action@v5 + with: + flavor: + # don't automatically tag with `latest`; we do this conditionally in the `tags` section + latest=false + images: | + ${{ vars.GAR_LOCATION }}-docker.pkg.dev/${{ vars.GCP_PROJECT_ID }}/${{ vars.GAR_REPOSITORY}}/autograph-edge + tags: | + type=sha,format=long,enable=${{ github.event_name == 'push' }} + type=raw,value=latest,enable=${{ github.event_name == 'push' }} + type=semver,pattern={{raw}},enable=${{ github.event_name == 'release' }} + + - name: Docker Metadata for Docker Hub + id: metahub uses: docker/metadata-action@v5 with: flavor: @@ -32,14 +49,15 @@ jobs: latest=false images: | ${{ vars.DOCKERHUB_REPO }} - ${{ vars.GCP_PROJECT_ID && format('{0}-docker.pkg.dev/{1}/{2}/autograph-edge', vars.GAR_LOCATION, vars.GCP_PROJECT_ID, vars.GAR_REPOSITORY) }} tags: | - type=semver,pattern={{raw}} + type=semver,pattern={{raw}},enable=${{ github.event_name == 'release' }} type=raw,value=latest,enable=${{ github.event_name == 'push' }} - type=sha,format=long,enable=${{ github.event_name == 'push' }} + + - name: Generate version.json + shell: bash + run: make generate - id: gcp-auth - if: ${{ vars.GCP_PROJECT_ID }} uses: google-github-actions/auth@v2 with: token_format: "access_token" @@ -47,7 +65,6 @@ jobs: workload_identity_provider: ${{ vars.GCPV2_GITHUB_WORKLOAD_IDENTITY_PROVIDER }} - name: Login to Google Artifact Registry - if: ${{ vars.GCP_PROJECT_ID }} uses: docker/login-action@v3 with: registry: ${{ vars.GAR_LOCATION }}-docker.pkg.dev @@ -55,27 +72,23 @@ jobs: password: ${{ steps.gcp-auth.outputs.access_token }} - name: Login to Dockerhub - if: ${{ vars.DOCKERHUB_REPO }} uses: docker/login-action@v3 with: username: ${{ vars.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} - - name: Generate version.json - shell: bash - run: ./version.sh | tee version.json - - - name: Build and push + - name: Build and push to Google Artifact Registry for each commit on main # On pushes to `main`, we build and push a new image, so we can simply # use the `docker/build-push-action` action. if: ${{ github.event_name == 'push' }} uses: docker/build-push-action@v6 with: - push: ${{ github.event_name == 'push' }} + push: true sbom: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} + tags: ${{ steps.metagar.outputs.tags }} + labels: ${{ steps.metagar.outputs.labels }} context: . + platforms: linux/amd64,linux/arm64 # copypasta from https://github.com/imjasonh/setup-crane/blob/main/action.yml - name: Set up crane @@ -95,17 +108,42 @@ jobs: echo "${tmp}" >> $GITHUB_PATH echo "${{ github.token }}" | crane auth login ghcr.io --username "dummy" --password-stdin - - name: Tag and push - # For releases, we specifically do _not_ want to rebuild, just tag the - # existing image and push. There's no officially maintained action for - # this use case, but it's trivial enough to do ourselves. + - name: Copy from Google Artifact Registory to Docker Hub + # We want to make sure that Docker Hub's latest tag is always up to + # date. For releases, we specifically do _not_ want to rebuild and + # instead only tag the existing image and push. There's no officially + # maintained action for this use case, but it's trivial enough to do + # ourselves. On builds on each commit of main ("push" events), the + # expectation is that only `latest` will be pushed to Docker Hub. For + # releases, the expectation is only the semver tag will be pushed. + env: + # Tags come in the form of a fully qualified image name and tag + # separated by newlines. + TAGS: | + ${{ steps.metahub.outputs.tags }} + # This github.sha won't work if the tag is an annotated tag, but we'll + # hit that when we hit that. (We'll want to use github.object.sha but + # only in tags, not in pushes) + SRC: ${{ vars.GAR_LOCATION }}-docker.pkg.dev/${{ vars.GCP_PROJECT_ID }}/${{ vars.GAR_REPOSITORY}}/autograph-edge:sha-${{ github.sha }} + run: | + crane digest $SRC + crane manifest $SRC + for tag in $TAGS; do + crane copy $SRC $tag + done + + - name: Copy image from Google Artifact Registory to Google Artifact Registory as semver tag + # This is conditional because we only can do this correctly (that is, + # with the correct TAGS from the metagar step) and only need to do it at + # all on release. if: ${{ github.event_name == 'release' }} env: - # Tags come in the form of a fully qualified image name and tag, eg: - # mozilla/autograph:1.1.8 - # us-west2-docker.pkg.dev/autograph-proj/autograph-repo/autograph:1.1.8 - TAGS: ${{ steps.meta.outputs.tags }} - SRC: ${{ vars.DOCKERHUB_REPO}}:sha-${{ github.sha }} + TAGS: | + ${{ steps.metagar.outputs.tags }} + # This github.sha won't work if the tag is an annotated tag, but we'll + # hit that when we hit that. (We'll want to use github.object.sha but + # only in tags, not in pushes) + SRC: ${{ vars.GAR_LOCATION }}-docker.pkg.dev/${{ vars.GCP_PROJECT_ID }}/${{ vars.GAR_REPOSITORY}}/autograph-edge:sha-${{ github.sha }} run: | crane digest $SRC crane manifest $SRC