CI #20
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: CI | |
on: | |
push: | |
branches: | |
- master | |
pull_request: | |
schedule: | |
- cron: '0 7 * * 1' | |
workflow_run: | |
workflows: ['Deploy preview'] | |
branches-ignore: | |
- master | |
jobs: | |
# This job is used to determine what files have changed and is used by later jobs to determine if they should run. | |
setup: | |
name: Setup | |
runs-on: ubuntu-latest | |
timeout-minutes: 1 | |
outputs: | |
frontend: ${{ steps.check-changed-files.outputs.frontend_any_changed }} | |
config: ${{ steps.check-changed-files.outputs.config_any_changed }} | |
markdown: ${{ steps.check-changed-files.outputs.markdown_any_changed }} | |
json: ${{ steps.check-changed-files.outputs.json_any_changed }} | |
python: ${{ steps.check-changed-files.outputs.python_any_changed }} | |
workflows: ${{ steps.check-changed-files.outputs.workflows_any_changed }} | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 2 | |
- name: Check which files have changed | |
id: check-changed-files | |
uses: tj-actions/[email protected] | |
with: | |
files_yaml_from_source_file: .github/filter-groups.yml | |
- name: Log outputs | |
run: | | |
echo "frontend changed: ${{ steps.check-changed-files.outputs.frontend_any_changed }} | |
echo "config changed: ${{ steps.check-changed-files.outputs.config_any_changed }} | |
echo "markdown changed: ${{ steps.check-changed-files.outputs.markdown_any_changed }} | |
echo "json changed: ${{ steps.check-changed-files.outputs.json_any_changed }} | |
echo "python changed: ${{ steps.check-changed-files.outputs.python_any_changed }} | |
echo "workflows changed: ${{ steps.check-changed-files.outputs.workflows_any_changed }} | |
# # | |
# Repository wide checks # | |
# # | |
prettier: | |
name: Prettier | |
runs-on: ubuntu-latest | |
timeout-minutes: 5 | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Setup PNPM | |
uses: pnpm/action-setup@v4 | |
with: | |
version: 9 | |
- name: Setup Node | |
uses: actions/setup-node@v4 | |
with: | |
node-version-file: './web/.node-version' | |
- name: Restore node_modules for web | |
id: cache-web | |
uses: actions/cache@v4 | |
with: | |
path: web/node_modules | |
key: ${{ runner.os }}-node_modules-${{ hashFiles('./web/pnpm-lock.yaml') }} | |
- name: Install web dependencies | |
if: steps.cache-web.outputs.cache-hit != 'true' | |
run: pnpm install --frozen-lockfile | |
working-directory: ./web | |
- name: Prettier Check | |
# Uses the prettier binary from the web node_modules so it's always in sync. | |
run: | | |
web/node_modules/.bin/prettier --check . | |
earthly: | |
name: earthly | |
needs: [prettier] | |
uses: ./.github/workflows/earthly-contrib.yml | |
secrets: inherit | |
validate_local_links: | |
name: Validate | |
needs: [setup] | |
if: >- | |
needs.setup.outputs.markdown != 'false' || | |
needs.setup.outputs.workflows != 'false' | |
uses: ./.github/workflows/validate_local_links_in_md.yml | |
jsonlint: | |
name: JSONLint | |
needs: [setup, prettier] | |
if: >- | |
needs.setup.outputs.json != 'false' || | |
needs.setup.outputs.workflows != 'false' | |
runs-on: ubuntu-latest | |
timeout-minutes: 1 | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Setup Node | |
uses: actions/setup-node@v4 | |
with: | |
node-version-file: './web/.node-version' | |
- name: Install jsonlint-mod | |
run: | | |
npm install -g jsonlint-mod | |
- name: Lint json | |
run: | | |
jsonlint -q web/src/locales/*.json | |
# # | |
# Frontend checks # | |
# # | |
unit_test: | |
name: Frontend / Unit tests | |
needs: [setup, prettier] | |
if: >- | |
needs.setup.outputs.frontend != 'false' || | |
needs.setup.outputs.workflows != 'false' | |
runs-on: ubuntu-latest | |
timeout-minutes: 4 | |
defaults: | |
run: | |
working-directory: web | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Setup PNPM | |
uses: pnpm/action-setup@v4 | |
with: | |
version: 9 | |
- name: Setup Node | |
uses: actions/setup-node@v4 | |
with: | |
node-version-file: './web/.node-version' | |
- name: Restore node_modules for web | |
id: cache-web | |
uses: actions/cache@v4 | |
with: | |
path: ./web/node_modules | |
key: ${{ runner.os }}-node_modules-${{ hashFiles('./web/pnpm-lock.yaml') }} | |
- name: Install web dependencies | |
if: steps.cache.outputs.cache-hit != 'true' | |
run: pnpm install --frozen-lockfile | |
- name: Generate config files | |
if: steps.cache.outputs.cache-hit == 'true' | |
run: pnpm create-generated-files | |
- name: Run test | |
run: pnpm run test:ci | |
eslint: | |
name: Frontend / ESLint | |
needs: [setup, prettier] | |
if: >- | |
needs.setup.outputs.frontend != 'false' || | |
needs.setup.outputs.workflows != 'false' | |
runs-on: ubuntu-latest | |
permissions: | |
contents: read | |
security-events: write | |
timeout-minutes: 4 | |
defaults: | |
run: | |
working-directory: web | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Setup PNPM | |
uses: pnpm/action-setup@v4 | |
with: | |
version: 9 | |
- name: Setup Node | |
uses: actions/setup-node@v4 | |
with: | |
node-version-file: './web/.node-version' | |
- name: Restore node_modules for web | |
id: cache-web | |
uses: actions/cache@v4 | |
with: | |
path: ./web/node_modules | |
key: ${{ runner.os }}-node_modules-${{ hashFiles('./web/pnpm-lock.yaml') }} | |
- name: Install web dependencies | |
if: steps.cache.outputs.cache-hit != 'true' | |
run: pnpm install --frozen-lockfile | |
- name: Generate config files | |
if: steps.cache.outputs.cache-hit == 'true' | |
run: pnpm create-generated-files | |
- name: Restore ESLint cache | |
uses: actions/cache@v4 | |
with: | |
path: ./web/node_modules/.cache/eslint/.eslintcache | |
key: ${{ runner.os }}-eslint_cache-${{ github.ref_name }}-${{ github.run_id }} | |
restore-keys: | | |
${{ runner.os }}-eslint_cache-${{ github.ref_name }} | |
${{ runner.os }}-eslint_cache-master | |
- name: ESLint | |
run: node_modules/.bin/eslint . | |
--ignore-path .gitignore | |
--ext .ts,.tsx . | |
--cache | |
--cache-location node_modules/.cache/eslint/.eslintcache | |
--format @microsoft/eslint-formatter-sarif | |
--output-file eslint-results.sarif | |
continue-on-error: true | |
- name: Upload analysis results to GitHub | |
uses: github/codeql-action/upload-sarif@v3 | |
with: | |
sarif_file: web/eslint-results.sarif | |
wait-for-processing: true | |
typecheck: | |
name: Frontend / Typecheck | |
needs: [setup, prettier] | |
if: >- | |
needs.setup.outputs.frontend != 'false' || | |
needs.setup.outputs.workflows != 'false' | |
runs-on: ubuntu-latest | |
timeout-minutes: 4 | |
defaults: | |
run: | |
working-directory: web | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Setup PNPM | |
uses: pnpm/action-setup@v4 | |
with: | |
version: 9 | |
- name: Setup Node | |
uses: actions/setup-node@v4 | |
with: | |
node-version-file: './web/.node-version' | |
- name: Restore node_modules for web | |
id: cache-web | |
uses: actions/cache@v4 | |
with: | |
path: ./web/node_modules | |
key: ${{ runner.os }}-node_modules-${{ hashFiles('./web/pnpm-lock.yaml') }} | |
- name: Install web dependencies | |
if: steps.cache.outputs.cache-hit != 'true' | |
run: pnpm install --frozen-lockfile | |
- name: Generate config files | |
run: pnpm create-generated-files | |
- name: Run TypeScript typechecking for app | |
run: pnpm run typecheck | |
- name: Run TypeScript typechecking for scripts | |
run: pnpm run typecheck --project tsconfig.node.json | |
validate_generate_files: | |
name: Frontend / Validate generated files | |
needs: [setup, prettier] | |
if: >- | |
needs.setup.outputs.frontend != 'false' || | |
needs.setup.outputs.config != 'false' || | |
needs.setup.outputs.workflows != 'false' | |
runs-on: ubuntu-latest | |
timeout-minutes: 2 | |
defaults: | |
run: | |
working-directory: web | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Setup PNPM | |
uses: pnpm/action-setup@v4 | |
with: | |
version: 9 | |
- name: Setup Node | |
uses: actions/setup-node@v4 | |
with: | |
node-version-file: './web/.node-version' | |
- name: Restore node_modules for web | |
id: cache-web | |
uses: actions/cache@v4 | |
with: | |
path: ./web/node_modules | |
key: ${{ runner.os }}-node_modules-${{ hashFiles('./web/pnpm-lock.yaml') }} | |
- name: Install web dependencies | |
if: steps.cache.outputs.cache-hit != 'true' | |
run: pnpm install --frozen-lockfile | |
- name: Generate zone config | |
run: pnpm run generate-zones-config | |
- name: Generate world file | |
run: pnpm run generate-world | |
deploy_preview_branch: | |
name: Deploy preview | |
needs: [eslint, typecheck, setup, validate_generate_files, unit_test] | |
if: >- | |
(needs.setup.outputs.frontend != 'false' || | |
needs.setup.outputs.workflows != 'false') && | |
github.event.pull_request.head.repo.full_name == github.repository && | |
github.ref_name != 'master' | |
uses: ./.github/workflows/deploy_preview_branch.yml | |
secrets: inherit | |
cypress_component: | |
name: Frontend / Cypress / Component | |
needs: [eslint, typecheck, validate_generate_files, unit_test] | |
runs-on: ubuntu-latest | |
timeout-minutes: 5 | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Setup PNPM | |
uses: pnpm/action-setup@v4 | |
with: | |
version: 9 | |
- name: Setup Node | |
uses: actions/setup-node@v4 | |
with: | |
node-version-file: './web/.node-version' | |
- name: Install ts-node | |
run: pnpm add ts-node --save-dev | |
working-directory: ./web | |
- name: Generate config files | |
run: pnpm create-generated-files | |
working-directory: ./web | |
- name: Cache Cypress binary | |
id: cache-cypress | |
uses: actions/cache@v4 | |
with: | |
path: ~/.cache/Cypress | |
key: ${{ runner.os }}-cypress-${{ hashFiles('./web/pnpm-lock.yaml') }} | |
- name: Restore node_modules for web | |
id: cache-web | |
uses: actions/cache@v4 | |
with: | |
path: web/node_modules | |
key: ${{ runner.os }}-node_modules-${{ hashFiles('./web/pnpm-lock.yaml') }} | |
- name: Install web dependencies | |
if: steps.cache-web.outputs.cache-hit != 'true' | |
run: pnpm install --frozen-lockfile | |
working-directory: ./web | |
- name: Install Cypress binary | |
if: steps.cache-cypress.outputs.cache-hit != 'true' | |
run: pnpm exec cypress install | |
working-directory: ./web | |
- name: Cypress run component tests | |
uses: cypress-io/github-action@v6 | |
env: | |
TZ: Europe/Copenhagen | |
with: | |
working-directory: ./web | |
install: false | |
# to run component tests we need to use "component: true" | |
component: true | |
- name: Upload screenshots | |
uses: actions/upload-artifact@v4 | |
if: failure() | |
with: | |
name: component-screenshots | |
path: web/cypress/screenshots | |
cypress_e2e: | |
name: Frontend / Cypress / E2E | |
needs: [eslint, typecheck, validate_generate_files, unit_test] | |
runs-on: ubuntu-latest | |
timeout-minutes: 10 | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Setup PNPM | |
uses: pnpm/action-setup@v4 | |
with: | |
version: 9 | |
- name: Setup Node | |
uses: actions/setup-node@v4 | |
with: | |
node-version-file: './web/.node-version' | |
- name: Cache Cypress binary | |
id: cache-cypress | |
uses: actions/cache@v4 | |
with: | |
path: ~/.cache/Cypress | |
key: ${{ runner.os }}-cypress-${{ hashFiles('./web/pnpm-lock.yaml') }} | |
- name: Restore node_modules for web | |
id: cache-web | |
uses: actions/cache@v4 | |
with: | |
path: web/node_modules | |
key: ${{ runner.os }}-node_modules-${{ hashFiles('./web/pnpm-lock.yaml') }} | |
- name: Install web dependencies | |
if: steps.cache-web.outputs.cache-hit != 'true' | |
run: pnpm install --frozen-lockfile | |
working-directory: ./web | |
- name: Install Cypress binary | |
if: steps.cache-cypress.outputs.cache-hit != 'true' | |
run: pnpm exec cypress install | |
working-directory: ./web | |
- name: Cypress run e2e tests | |
uses: cypress-io/github-action@v6 | |
env: | |
TZ: Europe/Copenhagen | |
with: | |
working-directory: ./web | |
install: false | |
build: pnpm run build --mode testing | |
start: pnpm run preview | |
config: baseUrl=http://127.0.0.1:4173/ | |
- name: Upload screenshots | |
uses: actions/upload-artifact@v4 | |
if: failure() | |
with: | |
name: e2e-screenshots | |
path: web/cypress/screenshots | |
# Python checks | |
python_formatting: | |
name: Python / Formatting | |
needs: [setup] | |
if: >- | |
needs.setup.outputs.python != 'false' || | |
needs.setup.outputs.workflows != 'false' | |
runs-on: ubuntu-latest | |
timeout-minutes: 5 | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Install poetry | |
run: | | |
pipx install poetry | |
- name: Get poetry version | |
id: get-poetry-version | |
run: | | |
echo "$(poetry --version | awk '{print "poetry-version="$3}' | tr -d '()')" >> $GITHUB_OUTPUT | |
- name: Setup Python | |
uses: actions/setup-python@v5 | |
with: | |
python-version-file: '.python-version' | |
- name: Restore cache | |
id: cache | |
uses: actions/cache@v4 | |
with: | |
path: .venv | |
key: ${{ runner.os }}-venv-poetry_${{steps.get-poetry-version.outputs.poetry-version}}-${{ hashFiles('poetry.lock') }} | |
restore-keys: ${{ runner.os }}-venv-poetry_${{steps.get-poetry-version.outputs.poetry-version}} | |
- name: Install Dependencies | |
if: steps.cache.outputs.cache-hit != 'true' | |
run: | | |
poetry install -E parsers --sync | |
- name: Check formatting | |
run: | | |
poetry run ruff format . --check | |
- name: Check linting | |
run: | | |
poetry run ruff check . --output-format=github | |
python_tests: | |
name: Python / Tests | |
needs: [setup] | |
if: >- | |
needs.setup.outputs.python != 'false' || | |
needs.setup.outputs.config != 'false' || | |
needs.setup.outputs.workflows != 'false' | |
runs-on: ubuntu-latest | |
timeout-minutes: 10 | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Install poetry | |
run: | | |
pipx install poetry | |
- name: Get poetry version | |
id: get-poetry-version | |
run: | | |
echo "$(poetry --version | awk '{print "poetry-version="$3}' | tr -d '()')" >> $GITHUB_OUTPUT | |
- name: Setup Python | |
uses: actions/setup-python@v5 | |
with: | |
python-version-file: '.python-version' | |
- name: Restore cache | |
id: cache | |
uses: actions/cache@v4 | |
with: | |
path: .venv | |
key: ${{ runner.os }}-venv-poetry_${{steps.get-poetry-version.outputs.poetry-version}}-${{ hashFiles('poetry.lock') }} | |
restore-keys: ${{ runner.os }}-venv-poetry_${{steps.get-poetry-version.outputs.poetry-version}} | |
- name: Install libxml2-dev and tesseract-ocr | |
run: | | |
sudo apt-get update | |
sudo apt-get install libxml2-dev tesseract-ocr tesseract-ocr-eng | |
- name: Install Poetry dependencies | |
if: steps.cache.outputs.cache-hit != 'true' | |
run: | | |
poetry install -E parsers --sync | |
- name: Run tests | |
run: | | |
poetry run test | |
# Config checks | |
validate_config_filenames: | |
name: Validate / Config filenames | |
needs: [setup] | |
if: >- | |
needs.setup.outputs.config != 'false' || | |
needs.setup.outputs.workflows != 'false' | |
runs-on: ubuntu-latest | |
timeout-minutes: 5 | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Validate config filenames | |
run: python scripts/validate_config_filenames.py | |
# Code quality checks | |
codeql: | |
needs: [setup, prettier] | |
name: CodeQL | |
uses: ./.github/workflows/codeql.yml |