Skip to content

Commit 7096057

Browse files
Trinaahackebrot
andauthored
[DISCO-2169] Delete CircleCI approval task for prod deployment (#250)
* chore: remove unhold-to-deploy-to-prod build step * docs: update release process documentation * docs: add clarification for CD Jenkins trigger * chore: consolidate stage and prod Docker image publication * fix: remove redundant dependency 'docker-image-build' from 'docker-image-publish' in CircleCI config * docs: update release process Co-authored-by: Raphael Pierzina <[email protected]> * chore: add check-for-deployment step * chore: add check for docker-image-publish-locust * fix: spacing in CircleCI config * fix: schema in docker-image-publish-locust * docs: add activity diagram of CircleCI main-workflow --------- Co-authored-by: Raphael Pierzina <[email protected]>
1 parent dcfd608 commit 7096057

File tree

3 files changed

+48
-77
lines changed

3 files changed

+48
-77
lines changed

.circleci/config.yml

Lines changed: 36 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ workflows:
2828
- contract-tests:
2929
<<: *pr-filters
3030
requires:
31-
- checks
3231
- docker-image-build
3332
- docs-build:
3433
<<: *pr-filters
@@ -53,45 +52,27 @@ workflows:
5352
- contract-tests:
5453
<<: *main-filters
5554
requires:
56-
- checks
5755
- docker-image-build
5856
- docs-build:
5957
<<: *main-filters
6058
- docs-publish-github-pages:
6159
<<: *main-filters
6260
requires:
6361
- docs-build
64-
- docker-image-publish-stage:
62+
- check-for-deployment:
6563
<<: *main-filters
6664
requires:
6765
- checks
68-
- unit-tests
69-
- integration-tests
7066
- test-coverage-check
7167
- contract-tests
72-
- docker-image-build
73-
- docker-image-publish-merino-locust:
68+
- docker-image-publish-locust:
7469
<<: *main-filters
7570
requires:
76-
- docker-image-publish-stage
77-
# The following job will require manual approval in the CircleCI web application.
78-
# Once provided, and when all the requirements are fullfilled (e.g. tests)
79-
- unhold-to-deploy-to-prod:
71+
- check-for-deployment
72+
- docker-image-publish:
8073
<<: *main-filters
81-
type: approval
8274
requires:
83-
- checks
84-
- unit-tests
85-
- integration-tests
86-
- test-coverage-check
87-
- contract-tests
88-
- docker-image-build
89-
# On approval of the `unhold-to-deploy-to-prod` job, any successive job that requires it
90-
# will run. In this case, it's manually triggering deployment to production.
91-
- docker-image-publish-prod:
92-
<<: *main-filters
93-
requires:
94-
- unhold-to-deploy-to-prod
75+
- docker-image-publish-locust
9576

9677
jobs:
9778
checks:
@@ -192,12 +173,19 @@ jobs:
192173
command: |
193174
sudo chown 1000:1000 tests/contract/kinto-attachments
194175
make run-contract-tests
195-
docker-image-publish-stage:
176+
check-for-deployment:
196177
docker:
197178
- image: cimg/base:2022.08
198179
steps:
199180
- checkout
200181
- skip-if-do-not-deploy
182+
docker-image-publish:
183+
# Pushing a new production Docker image to the Docker Hub registry triggers a
184+
# webhook that starts the Jenkins deployment workflow
185+
docker:
186+
- image: cimg/base:2022.08
187+
steps:
188+
- checkout
201189
- attach_workspace:
202190
at: /tmp/workspace
203191
- setup_remote_docker
@@ -206,33 +194,48 @@ jobs:
206194
command: docker load -i /tmp/workspace/merinopy.tar.gz
207195
- dockerhub-login
208196
- run:
209-
name: Push to Docker Hub # Load tests are triggered though [load test: (abort|warn)] label.
197+
name: Push to Docker Hub
198+
# The commit tag signals deployment and load test instructions to Jenkins by
199+
# modifying the Docker image tag name. The convention looks as follows:
200+
#^(?P<environment>stage|prod)(?:-(?P<task>\w+)-(?P<onfailure>warn|abort))?-(?P<commit>[a-z0-9]+)$
210201
command: |
211202
if [ "${CIRCLE_BRANCH}" == "main" ]; then
203+
PROD_DOCKER_TAG="prod-${CIRCLE_SHA1}"
212204
if git log -1 "$CIRCLE_SHA1" | grep -q '\[load test: warn\]'; then
213205
echo "Load test requested. Slack warning will be output if test fails and deployment workflow for prod will proceed."
214-
DOCKER_TAG="stage-loadtest-warn-${CIRCLE_SHA1}"
206+
STAGE_DOCKER_TAG="stage-loadtest-warn-${CIRCLE_SHA1}"
215207
elif git log -1 "$CIRCLE_SHA1" | grep -q '\[load test: abort\]'; then
216208
echo "Load test requested. Deployment workflow for prod will abort if load test fails."
217-
DOCKER_TAG="stage-loadtest-abort-${CIRCLE_SHA1}"
209+
STAGE_DOCKER_TAG="stage-loadtest-abort-${CIRCLE_SHA1}"
218210
else
219-
DOCKER_TAG="stage-${CIRCLE_SHA1}"
211+
STAGE_DOCKER_TAG="stage-${CIRCLE_SHA1}"
220212
fi
221213
fi
222214
223215
if [ -n "${DOCKER_TAG}" ]; then
224-
echo ${DOCKERHUB_REPO}:${DOCKER_TAG}
225-
docker tag app:build ${DOCKERHUB_REPO}:${DOCKER_TAG}
216+
echo ${DOCKERHUB_REPO}:${STAGE_DOCKER_TAG} ${DOCKERHUB_REPO}:${PROD_DOCKER_TAG}
217+
docker tag app:build ${DOCKERHUB_REPO}:${STAGE_DOCKER_TAG}
218+
docker tag app:build ${DOCKERHUB_REPO}:${PROD_DOCKER_TAG}
219+
docker tag app:build ${DOCKERHUB_REPO}:latest
226220
docker images
227-
docker push "${DOCKERHUB_REPO}:${DOCKER_TAG}"
221+
docker push "${DOCKERHUB_REPO}:${STAGE_DOCKER_TAG}"
222+
docker push "${DOCKERHUB_REPO}:${PROD_DOCKER_TAG}"
223+
docker push "${DOCKERHUB_REPO}:latest"
228224
else
229225
echo "Not pushing to dockerhub for tag=${CIRCLE_TAG} branch=${CIRCLE_BRANCH}"
230226
fi
231-
docker-image-publish-merino-locust:
227+
docker-image-publish-locust:
232228
docker:
233229
- image: cimg/base:2022.08
234230
steps:
235231
- checkout
232+
- run:
233+
name: Check for load test directive
234+
command: |
235+
if ! git log -1 "$CIRCLE_SHA1" | grep -q '\[load test: abort\|warn\]'; then
236+
echo "Skipping remaining steps in this job: load test not required."
237+
circleci-agent step halt
238+
fi
236239
- setup_remote_docker:
237240
docker_layer_caching: true
238241
- run:
@@ -256,37 +259,6 @@ jobs:
256259
else
257260
echo "Not pushing to dockerhub for tag=${CIRCLE_TAG} branch=${CIRCLE_BRANCH}"
258261
fi
259-
docker-image-publish-prod:
260-
docker:
261-
- image: cimg/base:2022.08
262-
steps:
263-
- checkout
264-
- skip-if-do-not-deploy
265-
- attach_workspace:
266-
at: /tmp/workspace
267-
- setup_remote_docker
268-
- run:
269-
name: Load Docker image from workspace
270-
command: docker load -i /tmp/workspace/merinopy.tar.gz
271-
- dockerhub-login
272-
- run:
273-
name: Push to Docker Hub (prod)
274-
# Using a different tag `prod-{CIRCLE_SHA1}` for production deployments
275-
command: |
276-
if [ "${CIRCLE_BRANCH}" == "main" ]; then
277-
DOCKER_TAG="prod-${CIRCLE_SHA1}"
278-
fi
279-
280-
if [ -n "${DOCKER_TAG}" ]; then
281-
echo ${DOCKERHUB_REPO}:${DOCKER_TAG}
282-
docker tag app:build ${DOCKERHUB_REPO}:${DOCKER_TAG}
283-
docker tag app:build ${DOCKERHUB_REPO}:latest
284-
docker images
285-
docker push "${DOCKERHUB_REPO}:${DOCKER_TAG}"
286-
docker push "${DOCKERHUB_REPO}:latest"
287-
else
288-
echo "Not pushing to dockerhub for tag=${CIRCLE_TAG} branch=${CIRCLE_BRANCH}"
289-
fi
290262
docs-build:
291263
docker:
292264
- image: cimg/rust:1.64

docs/dev/circleci_main_workflow.jpg

298 KB
Loading

docs/dev/release-process.md

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
# The Release Process
22

3-
This project currently follows a [Continuous Delivery][continuous_delivery] process, but it's gradually moving toward [Continuous Deployment][continuous_deployment].
3+
This project currently follows a [Continuous Deployment][continuous_deployment] process.
44

5-
[continuous_delivery]: https://en.wikipedia.org/wiki/Continuous_delivery
65
[continuous_deployment]: https://en.wikipedia.org/wiki/Continuous_deployment
76

8-
Whenever a commit is pushed to this repository's `main` branch, the deployment pipeline kicks in, deploying the changeset to the [`stage` environment](../firefox.md#stage).
7+
Whenever a commit is pushed to this repository's `main` branch, a CircleCI workflow is triggered which performs code checks and runs automated tests. The workflow additionally builds a new Docker image of the service and pushes that Docker image to the Docker Hub registry (this requires all previous jobs to pass).
8+
9+
Pushing a new Docker image to the Docker Hub registry triggers a webhook that starts the Jenkins deployment pipeline (the Docker image tag determines the target environment). The deployment pipeline first deploys to the [`stage` environment](../firefox.md#stage) and subsequently to the [`production` environment](../firefox.md#production).
10+
11+
![Activity diagram of CircleCI main-workflow][activity_circleci_main_workflow]
12+
913
After the deployment is complete, accessing the [`__version__` endpoint][stage_version] will show the commit hash of the deployed version, which will eventually match to the one of the latest commit on the `main` branch (a node with an older version might still serve the request before it is shut down).
1014

1115
[stage_version]: https://stage.merino.nonprod.cloudops.mozgcp.net/__version__
@@ -37,18 +41,12 @@ Load testing can be run locally or as a part of the deployment process. Local ex
3741
Abort will prevent deployment should the load testing fail while warn will simply warn via Slack and continue deployment. For detailed specifics on load testing and this convention, please see the relevant documentation: [load-testing-docs]: /tests/load/README.md].
3842

3943
## Releasing to production
40-
Developers with write access to the Merino repository can initiate a deployment to production after a Pull-Request on the Merino GitHub repository is merged to the `main` branch.
44+
Developers with write access to the Merino repository will initiate a deployment to production when a Pull-Request on the Merino GitHub repository is merged to the `main` branch.
45+
Developers **must** monitor the [Merino Application & Infrastructure][merino_app_info] dashboard for any anomaly, for example significant changes in HTTP response codes, increase in latency, cpu/memory usage (most things under the infrastructure heading).
46+
4147
While any developer with write access can trigger the deployment to production, the _expectation_ is that individual(s) who authored and merged the Pull-Request should do so, as they are the ones most familiar with their changes and who can tell, by looking at the data, if anything looks anomalous.
4248
In general authors should feel _responsible_ for the changes they make and shepherd these changes through to deployment.
4349

44-
Releasing to production can be done by:
45-
46-
1. opening the [CircleCI dashboard][circleci_dashboard];
47-
2. looking up the pipeline named `merino <PR NUMBER>` running in the `main-workflow`; this pipeline should either be in a running status (if the required test jobs are still running) or in the "on hold" status, with the `unhold-to-deploy-to-prod` being held;
48-
3. once in the "on hold" status, with all the other jobs successfully completed, clicking on the "thumbs up" action on the `unhold-to-deploy-to-prod` job row will approve it and trigger the deployment, unblocking the `deploy-to-prod` job;
49-
4. developers **must** monitor the [Merino Application & Infrastructure][merino_app_info] dashboard for any anomaly, for example significant changes in HTTP response codes, increase in latency, cpu/memory usage (most things under the infrastructure heading).
50-
51-
[circleci_dashboard]: https://app.circleci.com/pipelines/github/mozilla-services/merino-py?branch=main&filter=all
5250
[merino_app_info]: https://earthangel-b40313e5.influxcloud.net/d/rQAfYKIVk/wip-merino-py-application-and-infrastructure?orgId=1&from=now-24h&to=now&var-environment=prodpy&refresh=1m
5351

5452
## What to do if production breaks?
@@ -64,4 +62,5 @@ don't panic and follow the instructions below:
6462

6563
[incident_docs]: https://mozilla-hub.atlassian.net/wiki/spaces/MIR/overview
6664
[contributing]: ../../CONTRIBUTING.md
67-
[load-testing-docs]: /tests/load/README.md
65+
[load-testing-docs]: /tests/load/README.md
66+
[activity_circleci_main_workflow]: ./circleci_main_workflow.jpg

0 commit comments

Comments
 (0)