From 4d1f7e935a614cc0445a680c752f3d1bfacd38a0 Mon Sep 17 00:00:00 2001 From: Eric Maydeck <126706864+emaydeck-mozilla@users.noreply.github.com> Date: Wed, 28 Aug 2024 12:19:06 -0600 Subject: [PATCH] feat: use GHA to build and push images to GAR (#750) This creates a GitHub Actions workflow that builds and pushes Docker images to Google Artifact Registry (GAR). This can either be triggered in either of the following ways: - Automatically through successful Circle CI tests when a new tag is created - Manually as a workflow_dispatch action This PR does not break or change the existing CircleCI workflow that builds Docker images and pushes them to Docker Hub. Once we know that this GHA workflow is behaving as expected, we can remove those steps from the CircleCI workflow and rename that to something else (ie. "tests" instead of "build-test-deploy"). Unfortunately, it seems GitHub won't let me test the new workflow until it's present in `master`. Once it's there, I can test/refine more as needed from a branch. This replaces https://github.com/mozilla-services/autopush-rs/pull/746. --- .github/workflows/build-and-push-image.yml | 84 ++++++++++++++++++++++ .github/workflows/docker.yml | 65 +++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 .github/workflows/build-and-push-image.yml create mode 100644 .github/workflows/docker.yml diff --git a/.github/workflows/build-and-push-image.yml b/.github/workflows/build-and-push-image.yml new file mode 100644 index 000000000..96e61249b --- /dev/null +++ b/.github/workflows/build-and-push-image.yml @@ -0,0 +1,84 @@ +name: Build and push image to GAR + +run-name: Build and push image "${{ inputs.image }}:${{ inputs.tag }}" to GAR + +on: + workflow_call: + inputs: + binary: + required: true + type: string + crate: + required: true + type: string + gar_location: + required: true + type: string + default: us + gar_repository: + required: true + type: string + default: autopush-prod + gcp_project_id: + required: true + type: string + default: moz-fx-autopush-prod + image: + required: true + type: string + tag: + required: true + type: string + +jobs: + build-and-push: + runs-on: ubuntu-latest + environment: build + permissions: + contents: read + id-token: write + env: + BINARY: ${{ inputs.binary }} + CRATE: ${{ inputs.crate }} + GAR_LOCATION: ${{ inputs.gar_location }} + GAR_REPOSITORY: ${{ inputs.gar_repository }} + GCP_PROJECT_ID: ${{ inputs.gcp_project_id }} + IMAGE: ${{ inputs.image }} + TAG: ${{ inputs.tag }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ env.TAG }} + - run: | + printf '{"commit":"%s","version":"%s","source":"https://github.com/%s","build":"%s/%s/actions/runs/%s"}\n' \ + "${GITHUB_SHA}" \ + "${GITHUB_REF_NAME}" \ + "${GITHUB_REPOSITORY}" \ + "${GITHUB_SERVER_URL}" \ + "${GITHUB_REPOSITORY}" \ + "${GITHUB_RUN_ID}" > version.json + - id: gcp-auth + uses: google-github-actions/auth@v2 + with: + token_format: 'access_token' + service_account: artifact-writer@${{ env.GCP_PROJECT_ID }}.iam.gserviceaccount.com + workload_identity_provider: ${{ vars.GCPV2_GITHUB_WORKLOAD_IDENTITY_PROVIDER }} + - uses: docker/login-action@v3 + with: + registry: ${{ env.GAR_LOCATION }}-docker.pkg.dev + username: oauth2accesstoken + password: ${{ steps.gcp-auth.outputs.access_token }} + - id: build-and-push + uses: docker/build-push-action@v6 + with: + context: . + file: Dockerfile + tags: + - ${{ env.GAR_LOCATION }}-docker.pkg.dev/${{ env.GCP_PROJECT_ID }}/${{ env.GAR_REPOSITORY }}/${{ env.IMAGE }}:latest + - ${{ env.GAR_LOCATION }}-docker.pkg.dev/${{ env.GCP_PROJECT_ID }}/${{ env.GAR_REPOSITORY }}/${{ env.IMAGE }}:${{ env.TAG }} + push: true + cache-from: type=gha + cache-to: type=gha,mode=max + build-args: | + CRATE=${{ env.CRATE }} + BINARY=${{ env.BINARY }} diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 000000000..383a1af31 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,65 @@ +name: Build and deploy Docker images to GAR +on: + check_run: + types: [completed] + workflow_dispatch: + inputs: + git_tag: + type: string + required: true + +jobs: + determine-tag: + name: Determine tag to build + if: | + github.event_name == "workflow_dispatch" || + (github.event_name == "check_run" && \ + github.event.check_run.name == "build-test-deploy" && \ + github.event.check_run.conclusion == "success" && \ + github.ref_type == "tag") + runs-on: ubuntu-latest + permissions: {} + outputs: + TAG: ${{ steps.determine.outputs.tag }} + steps: + - id: determine + run: | + # workflow_dispatch + if [[ "${{ github.event.inputs.git_tag }}" != "" ]]; then + echo "tag=${{ github.event.inputs.git_tag }}" >> $GITHUB_OUTPUT + # successful check_run from tag + elif [[ "${{ github.ref }}" != "" ]] && \ + [[ "${{ github.ref_type }}" == "tag" ]]; then + echo "tag=$(cut -d \/ -f3 <(echo '${{ github.ref }}'))" >> $GITHUB_OUTPUT + else + echo "Cannot determine tag" + exit 1 + fi + + autoconnect: + name: "Autoconnect: Build and push to GAR" + needs: [tag] + permissions: + contents: read + id-token: write + uses: ./.github/workflows/build-and-push-image.yml + secrets: inherit + with: + binary: autoconnect + crate: autoconnect + image: autoconnect + tag: ${{ needs.tag.outputs.TAG }} + + autoendpoint: + name: "Autoendpoint: Build and push to GAR" + needs: [tag] + permissions: + contents: read + id-token: write + uses: ./.github/workflows/build-and-push-image.yml + secrets: inherit + with: + binary: autoendpoint + crate: autoendpoint + image: autoendpoint + tag: ${{ needs.tag.outputs.TAG }}