From 14b87304468e2563b38b09dc6e1e086d24d0e534 Mon Sep 17 00:00:00 2001 From: RMcVelia Date: Fri, 1 Nov 2024 15:51:08 +0000 Subject: [PATCH 1/2] Add slack failure to build-docker-image --- build-docker-image/README.md | 1 + build-docker-image/action.yml | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/build-docker-image/README.md b/build-docker-image/README.md index f8b3ccb..e82215e 100644 --- a/build-docker-image/README.md +++ b/build-docker-image/README.md @@ -30,6 +30,7 @@ A service that uses this action with reuse-cache = true, should also have a cach - `target`: The target stage to build of a multi-stage build - `docker-repository`: Repository name in the container registry. e.g. ghcr.io/dfe-digital/register-trainee-teachers. Defaults to current Github repository name. - `max-cache`: Set to true to use maximum cache level when reuse-cache is set. Defaults to minimum (false) +- `slack-webhook`: A slack webhook to send a slack message to the service tech channel (Optional) ## Outputs - `tag`: Tag uniquely generated for this build (Currently long commit SHA) diff --git a/build-docker-image/action.yml b/build-docker-image/action.yml index b6adacd..124f910 100644 --- a/build-docker-image/action.yml +++ b/build-docker-image/action.yml @@ -28,6 +28,8 @@ inputs: default: false type: boolean required: false + slack-webhook: + required: false outputs: tag: @@ -181,3 +183,15 @@ runs: - name: Push ${{ env.DOCKER_REPOSITORY }}:${{ env.IMAGE_TAG }} image to registry shell: bash run: docker image push --all-tags ${{ env.DOCKER_REPOSITORY }} + + - name: Notify slack channel on job failure + uses: rtCamp/action-slack-notify@master + if: ${{ failure() && github.ref == 'refs/heads/main' && inputs.slack-webhook != '' }} + with: + SLACK_USERNAME: CI Deployment + SLACK_COLOR: failure + SLACK_ICON_EMOJI: ':github-logo:' + SLACK_TITLE: 'Build failure' + SLACK_MESSAGE: ':alert: Build failure on commit ${{env.IMAGE_TAG}} :sadparrot:' + SLACK_WEBHOOK: ${{ inputs.slack-webhook }} + SLACK_FOOTER: Sent from build-docker-image From 7088d4d02579921b44ac061157c7e9449cdfa7b5 Mon Sep 17 00:00:00 2001 From: RMcVelia Date: Fri, 1 Nov 2024 15:51:40 +0000 Subject: [PATCH 2/2] Add deploy-to-aks action --- build-docker-image/README.md | 2 +- deploy-to-aks/README.md | 40 +++++++++ deploy-to-aks/action.yml | 154 +++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 deploy-to-aks/README.md create mode 100644 deploy-to-aks/action.yml diff --git a/build-docker-image/README.md b/build-docker-image/README.md index e82215e..38c1a21 100644 --- a/build-docker-image/README.md +++ b/build-docker-image/README.md @@ -30,7 +30,7 @@ A service that uses this action with reuse-cache = true, should also have a cach - `target`: The target stage to build of a multi-stage build - `docker-repository`: Repository name in the container registry. e.g. ghcr.io/dfe-digital/register-trainee-teachers. Defaults to current Github repository name. - `max-cache`: Set to true to use maximum cache level when reuse-cache is set. Defaults to minimum (false) -- `slack-webhook`: A slack webhook to send a slack message to the service tech channel (Optional) +- `slack-webhook`: A slack webhook to send a slack message to the service tech channel. See https://technical-guidance.education.gov.uk/infrastructure/monitoring/slack/#content (Optional) ## Outputs - `tag`: Tag uniquely generated for this build (Currently long commit SHA) diff --git a/deploy-to-aks/README.md b/deploy-to-aks/README.md new file mode 100644 index 0000000..2fd7a6a --- /dev/null +++ b/deploy-to-aks/README.md @@ -0,0 +1,40 @@ +# Deploy to AKS + +Deploy a docker image by sha to a specific service environment. +Optionally after deployment +- run a seed command for review apps + - if enabled, it will run 'make review seed-review-app' so this must exist in the Makefile +- run a smoktest after deployment + +If using Google Cloud then GCP_PROJECT_ID abd GCP_WIP variables must be set in the service Makefile. + +## Inputs +- `azure-credentials`: A JSON string containing service principal credentials (Required) +- `gcp-wip`: The full identifier of the GCP Workload Identity Provider. See https://github.com/DFE-Digital/terraform-modules/blob/main/aks/dfe_analytics/README.md#authentication---github-actions (Optional) +- `gcp-project-id`: The name of the GCP Project ID. See https://github.com/DFE-Digital/terraform-modules/blob/main/aks/dfe_analytics/README.md#authentication---github-actions (Optional) +- `environment`: Name of the environment to deploy (Required) +- `pr-number`: Pull Request Number if deploying a review app (Optional) +- `db-seed`: Run seed command after a deployment. Should only be used for review apps (default: false) +- `sha`: Commit sha corresponding to the docker image tag to be deployed (Required) +- `slack-webhook` : A slack webhook to send a slack message to the service tech channel on deploy failure. See https://technical-guidance.education.gov.uk/infrastructure/monitoring/slack/#content (Optional) +- `smoke-test` : Run an application smoke test after deployment (default: false) +- `healthcheck` : Health check path, without first / e.g. 'healthcheck/all' (Optional) +- `terraform-base` : Name of the base terraform path (default: 'terraform/application') + +## Example + +```yaml +- name: Deploy App to Review + id: deploy_review + uses: DFE-Digital/github-actions/deploy-to-aks@master + with: + azure-credentials: ${{ secrets.AZURE_CREDENTIALS }} + environment: review + pr-number: ${{ github.event.pull_request.number }} + sha: ${{ needs.build.outputs.docker-image-tag }} + healthcheck: 'healthcheck/all' + db-seed: true + smoke-test: true + gcp-wip: ${{ vars.GCP_WIP }} + gcp-project-id: ${{ vars.GCP_PROJECT_ID }} +``` diff --git a/deploy-to-aks/action.yml b/deploy-to-aks/action.yml new file mode 100644 index 0000000..1282099 --- /dev/null +++ b/deploy-to-aks/action.yml @@ -0,0 +1,154 @@ +name: Deploy to AKS environment +description: Deploy a docker image to an AKS environment + +inputs: + azure-credentials: + description: A JSON string containing service principal credentials. + required: true + gcp-wip: + description: The full identifier of the GCP Workload Identity Provider. + required: false + gcp-project-id: + description: The name of the GCP Project ID. + required: false + environment: + description: Environment to deploy to + required: true + pr-number: + description: PR number for the review app + required: false + sha: + description: Commit sha to be deployed + required: true + slack-webhook: + description: Name of the slack webhook + required: false + db-seed: + description: Run seed command after a deployment. Normally only used for review apps. + type: boolean + required: false + default: false + smoke-test: + description: Enable smoke test after deployment + type: boolean + required: false + default: false + healthcheck: + description: Health check path + required: false + terraform-base: + description: Path to the terraform files + required: false + default: 'terraform/application' + +outputs: + environment_url: + description: The first external URL for the deployed environment + value: ${{ steps.set_output.outputs.ENVIRONMENT_URL }} + +runs: + using: composite + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set Environment variables + id: set_env_var + shell: bash + run: | + terraform_version=$(awk '/{/{f=/^terraform/;next}f' ${{ inputs.terraform-base }}/terraform.tf | grep -o [0-9\.]*) + echo "TERRAFORM_VERSION=$terraform_version" >> $GITHUB_ENV + + - name: Use Terraform ${{ env.TERRAFORM_VERSION }} + uses: hashicorp/setup-terraform@v3 + with: + terraform_version: ${{ env.TERRAFORM_VERSION }} + terraform_wrapper: false + + - uses: azure/login@v2 + if: ${{ inputs.db-seed == 'true' }} + with: + creds: ${{ inputs.azure-credentials }} + + - uses: google-github-actions/auth@v2 + if: ${{ inputs.gcp-wip != '' }} + with: + project_id: ${{ inputs.gcp-project-id }} + workload_identity_provider: ${{ inputs.gcp-wip }} + + - uses: DFE-Digital/github-actions/set-kubelogin-environment@master + with: + azure-credentials: ${{ inputs.azure-credentials }} + + - name: Terraform apply + shell: bash + run: make ${{ inputs.environment }} ci terraform-apply + env: + DOCKER_IMAGE_TAG: ${{ inputs.sha }} + PR_NUMBER: ${{ inputs.pr-number }} + + - name: Install kubectl + if: ${{ ( inputs.db-seed == 'true' && inputs.environment == 'review' ) }} + uses: DFE-Digital/github-actions/set-kubectl@master + + - name: Seed review app + shell: bash + if: ${{ inputs.db-seed == 'true' }} + run: make ci ${{ inputs.environment }} db-seed + env: + PR_NUMBER: ${{ inputs.pr-number }} + + - name: set DEPLOY_URL output + shell: bash + id: set_output + run: | + first_url=$(terraform -chdir=${{ inputs.terraform-base }} output -json external_urls | jq -r '.[0]') + echo "ENVIRONMENT_URL=${first_url}" >> $GITHUB_OUTPUT + + - name: Run healthcheck + if: ${{ inputs.healthcheck != '' }} + shell: bash + run: | + external_urls=$(terraform -chdir=${{ inputs.terraform-base }} output -json external_urls | jq -r '.[]') + for url in $external_urls; do + echo "Check health for $url/${{ inputs.healthcheck }}..." + curl -sS --fail "$url/${{ inputs.healthcheck }}" > /dev/null + done + if [ ${{ inputs.pr-number }} != '' ]; then + echo "URLS<> $GITHUB_ENV + for url in $external_urls; do + echo $url >> $GITHUB_ENV + done + echo "EOF" >> $GITHUB_ENV + fi + + - name: Post comment to Pull Request ${{ inputs.pr-number }} + if: inputs.pr-number != '' + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: aks + message: | + ### Deployments + + | Review app is available at these URLs: | + | ---------------------------------------------------------------------------------------- | + | ${{ env.URLS }} | + + - name: Run smoke test + shell: bash + if: ${{ inputs.smoke-test == 'true' }} + env: + PR_NUMBER: ${{ inputs.pr-number }} + run: | + make ci ${{ inputs.environment }} smoke-test + + - name: Notify Slack channel on job failure + if: ${{ failure() && github.ref == 'refs/heads/main' && inputs.slack-webhook != '' }} + uses: rtCamp/action-slack-notify@master + env: + SLACK_USERNAME: CI Deployment + SLACK_TITLE: Deployment failure + SLACK_MESSAGE: ${{ inputs.environment }} deployment job failed + SLACK_WEBHOOK: ${{ inputs.slack-webhook }} + SLACK_COLOR: failure + SLACK_FOOTER: Sent from deploy-to-aks