[171] Enable explicit consent to share references #17710
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
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json | |
name: Build and Deploy | |
concurrency: build_and_deploy_${{ github.ref_name }} | |
on: | |
push: | |
branches: | |
- main | |
pull_request: | |
branches: | |
- main | |
types: [opened, reopened, synchronize, labeled] | |
permissions: | |
contents: write | |
deployments: write | |
packages: write | |
pull-requests: write | |
jobs: | |
build: | |
environment: | |
name: review_aks | |
name: Build | |
runs-on: ubuntu-latest | |
env: | |
DOCKER_IMAGE: ghcr.io/dfe-digital/apply-teacher-training | |
GEMS_NODE_MODULES_IMAGE: ghcr.io/dfe-digital/apply-teacher-training-gems-node-modules | |
outputs: | |
IMAGE_TAG: ${{ env.IMAGE_TAG }} | |
GIT_BRANCH: ${{ env.GIT_BRANCH }} | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Set docker image tag (push) | |
if: github.event_name == 'push' | |
run: | | |
GIT_REF=${{ github.ref }} | |
echo "GIT_BRANCH=${GIT_REF##*/}" >> $GITHUB_ENV # GIT_BRANCH will be main for refs/heads/main | |
echo "IMAGE_TAG=${{ github.sha }}" >> $GITHUB_ENV | |
- name: Set docker image tag (pull_request) | |
if: github.event_name == 'pull_request' | |
run: | | |
# This is the actual PR branch | |
GIT_REF=${{ github.head_ref }} | |
echo "GIT_BRANCH=${GIT_REF##*/}" >> $GITHUB_ENV | |
echo "IMAGE_TAG=${{ github.event.pull_request.head.sha }}" >> $GITHUB_ENV | |
# TODO Need to check this for AKS review apps | |
- name: Set KV environment variables | |
run: | | |
# tag build to the review env for vars and secrets | |
tf_vars_file=terraform/aks/workspace_variables/review_aks.tfvars.json | |
echo "KEY_VAULT_NAME=$(jq -r '.key_vault_name' ${tf_vars_file})" >> $GITHUB_ENV | |
echo "KEY_VAULT_INFRA_SECRET_NAME=$(jq -r '.key_vault_infra_secret_name' ${tf_vars_file})" >> $GITHUB_ENV | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
- name: Login to GitHub Container Registry | |
uses: docker/login-action@v3 | |
with: | |
registry: ghcr.io | |
username: ${{ github.repository_owner }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- uses: azure/login@v2 | |
with: | |
creds: ${{ secrets.AZURE_CREDENTIALS }} | |
- uses: DFE-Digital/keyvault-yaml-secret@v1 | |
id: get-secret | |
with: | |
keyvault: ${{ env.KEY_VAULT_NAME }} | |
secret: ${{ env.KEY_VAULT_INFRA_SECRET_NAME }} | |
key: SNYK_TOKEN | |
- name: Build gems-node-modules Docker Image | |
uses: docker/build-push-action@v6 | |
with: | |
target: gems-node-modules | |
tags: | | |
${{ env.GEMS_NODE_MODULES_IMAGE }}:${{ env.IMAGE_TAG }} | |
${{ env.GEMS_NODE_MODULES_IMAGE }}:${{ env.GIT_BRANCH }} | |
push: true | |
cache-to: type=inline | |
cache-from: | | |
type=registry,ref=${{ env.GEMS_NODE_MODULES_IMAGE }}:${{ env.GIT_BRANCH }} | |
type=registry,ref=${{ env.GEMS_NODE_MODULES_IMAGE }}:main | |
- name: Build Docker Image | |
uses: docker/build-push-action@v6 | |
with: | |
tags: | | |
${{ env.DOCKER_IMAGE }}:${{ env.IMAGE_TAG }} | |
${{ env.DOCKER_IMAGE }}:${{ env.GIT_BRANCH }} | |
push: false | |
load: true | |
cache-to: type=inline | |
cache-from: | | |
type=registry,ref=${{ env.DOCKER_IMAGE }}:main | |
type=registry,ref=${{ env.DOCKER_IMAGE }}:${{ env.IMAGE_TAG }} | |
type=registry,ref=${{ env.DOCKER_IMAGE }}:${{ env.GIT_BRANCH }} | |
type=registry,ref=${{ env.GEMS_NODE_MODULES_IMAGE }}:${{ env.GIT_BRANCH }} | |
type=registry,ref=${{ env.GEMS_NODE_MODULES_IMAGE }}:main | |
build-args: | | |
SHA=${{ env.IMAGE_TAG }} | |
- name: Run Snyk to check Docker image for vulnerabilities | |
uses: snyk/actions/docker@master | |
env: | |
SNYK_TOKEN: ${{ steps.get-secret.outputs.snyk_token }} | |
with: | |
image: ${{ env.DOCKER_IMAGE }}:${{ env.IMAGE_TAG }} | |
args: --file=Dockerfile --severity-threshold=high --exclude-app-vulns | |
- name: Push ${{ env.DOCKER_IMAGE }} images | |
run: docker image push --all-tags ${{ env.DOCKER_IMAGE }} | |
- name: Notify Slack channel on job failure | |
if: failure() && github.event_name == 'push' | |
uses: rtCamp/action-slack-notify@v2 | |
env: | |
SLACK_USERNAME: CI Deployment | |
SLACK_TITLE: Build failure | |
SLACK_MESSAGE: Build failure on branch ${{env.GIT_BRANCH}} | |
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} | |
SLACK_COLOR: failure | |
SLACK_FOOTER: Sent from build job in build workflow | |
lint: | |
name: Lint | |
needs: [build] | |
runs-on: ubuntu-latest | |
defaults: | |
run: | |
working-directory: /app | |
strategy: | |
fail-fast: false | |
matrix: | |
tests: [rubocop, erblint, brakeman, yarn_lint] | |
include: | |
- tests: rubocop | |
command: bundle exec rubocop --format clang --parallel | |
- tests: erblint | |
command: bundle exec rake erblint | |
- tests: brakeman | |
command: bundle exec rake brakeman | |
- tests: yarn_lint | |
command: | | |
yarn install | |
yarn run lint && yarn run stylelint app/frontend/styles && \ | |
yarn run test | |
container: | |
image: ghcr.io/dfe-digital/apply-teacher-training-gems-node-modules:${{ needs.build.outputs.IMAGE_TAG }} | |
options: -a STDOUT -a STDERR -t | |
credentials: | |
username: ${{ github.repository_owner }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
steps: | |
- name: ${{ matrix.tests }} | |
run: ${{ env.COMMAND }} | |
env: | |
COMMAND: ${{ matrix.command }} | |
- name: Notify Slack channel on job failure | |
if: failure() && github.event_name == 'push' | |
uses: rtCamp/action-slack-notify@v2 | |
env: | |
SLACK_USERNAME: CI Deployment | |
SLACK_TITLE: Lint failure | |
SLACK_MESSAGE: ${{ matrix.tests }} lint failure on branch ${{ needs.build.outputs.GIT_BRANCH }} | |
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} | |
SLACK_COLOR: failure | |
SLACK_FOOTER: Sent from lint job in build workflow | |
test: | |
name: Tests | |
needs: [build] | |
runs-on: ubuntu-latest | |
outputs: | |
IMAGE_TAG: ${{ needs.build.outputs.IMAGE_TAG }} | |
flakey_tests: ${{ steps.set_flakey_test_results_var.outputs.flakey_tests }} | |
strategy: | |
fail-fast: false | |
matrix: | |
tests: | |
[ | |
unit_shared, | |
unit_candidate-provider, | |
unit_support-referee-api, | |
integration_shared, | |
integration_provider, | |
integration_candidate, | |
] | |
feature-flags: [on, off] | |
# Use these offsets as the end of cycle approaches | |
# offset-date: [real_world, after_apply_deadline, before_apply_reopens, after_apply_reopens] | |
# Use these offsets through mid-cycle | |
offset-date: [real_world] | |
include: | |
- tests: unit_shared | |
include-pattern: spec/.*_spec.rb | |
exclude-pattern: spec/(system|smoke|.*/(candidate_interface|provider_interface|support_interface|referee_interface|.*_api|api_.*|.*_api_.*))/.*_spec.rb | |
- tests: unit_candidate-provider | |
include-pattern: spec/.*/(candidate_interface|provider_interface)/.*_spec.rb | |
exclude-pattern: spec/(system|smoke)/.*_spec.rb | |
- tests: unit_support-referee-api | |
include-pattern: spec/.*/(support_interface|referee_interface|.*_api|api_.*|.*_api_.*)/.*_spec.rb | |
exclude-pattern: spec/(system|smoke)/.*_spec.rb | |
- tests: integration_shared | |
include-pattern: spec/system/.*_spec.rb | |
exclude-pattern: spec/system/(provider_interface|candidate_interface)/.*_spec.rb | |
- tests: integration_provider | |
include-pattern: spec/system/provider_interface/.*_spec.rb | |
- tests: integration_candidate | |
include-pattern: spec/system/candidate_interface/.*_spec.rb | |
services: | |
redis: | |
image: redis:alpine | |
ports: | |
- 6379:6379 | |
postgres: | |
image: postgres:14 | |
env: | |
POSTGRES_USER: postgres | |
POSTGRES_PASSWORD: postgres | |
POSTGRES_DB: postgres | |
ports: | |
- 5432:5432 | |
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 | |
defaults: | |
run: | |
working-directory: /app | |
container: | |
image: ghcr.io/dfe-digital/apply-teacher-training:${{ needs.build.outputs.IMAGE_TAG }} | |
credentials: | |
username: ${{ github.repository_owner }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
env: | |
RAILS_ENV: test | |
DB_HOSTNAME: postgres | |
DB_USERNAME: postgres | |
DB_PASSWORD: postgres | |
REDIS_URL: redis://redis:6379/0 | |
DB_PORT: 5432 | |
ZENDESK_MESSAGING_KEY: ${{ secrets.ZENDESK_MESSAGING_KEY_CI }} | |
steps: | |
- name: Setup Parallel Database | |
run: bundle exec rake parallel:setup | |
- name: Install chromedriver | |
run: apk add chromium chromium-chromedriver | |
- name: ${{ matrix.tests }} tests with feature flags ${{ matrix.feature-flags }} | |
run: bundle exec --verbose parallel_rspec --pattern "${{ env.INCLUDE_PATTERN }}" --exclude-pattern "${{ env.EXCLUDE_PATTERN }}" | |
env: | |
INCLUDE_PATTERN: ${{ matrix.include-pattern }} | |
EXCLUDE_PATTERN: ${{ matrix.exclude-pattern || ' ' }} | |
TEST_MATRIX_NODE_NAME: ${{ matrix.tests }} | |
DEFAULT_FEATURE_FLAG_STATE: ${{ matrix.feature-flags }} | |
TEST_DATE_AND_TIME: ${{ matrix.offset-date }} | |
- name: Read flakey test results | |
id: set_flakey_test_results_var | |
run: | | |
file_text=$(cat /app/tmp/rspec-retry-flakey-specs.log) | |
if [ ! -z "$file_text" ] | |
then | |
echo "Flakey specs found" | |
echo "file_text: $file_text" | |
# Use GitHub SHA as uuidgen is not available | |
echo "flakey_tests<<$GITHUB_SHA" >> $GITHUB_OUTPUT | |
cat /app/tmp/rspec-retry-flakey-specs.log >> $GITHUB_OUTPUT | |
echo "$GITHUB_SHA" >> $GITHUB_OUTPUT | |
else | |
echo "No flakey tests logged" | |
fi | |
- name: Notify Slack channel on job failure | |
if: failure() && github.event_name == 'push' | |
uses: rtCamp/action-slack-notify@v2 | |
env: | |
SLACK_USERNAME: CI Deployment | |
SLACK_TITLE: Test failure | |
SLACK_MESSAGE: ${{ matrix.tests }} (feature-flags ${{ matrix.feature-flags }}) test failure on branch ${{ needs.build.outputs.GIT_BRANCH }} | |
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} | |
SLACK_COLOR: failure | |
SLACK_FOOTER: Sent from test job in build workflow | |
report-flakey-specs: | |
name: Report on flakey specs in pull request | |
needs: [test] | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout source | |
uses: actions/checkout@v4 | |
- name: Comment on flakey specs in pull request | |
uses: actions/github-script@v7 | |
if: github.event_name == 'pull_request' && needs.test.outputs.flakey_tests | |
env: | |
FLAKEY_TEST_DATA: | | |
${{ needs.test.outputs.flakey_tests }} | |
with: | |
github-token: ${{ secrets.GITHUB_TOKEN }} | |
script: | | |
const script = require('/home/runner/work/apply-for-teacher-training/apply-for-teacher-training/.github/scripts/comment_on_flakey_specs.js') | |
script({github, context}) | |
deploy-v2-review-app: | |
name: Deployment To Review v2 | |
concurrency: deploy_v2_review_${{ github.event.pull_request.number }} | |
if: ${{ github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'deploy_v2') }} | |
environment: | |
name: review_aks | |
needs: [build] | |
runs-on: ubuntu-latest | |
steps: | |
- name: Start review_aks-${{ github.event.pull_request.number }} Deployment | |
uses: bobheadxi/deployments@v1 | |
id: deployment | |
with: | |
env: review_aks-${{ github.event.pull_request.number }} | |
ref: ${{ github.head_ref }} | |
step: start | |
token: ${{ secrets.GITHUB_TOKEN }} | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Deploy App to Review v2 | |
id: deploy_v2_review | |
uses: ./.github/actions/deploy_v2/ | |
with: | |
azure-credentials: ${{ secrets.AZURE_CREDENTIALS }} | |
environment: review_aks | |
pr-number: ${{ github.event.pull_request.number }} | |
sha: ${{ needs.build.outputs.IMAGE_TAG }} | |
slack-webhook: ${{ secrets.SLACK_WEBHOOK }} | |
- name: Update review_aks-${{ github.event.pull_request.number }} status | |
if: always() | |
uses: bobheadxi/deployments@v1 | |
with: | |
env: review_aks-${{ github.event.pull_request.number }} | |
ref: ${{ github.head_ref }} | |
step: finish | |
token: ${{ secrets.GITHUB_TOKEN }} | |
status: ${{ job.status }} | |
deployment_id: ${{ steps.deployment.outputs.deployment_id }} | |
env_url: ${{ steps.deploy_v2_review.outputs.deploy-url }} | |
merge-dependabot: | |
name: Merge dependabot | |
if: ${{ github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'dependencies') }} | |
needs: [lint, test, deploy-v2-review-app, report-flakey-specs] | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Merge minor dependency updates | |
uses: fastify/github-action-merge-dependabot@v3 | |
with: | |
github-token: ${{ secrets.ACTIONS_API_ACCESS_TOKEN }} | |
target: minor | |
exclude: "govuk-components,govuk_design_system_formbuilder,govuk-frontend" | |
merge-method: merge | |
deploy-aks-before-production: | |
name: Parallel deployment before production v2 | |
if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
environment: | |
name: ${{ matrix.environment }} | |
url: ${{ steps.deploy_app_before_production_v2.outputs.deploy-url }} | |
needs: [lint, test] | |
runs-on: ubuntu-latest | |
strategy: | |
fail-fast: false | |
matrix: | |
environment: [qa_aks, staging_aks] | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Deploy App to ${{ matrix.environment }} v2 | |
id: deploy_app_before_production_v2 | |
uses: ./.github/actions/deploy_v2/ | |
with: | |
azure-credentials: ${{ secrets.AZURE_CREDENTIALS }} | |
environment: ${{ matrix.environment }} | |
sha: ${{ github.sha }} | |
slack-webhook: ${{ secrets.SLACK_WEBHOOK }} | |
deploy-aks-production: | |
name: Production deployment v2 | |
if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
environment: | |
name: production_aks | |
url: ${{ steps.deploy_app_v2.outputs.deploy-url }} | |
needs: [deploy-aks-before-production] | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Deploy App to production v2 | |
id: deploy_app_v2 | |
uses: ./.github/actions/deploy_v2/ | |
with: | |
azure-credentials: ${{ secrets.AZURE_CREDENTIALS }} | |
environment: production_aks | |
sha: ${{ github.sha }} | |
slack-webhook: ${{ secrets.SLACK_WEBHOOK }} | |
# TODO Update needs to deploy-aks-production when production is deployed | |
deploy-aks-after-production: | |
name: Sandbox deployment v2 | |
if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
environment: | |
name: sandbox_aks | |
url: ${{ steps.deploy_app_after_production_v2.outputs.deploy-url }} | |
needs: [deploy-aks-production] | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Deploy App to sandbox v2 | |
id: deploy_app_after_production_v2 | |
uses: ./.github/actions/deploy_v2/ | |
with: | |
azure-credentials: ${{ secrets.AZURE_CREDENTIALS }} | |
environment: sandbox_aks | |
sha: ${{ github.sha }} | |
slack-webhook: ${{ secrets.SLACK_WEBHOOK }} |