name: CI # Signage is a standalone repository: every job installs it with --frozen-lockfile from its own # pnpm-lock.yaml and takes Ekklesia's module-development packages (@ekklesia/*) from Ekklesia's # public package registry (.npmrc; platform ADRs 0053 and 0054). Only the integration job fetches # Core source: one immutable commit through the pinned Gitea pull ref in ci/platform.env, used as the # generic deployment harness and image source, never as a workspace dependency. # # 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.27, which honours `concurrency` cancellation; `permissions` and # `timeout-minutes` are declared so the workflow is correct wherever they are enforced. 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: Set up Node.js at the repository's version uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: .node-version # pnpm at exactly the `packageManager` version, and @ekklesia/* from the public registry named in # .npmrc: no token, and no Ekklesia checkout. - name: Install (frozen lockfile) run: | corepack enable corepack install pnpm install --frozen-lockfile - name: Lint run: pnpm 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: Set up Node.js at the repository's version uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: .node-version # pnpm at exactly the `packageManager` version, and @ekklesia/* from the public registry named in # .npmrc: no token, and no Ekklesia checkout. - name: Install (frozen lockfile) run: | corepack enable corepack install pnpm install --frozen-lockfile - name: Typecheck the server, browser, and browser-test projects run: pnpm 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: Set up Node.js at the repository's version uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: .node-version # pnpm at exactly the `packageManager` version, and @ekklesia/* from the public registry named in # .npmrc: no token, and no Ekklesia checkout. - name: Install (frozen lockfile) run: | corepack enable corepack install pnpm install --frozen-lockfile - name: Unit, browser, and display contract tests run: pnpm 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: Set up Node.js at the repository's version uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: .node-version # pnpm at exactly the `packageManager` version, and @ekklesia/* from the public registry named in # .npmrc: no token, and no Ekklesia checkout. - name: Install (frozen lockfile) run: | corepack enable corepack install pnpm install --frozen-lockfile - name: Build the server and both browser artifacts run: pnpm build # The built package and its migrations, read the way the platform reads them, with only the # published SDK parsers (scripts/validate-module.mjs says what only Ekklesia itself can check). - name: Validate the built module and its migrations run: pnpm validate # The real linux-x64-glibc Signage Module Package inside Ekklesia, end to end. The pinned platform # builds one generic image with no bundled module source, verifies and installs Signage into # persistent module storage, applies its migrations, and drives its split-origin Dashboard and # kiosk display in real browsers. It then checks process restart, container recreation, lifecycle # disable/re-enable, removal, and reinstall against the same database and package. 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: Set up Node.js at the repository's version uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: .node-version - name: Install (frozen lockfile) run: | corepack enable corepack install pnpm install --frozen-lockfile - name: Fetch the pinned Ekklesia integration harness run: bash ci/fetch-platform.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/platform/scripts/ci-sweep.sh --stale - name: Build, install, and run the external Signage package run: bash ci/integration.sh # Whatever happened above, this job's own stacks do not outlive it. If the first step failed, # nothing was started. - name: Remove this job's CI stacks if: always() run: | if [ -f build/platform/scripts/ci-sweep.sh ]; then bash build/platform/scripts/ci-sweep.sh --job fi