Skip to content

Merge pull request #1389 from DFE-Digital/dependabot/terraform/terraf… #3680

Merge pull request #1389 from DFE-Digital/dependabot/terraform/terraf…

Merge pull request #1389 from DFE-Digital/dependabot/terraform/terraf… #3680

Workflow file for this run

name: Build Docker Image
on:
pull_request:
types: [assigned, opened, synchronize, reopened, ready_for_review]
push:
branches:
- master
permissions:
contents: write
deployments: write
issues: write
packages: write
pull-requests: write
jobs:
build:
name: Build
runs-on: ubuntu-latest
outputs:
DOCKER_IMAGE: ${{ env.DOCKER_IMAGE }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: set-up-environment
uses: DFE-Digital/github-actions/set-up-environment@master
- uses: Azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- uses: DfE-Digital/keyvault-yaml-secret@v1
id: keyvault-yaml-secret
with:
keyvault: ${{ secrets.KEY_VAULT}}
secret: INFRA-KEYS
key: SLACK-WEBHOOK, SNYK-TOKEN
- name: Lint Dockerfile
uses: brpaz/hadolint-action@master
with:
dockerfile: "Dockerfile"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@master
- name: Set environment variables
run: |
GIT_SHORT_SHA=$(echo "${{ github.sha }}" | cut -c -7)
echo "GIT_SHORT_SHA=${GIT_SHORT_SHA}" >> $GITHUB_ENV
if [ "${{github.ref}}" == "refs/heads/master" ]
then
DOCKER_IMAGE=${{ env.DOCKER_REPOSITORY }}:sha-${GIT_SHORT_SHA}
echo "DOCKER_IMAGE=${DOCKER_IMAGE}" >> $GITHUB_ENV
GIT_REF=${{ github.ref }} # GIT_BRANCH will be main for refs/heads/main
else
DOCKER_IMAGE=${{ env.DOCKER_REPOSITORY }}:review-${GIT_SHORT_SHA}
echo "DOCKER_IMAGE=${DOCKER_IMAGE}" >> $GITHUB_ENV
GIT_REF=${{ github.head_ref }}
fi
echo "GIT_BRANCH=${GIT_REF##*/}" >> $GITHUB_ENV
- name: Login to GitHub Container Repository
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build docker image
uses: docker/build-push-action@v5
with:
cache-from: |
type=registry,ref=${{ env.DOCKER_REPOSITORY }}:${{ env.GIT_BRANCH }}
type=registry,ref=${{ env.DOCKER_REPOSITORY }}:master
cache-to: type=inline
tags: |
${{ env.DOCKER_IMAGE }}
${{ env.DOCKER_REPOSITORY }}:${{ env.GIT_BRANCH }}
push: false
load: true
build-args: |
APP_SHA=${{ env.GIT_SHORT_SHA }}
- name: Push image to registry
if: ${{ success() }}
run: docker image push --all-tags ${{ env.DOCKER_REPOSITORY }}
- name: Slack Notification
if: failure() && github.ref == 'refs/heads/master'
uses: rtCamp/action-slack-notify@master
env:
SLACK_COLOR: ${{env.SLACK_ERROR}}
SLACK_TITLE: 'Failure Building Adviser'
SLACK_MESSAGE: 'There has been a failure building the teacher training adviser'
SLACK_WEBHOOK: ${{ steps.keyvault-yaml-secret.outputs.SLACK-WEBHOOK }}
java-test:
name: Javascript Tests
runs-on: ubuntu-latest
needs: [build]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: set-up-environment
uses: DFE-Digital/github-actions/set-up-environment@master
- uses: Azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- uses: DfE-Digital/keyvault-yaml-secret@v1
id: keyvault-yaml-secret
with:
keyvault: ${{ secrets.KEY_VAULT}}
secret: INFRA-KEYS
key: SLACK-WEBHOOK
- name: Run Javascript Tests
run: |-
docker run -t --rm -e RAILS_ENV=test -e NODE_ENV=test -e CI=true \
${{ needs.build.outputs.DOCKER_IMAGE }} "yarn && yarn spec"
- name: Slack Notification
if: failure() && github.ref == 'refs/heads/master'
uses: rtCamp/action-slack-notify@master
env:
SLACK_COLOR: ${{env.SLACK_FAILURE}}
SLACK_TITLE: 'Failure: Testing Master ${{env.APPLICATION}} ${{github.ref}}'
SLACK_TEXT: 'The javascript tests hav failed please click on the Actions URL to investigate the problem.'
SLACK_WEBHOOK: ${{ steps.keyvault-yaml-secret.outputs.SLACK-WEBHOOK }}
security-test:
name: Security Tests
runs-on: ubuntu-latest
needs: [build]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: set-up-environment
uses: DFE-Digital/github-actions/set-up-environment@master
- uses: Azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- uses: DfE-Digital/keyvault-yaml-secret@v1
id: keyvault-yaml-secret
with:
keyvault: ${{ secrets.KEY_VAULT}}
secret: INFRA-KEYS
key: SLACK-WEBHOOK
- name: Run Brakeman static security scanner
run: |-
docker run -t --rm -e RAILS_ENV=test ${{ needs.build.outputs.DOCKER_IMAGE }} brakeman --no-pager
- name: Slack Notification
if: failure() && github.ref == 'refs/heads/master'
uses: rtCamp/action-slack-notify@master
env:
SLACK_COLOR: ${{env.SLACK_FAILURE}}
SLACK_TITLE: 'Failure: Testing Master ${{env.APPLICATION}} ${{github.ref}}'
SLACK_TEXT: 'The security tests hav failed please click on the Actions URL to investigate the problem.'
SLACK_WEBHOOK: ${{ steps.keyvault-yaml-secret.outputs.SLACK-WEBHOOK }}
unit-test:
name: Unit Tests
runs-on: ubuntu-latest
needs: [build]
services:
postgres:
image: postgres:11.11
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- name: Checkout
uses: actions/checkout@v4
- name: set-up-environment
uses: DFE-Digital/github-actions/set-up-environment@master
- uses: Azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- uses: DfE-Digital/keyvault-yaml-secret@v1
id: keyvault-yaml-secret
with:
keyvault: ${{ secrets.KEY_VAULT}}
secret: INFRA-KEYS
key: SONAR-TOKEN, SLACK-WEBHOOK
- name: Setup sonarqube
uses: warchant/setup-sonar-scanner@v7
- name: Prepare DB
run: |-
docker run --net=host -t --rm -e RAILS_ENV=test -e DATABASE_URL="postgresql://postgres:postgres@localhost" ${{ needs.build.outputs.DOCKER_IMAGE }} rails db:prepare
- name: Lint Ruby
run: |-
docker run -t --rm -v ${PWD}/out:/app/out -e RAILS_ENV=test ${{ needs.build.outputs.DOCKER_IMAGE }} \
rubocop app config db lib spec Gemfile --format json --out=/app/out/rubocop-result.json
- name: Keep Rubocop output
if: always()
uses: actions/upload-artifact@v3
with:
name: Rubocop_results
path: ${{ github.workspace }}/out/rubocop-result.json
- name: Run Specs
run: |-
docker run --net=host -t --rm -v ${PWD}/out:/app/out -v ${PWD}/coverage:/app/coverage -e RAILS_ENV=test -e DATABASE_URL="postgresql://postgres:postgres@localhost" ${{ needs.build.outputs.DOCKER_IMAGE }} \
rspec --format RspecSonarqubeFormatter --out /app/out/test-report.xml --format documentation
- name: Fixup report file paths
run: sudo sed -i "s?\"/app/?\"${PWD}/?" coverage/coverage.json
- name: Keep Unit Tests Results
if: always()
uses: actions/upload-artifact@v3
with:
name: unit_tests
path: ${{ github.workspace }}/out/*
- name: Keep Code Coverage Report
if: always()
uses: actions/upload-artifact@v3
with:
name: Code_Coverage
path: ${{ github.workspace }}/coverage/*
- name: Run sonarqube
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: sonar-scanner
-Dsonar.login=${{ steps.keyvault-yaml-secret.outputs.SONAR-TOKEN }}
-Dsonar.organization=dfe-digital
-Dsonar.host.url=https://sonarcloud.io/
-Dsonar.projectKey=get-teacher-training-adviser-service
-Dsonar.testExecutionReportPaths=${PWD}/out/test-report.xml
-Dsonar.ruby.coverage.reportPaths=${PWD}/coverage/coverage.json
-Dsonar.ruby.rubocop.reportPaths=${PWD}/out/rubocop-result.json
- name: Slack Notification
if: failure() && github.ref == 'refs/heads/master'
uses: rtCamp/action-slack-notify@master
env:
SLACK_COLOR: ${{env.SLACK_FAILURE}}
SLACK_TITLE: 'Failure: Testing Master ${{env.APPLICATION}} ${{github.ref}}'
SLACK_TEXT: 'The Unit tests hav failed please click on the Actions URL to investigate the problem.'
SLACK_WEBHOOK: ${{ steps.keyvault-yaml-secret.outputs.SLACK-WEBHOOK }}
review:
name: Review Deployment Process
needs: [ unit-test , security-test, java-test ]
if: github.ref != 'refs/heads/master'
runs-on: ubuntu-latest
concurrency: Review_${{github.event.number}}
environment:
name: Review
steps:
- uses: actions/checkout@v4
- uses: DFE-Digital/github-actions/set-up-environment@master
- uses: Azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- uses: DfE-Digital/keyvault-yaml-secret@v1
id: keyvault-yaml-secret
with:
keyvault: ${{ secrets.KEY_VAULT}}
secret: INFRA-KEYS
key: SLACK-WEBHOOK
- name: Deploy to Review
uses: ./.github/workflows/actions/deploy
id: deploy
with:
environment: Review
sha: ${{ github.sha }}
pr: ${{github.event.number}}
AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
KEY_VAULT: ${{ secrets.KEY_VAULT }}
ARM_ACCESS_KEY: ${{ secrets.ARM_ACCESS_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Post PR comment
run: |
curl --silent \
--header "Accept: application/vnd.github.v3+json" \
--header "Authorization: Bearer ${{ github.token }}" \
--request POST \
--data '{"body": "Review app deployed to https://${{env.REVIEW_APPLICATION}}-${{github.event.number}}.${{env.DOMAIN}} "}' \
https://api.github.com/repos/${{ github.repository }}/issues/${{github.event.number }}/comments
- name: Add Review Label
if: contains(github.event.pull_request.user.login, 'dependabot') == false
uses: actions-ecosystem/action-add-labels@v1
with:
labels: Review
development:
name: Development Deployment
needs: [ unit-test , security-test, java-test ]
if: github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
concurrency: Development
outputs:
release_tag: ${{steps.tag_version.outputs.pr_number}}
release_sha: ${{github.sha}}
environment:
name: Development
steps:
- uses: actions/checkout@v4
- uses: DFE-Digital/github-actions/set-up-environment@master
- uses: Azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- uses: DfE-Digital/keyvault-yaml-secret@v1
id: keyvault-yaml-secret
with:
keyvault: ${{ secrets.KEY_VAULT}}
secret: INFRA-KEYS
key: SLACK-WEBHOOK
- name: Trigger Development Deployment
uses: ./.github/workflows/actions/deploy
id: deploy
with:
environment: Development
sha: ${{ github.sha }}
AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
KEY_VAULT: ${{ secrets.KEY_VAULT }}
ARM_ACCESS_KEY: ${{ secrets.ARM_ACCESS_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Generate Tag from PR Number
id: tag_version
uses: DFE-Digital/github-actions/GenerateReleaseFromSHA@master
with:
sha: ${{github.sha}}
- name: Create a GitHub Release
id: release
if: steps.tag_version.outputs.pr_found == 1
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.tag_version.outputs.pr_number }}
release_name: Release ${{ steps.tag_version.outputs.pr_number }}
commitish: ${{ github.sha }}
prerelease: false
draft: false
- name: Copy PR Info to Release
if: steps.release.outputs.id
uses: DFE-Digital/github-actions/CopyPRtoRelease@master
with:
PR_NUMBER: ${{ steps.tag_version.outputs.pr_number }}
RELEASE_ID: ${{ steps.release.outputs.id }}
TOKEN: ${{secrets.GITHUB_TOKEN}}
owasp:
name: OWASP Checks
needs: [ development ]
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v4
- name: Vunerability Test
uses: ./.github/workflows/actions/owasp
id: deploy
with:
environment: Development
AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
KEY_VAULT: ${{ secrets.KEY_VAULT }}
ARM_ACCESS_KEY: ${{ secrets.ARM_ACCESS_KEY }}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
qa:
name: Quality Assurance Deployment
needs: [ development ]
if: github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
concurrency: QA
environment:
name: Test
steps:
- uses: actions/checkout@v4
- uses: DFE-Digital/github-actions/set-up-environment@master
- uses: Azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- uses: DfE-Digital/keyvault-yaml-secret@v1
id: keyvault-yaml-secret
with:
keyvault: ${{ secrets.KEY_VAULT}}
secret: INFRA-KEYS
key: SLACK-WEBHOOK
- name: Deploy to Test
uses: ./.github/workflows/actions/deploy
id: deploy
with:
environment: Test
sha: ${{ github.sha }}
AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
KEY_VAULT: ${{ secrets.KEY_VAULT }}
ARM_ACCESS_KEY: ${{ secrets.ARM_ACCESS_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Slack Notification
if: failure()
uses: rtCamp/action-slack-notify@master
env:
SLACK_COLOR: ${{env.SLACK_FAILURE}}
SLACK_TITLE: 'Failure: Failure in Post-Development Deploy'
SLACK_MESSAGE: 'Failure with initialising QA deployment for ${{env.APPLICATION}}'
SLACK_WEBHOOK: ${{ steps.keyvault-yaml-secret.outputs.SLACK-WEBHOOK }}
integration:
name: Integration Tests
runs-on: ubuntu-latest
needs: [ build, qa ]
services:
postgres:
image: postgres:11.11
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- name: Checkout
uses: actions/checkout@v4
- name: set-up-environment
uses: DFE-Digital/github-actions/set-up-environment@master
- uses: Azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- uses: DfE-Digital/keyvault-yaml-secret@v1
id: keyvault-yaml-secret
with:
keyvault: ${{ secrets.KEY_VAULT}}
secret: INFRA-KEYS
key: HTTP-USERNAME, HTTP-PASSWORD, MAILSAC-API-KEY
- name: Prepare DB
run: |-
docker run --net=host -t --rm -e RAILS_ENV=test -e DATABASE_URL="postgresql://postgres:postgres@localhost" ${{ needs.build.outputs.DOCKER_IMAGE }} rails db:prepare
- name: Run Integration Tests
run: |-
docker run --net=host -t --rm -e RAILS_ENV=test -e HTTP_USERNAME -e HTTP_PASSWORD -e MAILSAC_API_KEY \
-e DATABASE_URL="postgresql://postgres:postgres@localhost" ${{needs.build.outputs.DOCKER_IMAGE}} "bundle exec rspec --tag integration"
env:
HTTP_USERNAME: ${{ steps.keyvault-yaml-secret.outputs.HTTP-USERNAME }}
HTTP_PASSWORD: ${{ steps.keyvault-yaml-secret.outputs.HTTP-PASSWORD }}
MAILSAC_API_KEY: ${{ steps.keyvault-yaml-secret.outputs.MAILSAC-API-KEY }}
production:
name: Production Deployment
runs-on: ubuntu-latest
needs: [ integration , development ]
concurrency: Production
environment:
name: Production
steps:
- uses: actions/checkout@v4
- uses: DFE-Digital/github-actions/set-up-environment@master
- uses: Azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- uses: DfE-Digital/keyvault-yaml-secret@v1
id: keyvault-yaml-secret
with:
keyvault: ${{ secrets.KEY_VAULT}}
secret: INFRA-KEYS
key: SLACK-WEBHOOK, SLACK-RELEASE-NOTE-WEBHOOK
- name: Get Release Id from Tag
id: tag_id
uses: DFE-Digital/github-actions/DraftReleaseByTag@master
with:
TAG: ${{needs.development.outputs.release_tag}}
TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Publish Release
if: steps.tag_id.outputs.release_id
uses: eregon/publish-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
release_id: ${{steps.tag_id.outputs.release_id}}
- name: Deploy to Production
uses: ./.github/workflows/actions/deploy
id: deploy
with:
environment: Production
sha: ${{ github.sha }}
AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
KEY_VAULT: ${{ secrets.KEY_VAULT }}
ARM_ACCESS_KEY: ${{ secrets.ARM_ACCESS_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Slack Release Notification
if: steps.tag_id.outputs.release_id
uses: rtCamp/action-slack-notify@master
env:
SLACK_COLOR: ${{env.SLACK_SUCCESS}}
SLACK_TITLE: "Release Published: ${{steps.tag_id.outputs.release_name}}"
SLACK_MESSAGE: ${{ fromJson( steps.tag_id.outputs.release_body) }}
SLACK_WEBHOOK: ${{ steps.keyvault-yaml-secret.outputs.SLACK-RELEASE-NOTE-WEBHOOK }}
MSG_MINIMAL: true
- name: Slack Notification
if: failure()
uses: rtCamp/action-slack-notify@master
env:
SLACK_COLOR: ${{env.SLACK_FAILURE}}
SLACK_TITLE: "Production Release : ${{github.event.title}}"
SLACK_MESSAGE: 'Failure deploying Production release'
SLACK_WEBHOOK: ${{ steps.keyvault-yaml-secret.outputs.SLACK-WEBHOOK }}