-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(ci): Moving deploy.yml notifications to teams and aligning it wit…
…h Identity.UW
- Loading branch information
1 parent
488d8ba
commit 9045fd4
Showing
1 changed file
with
171 additions
and
125 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,38 +3,44 @@ name: Deploy the UW Directory | |
on: | ||
workflow_dispatch: | ||
inputs: | ||
target_cluster: | ||
description: cluster. Choose from dev/eval/prod. | ||
default: eval | ||
target-stage: | ||
required: true | ||
rfc: | ||
default: eval | ||
description: > | ||
rfc. The RFC number or link associated with this | ||
deployment. Required when deploying to prod. | ||
(target-stage) | ||
Which cluster you want to deploy to. | ||
Choose from dev, eval, prod. | ||
target-version: | ||
required: false | ||
description: > | ||
(target-version) | ||
The semver you want to deploy. If you do not provide this, the workflow | ||
will promote from the "previous" cluster (dev -> eval, eval -> prod). | ||
associated-record: | ||
required: false | ||
description: > | ||
version. The version to deploy (e.g., '1.2.3'). If not provided, | ||
the most recent release candidate will be used (eval will source from dev, | ||
prod will source from eval). | ||
(associated-record) | ||
Only required if target-stage is prod. | ||
A link to an RFC, Jira, or other document associated | ||
with this change. | ||
env: | ||
GCLOUD_TOKEN: ${{ secrets.GCR_TOKEN }} | ||
SLACK_BOT_TOKEN: ${{ secrets.ACTIONS_SLACK_BOT_TOKEN }} | ||
DRY_RUN: false # ? | ||
STEP_SCRIPTS: ${{ github.workspace }}/.github/steps/deploy | ||
# target_cluster: dev | ||
#TODO Replace with Deploy WebHook - Testing with this for now, while coordinating with the team | ||
TEAMS_INTEGRATIONS_DAILY_WEB_TESTS: ${{ secrets.TEAMS_INTEGRATIONS_DAILY_WEB_TESTS }} | ||
|
||
jobs: | ||
# The `configure` job reconciles the target version (if it wasn't explicitly provided), | ||
# creates a slack notification for the deployment (except for developer instances), | ||
# and updates the slack notification with additional deployment context information. | ||
# The `configure` job reconciles the target version (if it wasn't explicitly provided) | ||
# and prepares the deployment context. Additionally, a Teams notification is sent at the | ||
# start of the deployment in the `deploy` job, and another notification is sent upon | ||
# deployment completion (regardless of success or failure) in the `notify-teams-finish` job. | ||
configure: | ||
env: | ||
target_cluster: ${{ github.event.inputs.target_cluster }} | ||
rfc: ${{ github.event.inputs.rfc }} | ||
target_stage: ${{ github.event.inputs.target-stage }} | ||
target_version: ${{ github.event.inputs.target-version }} | ||
associated_record: ${{ github.event.inputs.associated-record }} | ||
outputs: | ||
target-version: ${{ steps.reconcile-version.outputs.target-version }} | ||
slack-notification-id: ${{ steps.slack.outputs.canvas-id }} #? | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
|
@@ -43,26 +49,28 @@ jobs: | |
# currently validate this record, because endpoints usually require | ||
# authentication. | ||
- name: Verify prod deployment record | ||
if: github.event.inputs.target_cluster == 'prod' | ||
if: github.event.inputs.target-stage == 'prod' | ||
run: | | ||
if [[ -z "${{ env.rfc }}" ]] | ||
if [[ -z "${{ env.associated_record }}" ]] | ||
then | ||
echo "Deployment to prod requires a link to an rfc" | ||
echo "Deployment to prod requires a link to an associated record" | ||
exit 1 | ||
fi | ||
# If the entity who created this deployment did not provide a version, | ||
# we will derive the version from the target stage's "previous" environment. | ||
# This means that deployments to eval will promote from dev, and deployments | ||
# to prod will promote from eval. It's OK if the same version is re-deployed, | ||
# it will have the same net effect of a `kubectl rollout restart`. | ||
# If the entity does provide a semver (target_version), that is used. | ||
|
||
# Output: `target-version`: The reconciled version to deploy. | ||
- name: Reconcile target deployment version | ||
id: reconcile-version | ||
run: | | ||
set -x | ||
if [[ -z "${target_version}" ]] | ||
if [[ -z "${{ env.target_version }}" ]] | ||
then | ||
case "${target_cluster}" in | ||
case "${target_stage}" in | ||
prod) | ||
source_stage=eval | ||
;; | ||
|
@@ -73,73 +81,21 @@ jobs: | |
source_stage=dev | ||
;; | ||
esac | ||
target_version=$(./scripts/get-deployed-version.sh -s ${target_cluster}) | ||
fi | ||
if [[ "${source_stage}" == "poetry" ]] | ||
then | ||
# Get the target version from the poetry configuration | ||
source ./scripts/globals.sh | ||
target_version=$(get_poetry_version) | ||
./scripts/install-build-scripts.sh | ||
target_version=$(./scripts/get-deployed-version.sh -s ${target_stage}) | ||
if [[ "${source_stage}" == "poetry" ]] | ||
then | ||
source ./scripts/globals.sh | ||
target_version=$(get_poetry_version) | ||
else | ||
target_version=$(./scripts/get-deployed-version.sh -s ${source_stage}) | ||
fi | ||
else | ||
target_version=$(./scripts/get-deployed-version.sh -s ${source_stage}) | ||
target_version="${{ env.target_version }}" | ||
fi | ||
echo "target-version=${target_version}" >> $GITHUB_OUTPUT | ||
# For shared instances (dev, eval, prod) we create a slack notification | ||
# so that others can be aware of the change. | ||
# TODO: Eval and prod deployment notifications should go to #iam-uwnetid | ||
# https://github.com/UWIT-IAM/uw-husky-directory/issues/152 | ||
- name: Create notification | ||
id: slack | ||
# Don't send notifications for developer instances | ||
if: env.target_cluster == 'dev' || env.target_cluster == 'eval' || env.target_cluster == 'prod' | ||
uses: UWIT-IAM/actions/[email protected] | ||
env: | ||
target_version: ${{ steps.reconcile-version.outputs.target-version }} | ||
with: | ||
json: > | ||
{ | ||
"description": "Deploy UW Husky Directory v${{ env.target_version }} to ${{ env.target_cluster }}", | ||
"channel": "#iam-bots", | ||
"status": "in progress", | ||
"steps": [ | ||
{ | ||
"stepId": "deploy", | ||
"status": "in progress", | ||
"description": "Create deployment and wait for update" | ||
} | ||
] | ||
} | ||
# This adds a special link for associated records, when they are provided; | ||
# this logic was a little too complex to capture only using github actions contexts, | ||
# so needed to be its own li'l step. | ||
# Output: context - The slack message snippet that provides a link to the audit record. | ||
- if: env.rfc | ||
id: audit | ||
run: | | ||
slack_link="<${{ env.rfc }} | Audit Record>" | ||
echo "context=[${slack_link}]" >> $GITHUB_OUTPUT | ||
# If we have a Slack notification for this change, add a context artifact to it. | ||
# This provides at-a-glance links and details in the slack notification for | ||
# traceability. | ||
# The output winds up reading something like: | ||
# "Deployment workflow for UW Husky Directory app image started by goulter [Audit Record]" where | ||
# all of "deployment workflow" "app image" "goulter" and "Audit Record" are all hyperlinks. | ||
- if: steps.slack.outputs.canvas-id | ||
uses: UWIT-IAM/actions/[email protected] | ||
env: | ||
workflow_link: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} | ||
image_link: https://gcr.io/uwit-mci-iam/husky-directory.app:${{ steps.reconcile-version.outputs.target-version }} | ||
target_version: ${{ steps.version.outputs.target-version }} | ||
actor_link: https://github.com/${{ github.actor }} | ||
with: | ||
canvas-id: ${{ steps.slack.outputs.canvas-id }} | ||
command: add-artifact | ||
description: > | ||
<${{ env.workflow_link }} | Deployment workflow> for UW Husky Directory | ||
<${{ env.image_link }} | app image ${{ env.target_version }}> | ||
started by <${{ env.actor_link }} | ${{ github.actor }}> | ||
${{ steps.audit.outputs.context }} | ||
echo "***target_version=${target_version}" >> $GITHUB_OUTPUT | ||
echo "::set-output name=target-version::${target_version}" | ||
# The deploy job simply runs the deploy script. This script will wait for | ||
# deployments to complete before exiting. If the deployment times out, | ||
|
@@ -155,52 +111,142 @@ jobs: | |
cancel-in-progress: false | ||
env: | ||
target_version: ${{ needs.configure.outputs.target-version }} | ||
target_stage: ${{ github.event.inputs.target_cluster }} | ||
associated_record: ${{ github.event.inputs.rfc }} | ||
slack_notification_id: ${{ needs.configure.outputs.slack-notification-id }} | ||
target_stage: ${{ github.event.inputs.target-stage }} | ||
associated_record: ${{ github.event.inputs.associated-record }} | ||
permissions: | ||
contents: read | ||
id-token: write | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- uses: abatilo/[email protected] | ||
- run: | | ||
sudo apt-get -y install jq | ||
poetry install | ||
- uses: actions/checkout@v3 | ||
- name: Notify Teams of Deployment Start | ||
run: | | ||
associated_record="${{ github.event.inputs.associated-record }}" | ||
target_stage="${{ github.event.inputs.target-stage }}" | ||
# Determine associated record value based on target stage and input | ||
if [ -z "$associated_record" ]; then | ||
if [ "$target_stage" != "prod" ]; then | ||
associated_record="Not required (deployment to $target_stage)" | ||
else | ||
associated_record="Missing (required for production)" | ||
fi | ||
fi | ||
curl -H "Content-Type: application/json" \ | ||
-d '{ | ||
"type": "message", | ||
"attachments": [ | ||
{ | ||
"contentType": "application/vnd.microsoft.card.adaptive", | ||
"content": { | ||
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json", | ||
"type": "AdaptiveCard", | ||
"version": "1.4", | ||
"body": [ | ||
{ | ||
"type": "TextBlock", | ||
"size": "Large", | ||
"weight": "Bolder", | ||
"text": "UW Directory - Deployment Notification" | ||
}, | ||
{ | ||
"type": "TextBlock", | ||
"text": "Deployment to stage **${{ github.event.inputs.target-stage }}** is starting.", | ||
"wrap": true | ||
}, | ||
{ | ||
"type": "FactSet", | ||
"facts": [ | ||
{"title": "Stage:", "value": "${{ github.event.inputs.target-stage }}"}, | ||
{"title": "Version:", "value": "${{ needs.configure.outputs.target-version }}"}, | ||
{"title": "Associated Record:", "value": "'"${associated_record}"'"}, | ||
{"title": "Initiated By:", "value": "${{ github.actor }}"} | ||
] | ||
} | ||
] | ||
} | ||
} | ||
] | ||
}' \ | ||
"${{ env.IDENTITY_UW_DEPLOY_MS_TEAMS_WEBHOOK_URL }}" | ||
- uses: ./.github/actions/configure-docker | ||
with: | ||
project-name: ${{ secrets.IAM_GCR_REPO }} | ||
gcr-token: ${{ secrets.GCR_TOKEN }} | ||
- run: | | ||
gcloud auth activate-service-account --key-file=${GOOGLE_APPLICATION_CREDENTIALS} | ||
./scripts/deploy.sh -g -t ${target_stage} -v ${target_version} -r "${{ github.event.inputs.rfc }}" | ||
./scripts/deploy.sh -g -t ${target_stage} -v ${target_version} -r "${{ associated_record }}" | ||
# probably need to account for -x, --dry-run at some point. lets see how things go. | ||
# This removes extraneous volatile information from the Slack notification, | ||
# leaving only any errors, the final status, and the deployment context artifact. | ||
cleanup: | ||
runs-on: ubuntu-latest | ||
needs: [configure, deploy] | ||
permissions: | ||
contents: read | ||
id-token: write | ||
if: needs.configure.outputs.slack-notification-id | ||
env: | ||
SLACK_CANVAS_ID: ${{ needs.configure.outputs.slack-notification-id }} | ||
deploy_result: ${{ needs.deploy.result == 'success' && 'succeeded' || 'failed' }} | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- uses: ./.github/actions/configure-docker | ||
with: | ||
project-name: ${{ secrets.IAM_GCR_REPO }} | ||
gcr-token: ${{ secrets.GCR_TOKEN }} | ||
- uses: UWIT-IAM/actions/[email protected] | ||
with: | ||
command: update-workflow | ||
step-id: deploy | ||
step-status: ${{ env.deploy_result }} | ||
canvas-id: ${{ needs.configure.outputs.slack-notification-id }} | ||
- uses: UWIT-IAM/actions/[email protected] | ||
with: | ||
workflow-status: ${{ env.deploy_result }} | ||
notify-teams-finish: | ||
runs-on: ubuntu-latest | ||
needs: [ configure, deploy ] | ||
steps: | ||
- name: Notify Teams of Deployment Completion | ||
if: always() # This step runs regardless of success or failure | ||
run: | | ||
deploy_result="${{ needs.deploy.result }}" | ||
deploy_status="Failed" | ||
associated_record="${{ github.event.inputs.associated-record }}" | ||
target_stage="${{ github.event.inputs.target-stage }}" | ||
if [ "$deploy_result" == "success" ]; then | ||
deploy_status="Succeeded" | ||
fi | ||
# Determine associated record value based on target stage and input | ||
if [ -z "$associated_record" ]; then | ||
if [ "$target_stage" != "prod" ]; then | ||
associated_record="Not required (deployment to $target_stage)" | ||
else | ||
associated_record="Missing (required for production)" | ||
fi | ||
fi | ||
curl -H "Content-Type: application/json" \ | ||
-d '{ | ||
"type": "message", | ||
"attachments": [ | ||
{ | ||
"contentType": "application/vnd.microsoft.card.adaptive", | ||
"content": { | ||
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json", | ||
"type": "AdaptiveCard", | ||
"version": "1.4", | ||
"body": [ | ||
{ | ||
"type": "TextBlock", | ||
"size": "Large", | ||
"weight": "Bolder", | ||
"text": "UW Directory - Deployment Notification" | ||
}, | ||
{ | ||
"type": "TextBlock", | ||
"text": "Deployment to stage **${{ github.event.inputs.target-stage }}** has **'"$deploy_status"'**.", | ||
"wrap": true | ||
}, | ||
{ | ||
"type": "FactSet", | ||
"facts": [ | ||
{"title": "Stage:", "value": "${{ github.event.inputs.target-stage }}"}, | ||
{"title": "Version:", "value": "${{ needs.configure.outputs.target-version }}"}, | ||
{"title": "Associated Record:", "value": "'"${associated_record}"'"}, | ||
{"title": "Initiated By:", "value": "${{ github.actor }}"}, | ||
{"title": "Status:", "value": "'"$deploy_status"'"} | ||
] | ||
} | ||
], | ||
"actions": [ | ||
{ | ||
"type": "Action.OpenUrl", | ||
"title": "View Workflow", | ||
"url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" | ||
} | ||
] | ||
} | ||
} | ||
] | ||
}' \ | ||
"${{ env.IDENTITY_UW_DEPLOY_MS_TEAMS_WEBHOOK_URL }}" | ||