Skip to content

Commit

Permalink
fix(ci): Moving deploy.yml notifications to teams and aligning it wit…
Browse files Browse the repository at this point in the history
…h Identity.UW
  • Loading branch information
soufianerafik committed Jan 17, 2025
1 parent 488d8ba commit 9045fd4
Showing 1 changed file with 171 additions and 125 deletions.
296 changes: 171 additions & 125 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
;;
Expand All @@ -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,
Expand All @@ -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 }}"

0 comments on commit 9045fd4

Please sign in to comment.