name: CI # Signage builds, tests, and runs only inside an Ekklesia workspace, so every job first assembles it # into the platform commit pinned in ci/platform.env (ci/assemble.sh) and installs that workspace # with --frozen-lockfile from ci/pnpm-lock.yaml. # # The same trust rules as the platform's own CI (docs/development/security.md there): # * every action is pinned by a full commit SHA; # * every checkout sets `persist-credentials: false`, and nothing in this workflow pushes; # * no repository, organization, or instance secret is referenced; # * there is no `pull_request_target`; # * the self-hosted runner executes trusted, reviewed code only. # # The server is Gitea 1.24, which ignores `permissions`, `concurrency`, and `timeout-minutes` # (https://docs.gitea.com/1.24/usage/actions/comparison). They are declared so the workflow is already # correct on a release that honours them; on 1.24 they bound nothing, and `permissions` does not # restrict the job token. on: pull_request: push: branches: - main permissions: contents: read concurrency: group: ci-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: lint: name: lint runs-on: ubuntu-latest timeout-minutes: 15 steps: - name: Check out repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: # Nothing here pushes, so the job token is never needed after checkout and must not be left # in .git/config for a later step to read. persist-credentials: false - name: Assemble Signage into the pinned platform run: bash ci/assemble.sh - name: Set up Node.js at the platform's version uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: build/workspace/.node-version - name: Install the assembled workspace (frozen lockfile) working-directory: build/workspace run: | corepack enable corepack install pnpm install --frozen-lockfile - name: Lint working-directory: build/workspace run: pnpm --filter @ekklesia/signage lint - name: Check that CI cleans up every stack it starts run: bash ci/check-cleanup.sh typecheck: name: typecheck runs-on: ubuntu-latest timeout-minutes: 15 steps: - name: Check out repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: # Nothing here pushes, so the job token is never needed after checkout and must not be left # in .git/config for a later step to read. persist-credentials: false - name: Assemble Signage into the pinned platform run: bash ci/assemble.sh - name: Set up Node.js at the platform's version uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: build/workspace/.node-version - name: Install the assembled workspace (frozen lockfile) working-directory: build/workspace run: | corepack enable corepack install pnpm install --frozen-lockfile - name: Build the platform packages Signage depends on working-directory: build/workspace run: pnpm exec turbo run build --filter='@ekklesia/signage^...' - name: Typecheck the server, browser, and browser-test projects working-directory: build/workspace run: pnpm --filter @ekklesia/signage typecheck test: name: test runs-on: ubuntu-latest timeout-minutes: 15 steps: - name: Check out repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: # Nothing here pushes, so the job token is never needed after checkout and must not be left # in .git/config for a later step to read. persist-credentials: false - name: Assemble Signage into the pinned platform run: bash ci/assemble.sh - name: Set up Node.js at the platform's version uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: build/workspace/.node-version - name: Install the assembled workspace (frozen lockfile) working-directory: build/workspace run: | corepack enable corepack install pnpm install --frozen-lockfile - name: Build the platform packages Signage depends on working-directory: build/workspace run: pnpm exec turbo run build --filter='@ekklesia/signage^...' - name: Unit, browser, and display contract tests working-directory: build/workspace run: pnpm --filter @ekklesia/signage test build: name: build runs-on: ubuntu-latest timeout-minutes: 20 steps: - name: Check out repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: # Nothing here pushes, so the job token is never needed after checkout and must not be left # in .git/config for a later step to read. persist-credentials: false - name: Assemble Signage into the pinned platform run: bash ci/assemble.sh - name: Set up Node.js at the platform's version uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: build/workspace/.node-version - name: Install the assembled workspace (frozen lockfile) working-directory: build/workspace run: | corepack enable corepack install pnpm install --frozen-lockfile # The same gates the platform's image build runs against exactly this module set: its boundary # rules (which apply to modules), the manifest, and the migrations. - name: Platform gates (boundaries, module manifest, migrations) working-directory: build/workspace run: | pnpm boundaries pnpm modules:validate pnpm migrations:validate - name: Build Signage and the platform it depends on working-directory: build/workspace run: pnpm exec turbo run build --filter='@ekklesia/signage...' # Signage inside Ekklesia, end to end, in a real browser: the platform's own Dockerfile builds the # deployment image with Signage in it, and the platform's split-topology deployment smoke runs # against it, pairing a kiosk display and running the scenarios in ci/display-scenarios. A # disposable database and object store with generated secrets; nothing is pushed or logged in to. integration: name: integration needs: - test - build runs-on: ubuntu-latest timeout-minutes: 45 env: DOCKER_BUILDKIT: "1" # Names this job's stacks, so its final step removes exactly these (the platform's # scripts/lib/ci-project.sh). EKKLESIA_CI_JOB_KEY: signage-integration steps: - name: Check out repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Assemble Signage into the pinned platform run: bash ci/assemble.sh # A job the runner killed (cancelled, or past the runner's own time limit) never ran its # cleanup. Anything a CI job left on this shared daemon more than three hours ago goes first. - name: Sweep stale CI stacks from the runner run: bash build/workspace/scripts/ci-sweep.sh --stale - name: Build the image and run the display scenarios run: bash ci/integration.sh # Whatever happened above, this job's own stacks do not outlive it. If assembly failed, nothing # was started. - name: Remove this job's CI stacks if: always() run: | if [ -f build/workspace/scripts/ci-sweep.sh ]; then bash build/workspace/scripts/ci-sweep.sh --job fi