Build & Unit Test #849
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
name: Deploy to AWS | |
run-name: ${{ github.event_name == 'workflow_dispatch' && format('Deploy to {0}', github.event.inputs.environment) || (github.ref == 'refs/heads/main' && 'Deploy to Test-UAT-Prod' || 'Build & Unit Test') }} | |
permissions: | |
packages: write | |
contents: write | |
on: | |
push: | |
paths-ignore: | |
[ | |
"**/README.md", | |
".github/workflows/increment-version.yml", | |
"version", | |
"python/**", | |
] | |
workflow_dispatch: | |
inputs: | |
environment: | |
description: Deploy to which environnment | |
type: choice | |
required: true | |
options: | |
- dev | |
- test | |
- uat | |
- prod | |
run_performance_tests: | |
required: false | |
default: false | |
type: boolean | |
description: Run performance tests | |
run_e2e_tests_assessment: | |
required: false | |
default: false | |
type: boolean | |
description: Run e2e tests (assessment) | |
run_e2e_tests_application: | |
required: false | |
default: true | |
type: boolean | |
description: Run e2e tests (application) | |
workflow_call: | |
inputs: | |
runner-cache-ref: | |
description: cache ref for the runner app | |
required: true | |
type: string | |
designer-cache-ref: | |
description: cache ref for the designer app | |
required: true | |
type: string | |
env: | |
DOCKER_REGISTRY: ghcr.io | |
IMAGE_NAME: "funding-service-design-form-runner-adapter" | |
IMAGE_NAME_DESIGNER: "funding-service-design-form-designer-adapter" | |
IMAGE_REPO_PATH: "ghcr.io/${{github.repository_owner}}" | |
jobs: | |
setup: | |
uses: communitiesuk/funding-service-design-workflows/.github/workflows/determine-jobs.yml@main | |
with: | |
environment: ${{ inputs.environment }} | |
docker-runner-build: | |
runs-on: ubuntu-latest | |
needs: [ setup ] | |
steps: | |
- name: Checkout repo | |
uses: actions/checkout@v4 | |
- name: "Set version in env" | |
id: set-version | |
run: | | |
source version | |
echo "VERSION=$VERSION" >> $GITHUB_ENV | |
- name: Docker metadata | |
id: metadata | |
uses: docker/metadata-action@v4 | |
with: | |
images: ${{env.IMAGE_REPO_PATH}}/${{env.IMAGE_NAME}} | |
tags: | | |
type=sha,format=long | |
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }} | |
type=raw,value=${{env.VERSION}},enable=${{ github.ref == format('refs/heads/{0}', 'main') }} | |
type=raw,value=latest | |
type=ref,event=branch | |
- name: Log in to the Container registry | |
uses: docker/login-action@v1 | |
with: | |
registry: ${{ env.DOCKER_REGISTRY }} | |
username: ${{ github.actor }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- uses: actions/checkout@v4 | |
- name: Use Node.js | |
uses: actions/setup-node@v3 | |
with: | |
node-version: "20.x" | |
- name: Get yarn cache directory path | |
id: yarn-cache-dir-path | |
run: echo "::set-output name=dir::$(yarn config get cacheFolder)" | |
- name: Get into the directory | |
id: change-dir | |
run: yarn config set enableImmutableInstalls false | |
- name: Create .env for runner workspace | |
run: | | |
touch ./runner/.env | |
echo LAST_TAG_GH=runner >> ./runner/.env | |
echo LAST_COMMIT_GH=runner >> ./runner/.env | |
cat ./runner/.env | |
- name: Run Unit test before docker build | |
run: | | |
echo "-- Git submodule initialize into local --" | |
git submodule update --init | |
echo "-- Pulling git submodules into local --" | |
git pull --recurse-submodules | |
echo "-- Installing digital-form-builder-adapter locally --" | |
node update-package.js | |
yarn install | |
echo "-- Building digital-form-builder-adapter locally --" | |
yarn setup | |
echo "-- Building digital-form-builder locally --" | |
# shellcheck disable=SC2164 | |
cd digital-form-builder | |
yarn | |
echo "-- Building digital-form-builder model locally --" | |
yarn model build | |
echo "-- Building digital-form-builder queue-model locally --" | |
yarn queue-model build | |
echo "-- Running unit tests --" | |
yarn runner test-cov | |
- name: Set up Docker Buildx property | |
run: echo "DOCKER_BUILDKIT=1" >> $GITHUB_ENV | |
- name: Cache Docker layers | |
uses: actions/cache@v4 | |
with: | |
path: ~/.buildx/cache | |
key: ${{ runner.os }}-buildx-runner-${{ hashFiles('./runner/Dockerfile') }}-${{ hashFiles('./runner/package.json') }} | |
restore-keys: | | |
${{ runner.os }}-buildx-runner-${{ hashFiles('./runner/Dockerfile') }}-${{ hashFiles('./runner/package.json') }} | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
with: | |
driver: docker-container | |
- name: Build and push docker image | |
uses: docker/build-push-action@v4 | |
with: | |
context: . | |
tags: ${{ steps.metadata.outputs.tags}} | |
labels: ${{ steps.metadata.outputs.labels }} | |
push: true | |
file: ./runner/Dockerfile | |
build-args: | | |
LAST_TAG='${{env.VERSION}}' | |
LAST_COMMIT='${{ github.sha }}' | |
cache-from: type=gha,scope=buildx | |
cache-to: type=gha,mode=max,scope=buildx | |
docker-designer-build: | |
runs-on: ubuntu-latest | |
needs: [ setup ] | |
steps: | |
- name: Checkout repo | |
uses: actions/checkout@v4 | |
- name: "Set version in env" | |
id: set-version | |
run: | | |
source version | |
echo "VERSION=$VERSION" >> $GITHUB_ENV | |
- name: Docker metadata | |
id: metadata | |
uses: docker/metadata-action@v4 | |
with: | |
images: ${{env.IMAGE_REPO_PATH}}/${{env.IMAGE_NAME_DESIGNER}} | |
tags: | | |
type=sha,format=long | |
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }} | |
type=raw,value=${{env.VERSION}},enable=${{ github.ref == format('refs/heads/{0}', 'main') }} | |
type=raw,value=latest | |
type=ref,event=branch | |
- name: Log in to the Container registry | |
uses: docker/login-action@v1 | |
with: | |
registry: ${{ env.DOCKER_REGISTRY }} | |
username: ${{ github.actor }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Create .env for designer workspace | |
run: | | |
touch ./designer/.env | |
echo LAST_TAG_GH=designer >> ./designer/.env | |
echo LAST_COMMIT_GH=designer >> ./designer/.env | |
cat ./designer/.env | |
- name: Cache Docker layers | |
uses: actions/cache@v4 | |
with: | |
path: ~/.buildx/cache | |
key: ${{ runner.os }}-buildx-runner-${{ hashFiles('./designer/Dockerfile') }}-${{ hashFiles('./designer/package.json') }} | |
restore-keys: | | |
${{ runner.os }}-buildx-designer-${{ hashFiles('./designer/Dockerfile') }}-${{ hashFiles('./designer/package.json') }} | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
with: | |
driver: docker-container | |
- name: Build and push docker image | |
uses: docker/build-push-action@v4 | |
with: | |
context: . | |
tags: ${{ steps.metadata.outputs.tags}} | |
labels: ${{ steps.metadata.outputs.labels }} | |
push: true | |
file: ./designer/Dockerfile | |
build-args: | | |
LAST_TAG='${{env.VERSION}}' | |
LAST_COMMIT='${{ github.sha }}' | |
cache-from: type=gha,scope=buildx | |
cache-to: type=gha,mode=max,scope=buildx | |
e2e-test: | |
needs: [ setup, docker-runner-build, docker-designer-build ] | |
runs-on: ubuntu-latest | |
name: run e2e | |
outputs: | |
tag: ${{ steps.hashFile.outputs.tag }} | |
hash: ${{ steps.hashFile.outputs.hash }} | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Use Node.js | |
uses: actions/setup-node@v3 | |
with: | |
node-version: "20.x" | |
- name: Get into the directory | |
id: change-dir | |
run: yarn config set enableImmutableInstalls false | |
- uses: actions/cache@v3 | |
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) | |
with: | |
path: | | |
node_modules # Cache the installed node modules | |
**/node_modules # Include subfolders if using workspaces | |
key: ${{ runner.os }}-yarn-e2e-${{ hashFiles('**/package.json') }} | |
restore-keys: | | |
${{ runner.os }}-yarn-e2e | |
${{ runner.os }}-yarn | |
- name: Setup e2e dependencies | |
run: | | |
echo "-- Git submodule initialize into local --" | |
git submodule update --init | |
echo "-- Pulling git submodules into local --" | |
git pull --recurse-submodules | |
echo "-- Installing digital-form-builder-adapter locally --" | |
node update-package.js | |
yarn install | |
echo "-- Install e2e dependencies --" | |
yarn e2e-test install | |
echo "-- Building digital-form-builder locally --" | |
cd digital-form-builder | |
yarn | |
- name: Injecting image into docker compose e2e | |
run: | | |
yq -i '.services.designer.image = "ghcr.io/communitiesuk/funding-service-design-form-designer-adapter:sha-${{ github.sha }}"' docker-compose.e2e.yml | |
yq -i '.services.runner.image = "ghcr.io/communitiesuk/funding-service-design-form-runner-adapter:sha-${{ github.sha }}"' docker-compose.e2e.yml | |
- name: Start containers | |
run: docker compose -f docker-compose.e2e.yml up -d | |
- name: Create S3 bucket | |
run: docker exec localstack /bin/sh -c "awslocal s3api create-bucket --bucket fsd-bucket --create-bucket-configuration LocationConstraint=eu-west-2 --region eu-west-2" | |
- name: Create S3 cors | |
run: | | |
docker exec localstack /bin/sh -c "awslocal s3api put-bucket-cors --bucket fsd-bucket --cors-configuration '{\"CORSRules\": [{\"AllowedOrigins\": [\"*\"],\"AllowedMethods\": [\"GET\", \"PUT\", \"POST\", \"DELETE\", \"HEAD\"],\"AllowedHeaders\": [\"*\"]}]}'" | |
- name: Run e2e tests | |
id: e2e | |
run: yarn e2e-test cypress run | |
continue-on-error: true | |
- name: Create Folders | |
run: mkdir -p ./e2e-test/cypress/screenshots/logs | |
- name: Get Logs from localstack | |
run: docker logs localstack > ./e2e-test/cypress/screenshots/logs/localstack.log | |
- name: Get Logs from runner | |
run: docker logs runner > ./e2e-test/cypress/screenshots/logs/runner.log | |
- name: Get all the uploaded files in the bucket | |
run: docker exec localstack /bin/sh -c "awslocal s3api list-objects --bucket fsd-bucket" | |
- name: Upload E2E Test Report Application | |
if: success() || failure() | |
uses: actions/[email protected] | |
with: | |
name: e2e-test-report-application | |
path: ./e2e-test/cypress/screenshots | |
retention-days: 5 | |
- name: Check for errors & exit the job | |
run: | | |
if [ "${{ steps.e2e.outcome }}" == "failure" ]; then | |
echo "Test failures please fix before deploying the service" | |
exit 1 | |
fi | |
dev_deploy: | |
needs: [ setup, docker-designer-build, docker-runner-build ] | |
if: ${{ always() && contains(fromJSON(needs.setup.outputs.jobs_to_run), 'dev') && (! contains(needs.*.result, 'failure') ) && (! contains(needs.*.result, 'cancelled') ) }} | |
permissions: | |
id-token: write # This is required for requesting the JWT | |
contents: read # This is required for actions/checkout | |
strategy: | |
matrix: | |
include: | |
- appname: "form-runner-adapter" | |
image_location: ghcr.io/communitiesuk/funding-service-design-form-runner-adapter:sha-${{ github.sha }} | |
- appname: "form-designer-adapter" | |
image_location: ghcr.io/communitiesuk/funding-service-design-form-designer-adapter:sha-${{ github.sha }} | |
uses: communitiesuk/funding-service-design-workflows/.github/workflows/standard-deploy.yml@main | |
secrets: | |
AWS_ACCOUNT: ${{ secrets.AWS_ACCOUNT }} | |
with: | |
environment: dev | |
app_name: ${{ matrix.appname }} | |
run_db_migrations: false | |
image_location: ${{ matrix.image_location }} | |
notify_slack: false | |
post_dev_deploy_tests: | |
needs: [ setup, docker-designer-build, docker-runner-build, dev_deploy ] | |
permissions: | |
id-token: write # This is required for requesting the JWT | |
contents: read # This is required for actions/checkout | |
secrets: | |
FSD_GH_APP_ID: ${{ secrets.FSD_GH_APP_ID }} | |
FSD_GH_APP_KEY: ${{ secrets.FSD_GH_APP_KEY }} | |
FS_BASIC_AUTH_USERNAME: ${{ secrets.FS_BASIC_AUTH_USERNAME }} | |
FS_BASIC_AUTH_PASSWORD: ${{ secrets.FS_BASIC_AUTH_PASSWORD }} | |
AWS_ACCOUNT: ${{ secrets.AWS_ACCOUNT }} | |
uses: communitiesuk/funding-service-design-workflows/.github/workflows/post-deploy.yml@main | |
with: | |
run_performance_tests: ${{ inputs.run_performance_tests || true }} | |
run_e2e_tests_assessment: ${{ inputs.run_e2e_tests_assessment || false }} | |
run_e2e_tests_application: ${{ inputs.run_e2e_tests_application || false }} | |
run_static_security_python: false | |
run_zap_scan: true | |
app_name: forms | |
environment: dev | |
notify_slack: false | |
test_deploy: | |
needs: [ setup, docker-designer-build, docker-runner-build, dev_deploy, post_dev_deploy_tests ] | |
if: ${{ always() && contains(fromJSON(needs.setup.outputs.jobs_to_run), 'test') && (! contains(needs.*.result, 'failure') ) && (! contains(needs.*.result, 'cancelled') ) }} | |
permissions: | |
id-token: write # This is required for requesting the JWT | |
contents: read # This is required for actions/checkout | |
strategy: | |
matrix: | |
include: | |
- appname: "form-runner-adapter" | |
image_location: ghcr.io/communitiesuk/funding-service-design-form-runner-adapter:sha-${{ github.sha }} | |
- appname: "form-designer-adapter" | |
image_location: ghcr.io/communitiesuk/funding-service-design-form-designer-adapter:sha-${{ github.sha }} | |
uses: communitiesuk/funding-service-design-workflows/.github/workflows/standard-deploy.yml@main | |
secrets: | |
AWS_ACCOUNT: ${{ secrets.AWS_ACCOUNT }} | |
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} | |
SLACK_NOTIFICATION_CHANNEL_ID: ${{ secrets.SLACK_NOTIFICATION_CHANNEL_ID }} | |
with: | |
environment: test | |
app_name: ${{ matrix.appname }} | |
run_db_migrations: false | |
image_location: ${{ matrix.image_location }} | |
notify_slack: true | |
post_test_deploy_tests: | |
needs: [ setup, docker-designer-build, docker-runner-build, dev_deploy, test_deploy ] | |
permissions: | |
id-token: write # This is required for requesting the JWT | |
contents: read # This is required for actions/checkout | |
if: ${{ always() && contains(fromJSON(needs.setup.outputs.jobs_to_run), 'test') && (! contains(needs.*.result, 'failure') ) && (! contains(needs.*.result, 'cancelled') ) }} | |
secrets: | |
FSD_GH_APP_ID: ${{ secrets.FSD_GH_APP_ID }} | |
FSD_GH_APP_KEY: ${{ secrets.FSD_GH_APP_KEY }} | |
FS_BASIC_AUTH_USERNAME: ${{ secrets.FS_BASIC_AUTH_USERNAME }} | |
FS_BASIC_AUTH_PASSWORD: ${{ secrets.FS_BASIC_AUTH_PASSWORD }} | |
AWS_ACCOUNT: ${{ secrets.AWS_ACCOUNT }} | |
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} | |
SLACK_NOTIFICATION_CHANNEL_ID: ${{ secrets.SLACK_NOTIFICATION_CHANNEL_ID }} | |
uses: communitiesuk/funding-service-design-workflows/.github/workflows/post-deploy.yml@main | |
with: | |
run_performance_tests: ${{ inputs.run_performance_tests || true }} | |
run_e2e_tests_assessment: ${{ inputs.run_e2e_tests_assessment || false }} | |
run_e2e_tests_application: ${{ inputs.run_e2e_tests_application || true }} | |
run_static_security_python: false | |
run_zap_scan: true | |
app_name: forms | |
environment: test | |
notify_slack: true | |
uat_deploy: | |
needs: [ setup, docker-designer-build, docker-runner-build, dev_deploy, test_deploy, post_test_deploy_tests ] | |
if: ${{ always() && contains(fromJSON(needs.setup.outputs.jobs_to_run), 'uat') && (! contains(needs.*.result, 'failure') ) && (! contains(needs.*.result, 'cancelled') ) }} | |
permissions: | |
id-token: write # This is required for requesting the JWT | |
contents: read # This is required for actions/checkout | |
uses: communitiesuk/funding-service-design-workflows/.github/workflows/standard-deploy.yml@main | |
secrets: | |
AWS_ACCOUNT: ${{ secrets.AWS_ACCOUNT }} | |
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} | |
SLACK_NOTIFICATION_CHANNEL_ID: ${{ secrets.SLACK_NOTIFICATION_CHANNEL_ID }} | |
with: | |
environment: uat | |
app_name: form-runner-adapter | |
run_db_migrations: false | |
image_location: ghcr.io/communitiesuk/funding-service-design-form-runner-adapter:sha-${{ github.sha }} | |
notify_slack: true | |
post_uat_deploy_tests: | |
needs: [ setup, docker-designer-build, docker-runner-build, dev_deploy, test_deploy, uat_deploy ] | |
permissions: | |
id-token: write # This is required for requesting the JWT | |
contents: read # This is required for actions/checkout | |
if: ${{ always() && contains(fromJSON(needs.setup.outputs.jobs_to_run), 'uat') && (! contains(needs.*.result, 'failure') ) && (! contains(needs.*.result, 'cancelled') ) }} | |
secrets: | |
FSD_GH_APP_ID: ${{ secrets.FSD_GH_APP_ID }} | |
FSD_GH_APP_KEY: ${{ secrets.FSD_GH_APP_KEY }} | |
FS_BASIC_AUTH_USERNAME: ${{ secrets.FS_BASIC_AUTH_USERNAME }} | |
FS_BASIC_AUTH_PASSWORD: ${{ secrets.FS_BASIC_AUTH_PASSWORD }} | |
AWS_ACCOUNT: ${{ secrets.AWS_ACCOUNT }} | |
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} | |
SLACK_NOTIFICATION_CHANNEL_ID: ${{ secrets.SLACK_NOTIFICATION_CHANNEL_ID }} | |
uses: communitiesuk/funding-service-design-workflows/.github/workflows/post-deploy.yml@main | |
with: | |
run_performance_tests: ${{ inputs.run_performance_tests || true }} | |
run_e2e_tests_assessment: ${{ inputs.run_e2e_tests_assessment || false }} | |
run_e2e_tests_application: ${{ inputs.run_e2e_tests_application || true }} | |
run_static_security_python: false | |
run_zap_scan: true | |
app_name: forms | |
environment: uat | |
notify_slack: true | |
prod_deploy: | |
needs: [ setup, docker-designer-build, docker-runner-build, dev_deploy, test_deploy, uat_deploy, post_uat_deploy_tests ] | |
if: ${{ always() && contains(fromJSON(needs.setup.outputs.jobs_to_run), 'prod') && (! contains(needs.*.result, 'failure') ) && (! contains(needs.*.result, 'cancelled') ) }} | |
permissions: | |
id-token: write # This is required for requesting the JWT | |
contents: read # This is required for actions/checkout | |
uses: communitiesuk/funding-service-design-workflows/.github/workflows/standard-deploy.yml@main | |
secrets: | |
AWS_ACCOUNT: ${{ secrets.AWS_ACCOUNT }} | |
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} | |
SLACK_NOTIFICATION_CHANNEL_ID: ${{ secrets.SLACK_NOTIFICATION_CHANNEL_ID }} | |
with: | |
environment: prod | |
app_name: form-runner-adapter | |
run_db_migrations: false | |
image_location: ghcr.io/communitiesuk/funding-service-design-form-runner-adapter:sha-${{ github.sha }} | |
notify_slack: true | |