1+ name : Release Docker Image
2+
3+ run-name : Release Docker Image ${{ github.event_name == 'workflow_dispatch' && inputs.service || '(auto-deploy)' }}
4+
5+ on :
6+ push :
7+ branches :
8+ - main
9+
10+ workflow_dispatch :
11+ inputs :
12+ version :
13+ description : |
14+ Version (of the form "1.2.3") or Branch (of the form "origin/branch-name").
15+ Leave empty to bump the latest version.
16+ type : string
17+ build_local :
18+ type : boolean
19+ default : false
20+ description : Uses build-cloud by default. If Build Cloud is down, set this to true to build locally.
21+ dry_run :
22+ description : If true, the workflow will not push the image to the registry.
23+ type : boolean
24+ default : false
25+ mirror_ecr :
26+ description : Push release image both to DockerHub and AWS ECR.
27+ default : " false"
28+ aws_role_to_assume_arn :
29+ description : role to assume.
30+ default : arn:aws:iam::710015040892:role/CiHubPlatformTerraform-20230302144600629400000001
31+ aws_region :
32+ description : The AWS region where we will mirror the image in.
33+ default : us-east-1
34+ aws_ecr_repository_name :
35+ description : The ECR repository to mirror image in.
36+
37+ env :
38+ GOPRIVATE : github.com/docker
39+ NAME : dockerhub-mcp
40+
41+ jobs :
42+ release :
43+ name : Release Service
44+ permissions :
45+ pull-requests : write
46+ # This permission is required to update the PR body content
47+ repository-projects : write
48+ # These permissions are needed to interact with GitHub's OIDC Token
49+ # endpoint. We need it in order to make requests to AWS ECR for image
50+ # mirroring.
51+ id-token : write
52+ contents : read
53+ runs-on : ubuntu-latest
54+ # Internally the create-release action attempts to push a commit to
55+ # cloud-manifests in a loop to avoid race-conditions. However, this could
56+ # have the side-effect of making the action hang for ever if we come across
57+ # a scenario that we haven't thought of. This timeout makes sure to fail the
58+ # workflow if that happens.
59+ timeout-minutes : 10
60+ steps :
61+ - name : Setup
62+ uses : docker/actions/setup-go@setup-go/v1
63+ id : setup_go
64+ with :
65+ app_id : ${{ secrets.HUB_PLATFORM_APP_ID }}
66+ app_private_key : ${{ secrets.HUB_PLATFORM_APP_PRIVATE_KEY }}
67+ go_version : ' 1.24'
68+
69+ - name : Checkout
70+ uses : actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
71+ with :
72+ token : ${{ steps.setup_go.outputs.token }}
73+ fetch-depth : 0
74+
75+ - name : Bump Version
76+ id : bump_version
77+ if : github.event_name == 'push' && inputs.version == ''
78+ uses : docker/actions/bump-version@bump-version/v1.1.0
79+ with :
80+ name : ${{ env.NAME }}
81+
82+ - name : Get Latest Version
83+ id : latest_version
84+ if : github.event_name != 'push' && inputs.version == ''
85+ uses : docker/actions/bump-version@bump-version/v1.1.0
86+ with :
87+ name : ${{ env.NAME }}
88+ include_tag : false
89+
90+ - name : Get Release Version
91+ id : release_version
92+ shell : bash
93+ run : |
94+ if [[ '${{ steps.bump_version.outcome }}' == 'success' ]]; then
95+ echo "version=${{ steps.bump_version.outputs.next_version_number }}" >> $GITHUB_OUTPUT
96+ echo "tag=${{ steps.bump_version.outputs.next_version }}" >> $GITHUB_OUTPUT
97+ elif [[ '${{ steps.latest_version.outcome }}' == 'success' ]]; then
98+ echo "version=${{ steps.latest_version.outputs.latest_version_number }}" >> $GITHUB_OUTPUT
99+ elif [[ '${{ inputs.version }}' != '' ]]; then
100+ echo "Using already provided version: ${{ inputs.version }}."
101+ echo "version=${{ inputs.version }}" >> $GITHUB_OUTPUT
102+ else
103+ echo "Unable to compute version for staging environment."
104+ exit 42
105+ fi
106+
107+ - name : Hub Login
108+ uses : docker/login-action@v2
109+ with :
110+ username : dockerbuildbot
111+ password : ${{ secrets.DOCKERBUILDBOT_WRITE_PAT }}
112+
113+ - name : Setup Hydrobuild
114+ uses : docker/setup-buildx-action@v3
115+ if : ${{ ! inputs.build_local }}
116+ with :
117+ version : " lab:latest"
118+ driver : cloud
119+ endpoint : docker/platform-experience
120+ install : true
121+
122+ - name : Check Docker image exists
123+ id : hub_image_exists
124+ shell : bash
125+ run : |
126+ if docker manifest inspect docker/${{ env.NAME }}:${{ steps.latest_version.outputs.latest_version_number }}; then
127+ echo 'exists=true' >> $GITHUB_OUTPUT
128+ else
129+ echo 'exists=false' >> $GITHUB_OUTPUT
130+ fi
131+
132+ - name : Ensure attestations are supported
133+ shell : bash
134+ # docker buildx inspect | grep Driver
135+ # Driver: docker
136+ # indicates that we need to enable containerd so
137+ # we can compute sboms.
138+ run : |
139+ driver=$(docker buildx inspect | grep "Driver:")
140+ if [[ "$driver" == *"docker"* ]]; then
141+ echo "detected driver, needs containerd snapshotter enabled: $driver"
142+ sudo mkdir -p /etc/docker
143+ if [ -f /etc/docker/daemon.json ]; then
144+ cat /etc/docker/daemon.json | jq '. + {"features": {"containerd-snapshotter": true}}' | sudo tee /etc/docker/daemon.json
145+ else
146+ echo '{"features": {"containerd-snapshotter": true}}' | sudo tee /etc/docker/daemon.json
147+ fi
148+ sudo systemctl restart docker
149+ fi
150+
151+ - name : Build and push service image
152+ if : steps.hub_image_exists.outputs.exists == 'false'
153+ uses : docker/build-push-action@v5
154+ with :
155+ context : .
156+ file : Dockerfile
157+ build-args : |
158+ SERVICE_NAME=${{ env.NAME }}
159+ SERVICE_VERSION=${{ steps.release_version.outputs.version }}
160+ push : ${{ inputs.dry_run != 'true' }}
161+ tags : |
162+ docker/${{ env.NAME }}:${{ steps.release_version.outputs.version }}
163+ docker/${{ env.NAME }}:latest
164+ labels : |
165+ org.opencontainers.image.revision=${{ github.event.pull_request.head.sha || github.event.after || github.event.release.tag_name }}
166+ org.opencontainers.image.source=https://github.com/${{ github.repository }}
167+ com.docker.image.source.entrypoint=Dockerfile
168+ provenance : mode=max
169+ sbom : true
170+
171+ - name : Configure AWS Credentials
172+ if : inputs.mirror_ecr == 'true'
173+ uses : aws-actions/configure-aws-credentials@v4
174+ with :
175+ role-session-name : gha-release-service-go-workflow
176+ role-to-assume : ${{ inputs.aws_role_to_assume_arn }}
177+ aws-region : ${{ inputs.aws_region }}
178+
179+ - name : Log in to Amazon ECR
180+ if : inputs.mirror_ecr == 'true'
181+ id : login_ecr
182+ uses : aws-actions/amazon-ecr-login@v2
183+
184+ # # Note: We're disabling this for now so branch images can be overriden
185+ # # on-demand. This is pending revisiting branch-based deployments.
186+ # - name: Check image exists in AWS ECR
187+ # if: inputs.mirror_ecr == 'true'
188+ # id: ecr_image_exists
189+ # shell: bash
190+ # run: |
191+ # if docker manifest inspect ${{ steps.login_ecr.outputs.registry }}/${{ inputs.service_name }}:${{ steps.image_tag.outputs.tag }}; then
192+ # echo 'exists=true' >> $GITHUB_OUTPUT
193+ # else
194+ # echo 'exists=false' >> $GITHUB_OUTPUT
195+ # fi
196+
197+ - name : Vendor modules
198+ # Basically, if the Hub image exists, then we need to make sure to vendor
199+ # for building the ECR image.
200+ if : steps.hub_image_exists.outputs.exists == 'true'
201+ working-directory : ${{ inputs.service_directory }}
202+ shell : bash
203+ run : |
204+ if [[ -f "go.mod" ]]; then
205+ go mod vendor
206+ fi
207+
208+ - name : Build and push Docker image to ECR
209+ if : inputs.mirror_ecr == 'true'
210+ uses : docker/build-push-action@v5
211+ with :
212+ context : .
213+ file : Dockerfile
214+ build-args : |
215+ SERVICE_NAME=${{ env.NAME }}
216+ SERVICE_VERSION=${{ steps.release_version.outputs.version }}
217+ push : ${{ inputs.dry_run != 'true' }}
218+ tags : |
219+ ${{ steps.login_ecr.outputs.registry }}/${{ inputs.aws_ecr_repository_name }}:${{ steps.release_version.outputs.version }}
220+ ${{ steps.login_ecr.outputs.registry }}/${{ inputs.aws_ecr_repository_name }}:latest
221+ labels : |
222+ org.opencontainers.image.revision=${{ github.event.pull_request.head.sha || github.event.after || github.event.release.tag_name }}
223+ org.opencontainers.image.source=https://github.com/${{ github.repository }}
224+ com.docker.image.source.entrypoint=Dockerfile
225+ provenance : mode=max
226+ sbom : true
227+
228+ - name : Log out of Amazon ECR
229+ if : inputs.mirror_ecr == true
230+ shell : bash
231+ run : docker logout ${{ steps.login_ecr.outputs.registry }}
232+
233+
234+ - name : Restore repository to initial HEAD
235+ shell : bash
236+ run : git checkout "${{steps.base_branch.outputs.git_ref}}"
237+
238+ - name : Delete git tag created by this workflow
239+ if : failure() && steps.release_version.outputs.tag != ''
240+ shell : bash
241+ run : |
242+ git push --delete origin ${{ steps.release_version.outputs.tag }}
243+ # TODO: Some other things to do on cleanup:
244+ #
245+ # 1. revert deploy commit in cloud-manifests.
246+ #
247+ # 2. delete image from Hub. Doesn't create friction often; but might cause
248+ # confusion.
249+ #
250+ # 3. delete image from ECR. Doesn't create friction often; but might cause
251+ # confusion.
0 commit comments