Skip to content

Test and deploy

Test and deploy #3019

name: 'Test and deploy'
env: # Keep this in sync with Dockerfile version
NODE_VERSION: "20.12.2"
on:
push:
branches: [ main ]
pull_request:
types: [ opened, synchronize ]
workflow_dispatch:
jobs:
lint:
name: 'Lint'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: 'Install'
run: npm install
- name: 'Lint'
run: npm run lint
env:
NODE_OPTIONS: '--max-old-space-size=8192'
test:
name: 'Test'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: 'Install'
run: npm install
- name: 'Test'
run: npm run test:ci
- name: 'Upload test results'
uses: actions/upload-artifact@v4
if: always()
with:
name: Test Results
path: junit.xml
- name: 'Upload coverage to Codecov'
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
directory: coverage
flags: unittests
# Upload event file so test results can be processed for the PR
# https://github.com/EnricoMi/publish-unit-test-result-action#support-fork-repositories-and-dependabot-branches
event_file:
name: "Event File"
runs-on: ubuntu-latest
steps:
- name: Upload
uses: actions/upload-artifact@v4
with:
name: Event File
path: ${{ github.event_path }}
build:
name: 'Build and deploy'
runs-on: ubuntu-22.04
env:
VERSION: snapshot
COMPOSE_PROJECT_NAME: tailormap-snapshot
COMPOSE_FILE: docker-compose.yml:docker-compose.traefik.yml:ci/docker-compose.snapshot.yml
COMPOSE_PROFILE: monitoring-enabled
BASE_HREF: /
HOST: ${{ secrets.DEPLOY_HOST_SNAPSHOT }}
API_SENTRY_DSN: ${{ vars.API_SENTRY_DSN }}
VIEWER_SENTRY_DSN: ${{ vars.VIEWER_SENTRY_DSN }}
ADMIN_HASHED_PASSWORD: ${{ secrets.ADMIN_HASHED_PASSWORD }}
OIDC_NAME: ${{ vars.OIDC_NAME }}
OIDC_ISSUER_URI: ${{ vars.OIDC_ISSUER_URI }}
OIDC_CLIENT_ID: ${{ vars.OIDC_CLIENT_ID }}
OIDC_CLIENT_SECRET: ${{ secrets.OIDC_CLIENT_SECRET }}
OIDC_SHOW_FOR_VIEWER: true
SOURCE_MAP_AUTH: ${{ secrets.SOURCE_MAP_AUTH }}
MAP5_URL: ${{ vars.MAP5_URL }}
BUILDX_NO_DEFAULT_ATTESTATIONS: 1
needs: [ lint, test ]
steps:
- uses: actions/checkout@v4
with:
# If tags aren't fetched the bin/post-build-localized.js script will leave fields in generated/version.json empty
# https://github.com/actions/checkout/issues/701
fetch-depth: 0
- name: 'GitHub Slug Action'
uses: rlespinasse/github-slug-action@v4
- name: 'Find Current Pull Request'
uses: jwalton/gh-find-current-pr@v1
id: find-pr
- name: 'Set variables for PR'
# When running on a PR, build and tag the Docker image for a deployment with a different base-href and a static-only deployment on
# a path prefix, with the frontend using the /api URL from the main branch deployment.
if: ${{ success() && steps.find-pr.outputs.number }}
env:
PR: ${{ steps.find-pr.outputs.number }}
run: |
echo "VERSION=pr-${PR}" >> $GITHUB_ENV
echo "COMPOSE_PROJECT_NAME=tailormap-pr-${PR}" >> $GITHUB_ENV
echo "COMPOSE_FILE=docker-compose.yml:docker-compose.traefik.yml:ci/docker-compose.pr.yml" >> $GITHUB_ENV
echo "BASE_HREF=/pull-request/${PR}/${GITHUB_REF_NAME_SLUG_URL}/" >> $GITHUB_ENV
echo "COMPOSE_PROFILE=" >> $GITHUB_ENV
- name: 'Log in to GitHub container registry'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: 'Build, tag and push image to registry'
# Always uses the 'snapshot' tag of the tailormap-api base image by setting the API_VERSION build arg
run: |
docker buildx create --use --name tailormap-builder
docker run --privileged --rm tonistiigi/binfmt --install all
docker buildx build --progress plain --pull --build-arg VERSION=${VERSION} --build-arg API_VERSION=snapshot --build-arg BASE_HREF=${BASE_HREF} --platform linux/amd64,linux/arm64 -t ghcr.io/b3partners/tailormap:${VERSION} . --push
- name: 'Set Docker context for deployment'
uses: arwynfr/actions-docker-context@v2
with:
docker_host: ${{ secrets.DOCKER_HOST_SNAPSHOT }}
context_name: 'dev-server'
ssh_cert: ${{ secrets.DOCKER_HOST_SNAPSHOT_SSH_CERT }}
ssh_key: ${{ secrets.DOCKER_HOST_SNAPSHOT_SSH_KEY }}
use_context: true
- name: 'Add known hosts'
run: |
ssh-keyscan -H ${{ secrets.DOCKER_HOSTNAME }} > $HOME/.ssh/known_hosts
# Latest Docker Compose version neededed for ci/docker-compose.pr.yml to use !reset to remove
# a service when merging Compose files
- name: Install latest Docker Compose
env:
COMPOSE_VERSION: "2.26.1"
run: |
DOCKER_CONFIG=/usr/local/lib/docker
sudo mkdir -p $DOCKER_CONFIG/cli-plugins
sudo curl -sSL https://github.com/docker/compose/releases/download/v${COMPOSE_VERSION}/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
docker compose version
- name: 'Update deployment using Docker Compose'
run: |
docker compose up -d --pull=always --quiet-pull
- name: 'Create GitHub deployment'
if: success()
uses: chrnorm/deployment-action@v2
with:
token: "${{ secrets.GITHUB_TOKEN }}"
environment-url: "https://${{ secrets.DEPLOY_HOST_SNAPSHOT }}${{ env.BASE_HREF}}"
description: "Deployment for ${{ env.VERSION }}"
environment: ${{ env.VERSION }}
initial-status: success
ref: "${{ env.GITHUB_HEAD_REF }}"
dependency-review:
name: 'Dependency Review'
if: ${{ github.event_name == 'pull_request' }}
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: actions/dependency-review-action@v4
# skip the jsts license check which fails on EDL-1.0, see https://github.com/actions/dependency-review-action/issues/575
with:
deny-licenses: GPL-2.0+, AGPL-3.0+
comment-summary-in-pr: on-failure
allow-dependencies-licenses: 'pkg:npm/jsts@2.11.0'
cyclonedx:
name: 'CycloneDX'
runs-on: ubuntu-latest
needs: build
permissions:
contents: read
if: ${{ github.ref == 'refs/heads/main' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || github.event_name == 'schedule') }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- run: npm install
- name: 'Create SBOM with CycloneDX'
uses: CycloneDX/gh-node-module-generatebom@v1
- name: 'Deploy SBOM'
uses: DependencyTrack/gh-upload-sbom@v3
with:
serverhostname: ${{ secrets.DEPENDENCY_TRACK_HOSTNAME }}
apikey: ${{ secrets.DEPENDENCY_TRACK_APIKEY }}
project: 'e63f997e-e070-423b-afc0-8ab704e14abf'
bomfilename: 'bom.xml'