mirror of
https://github.com/zadam/trilium.git
synced 2026-09-12 19:50:20 +05:00
Vitest 5 handed the webdriverio provider to community maintenance, and no
stable 5.x of `@vitest/browser-webdriverio` was ever published — npm `latest`
is still 4.1.11, with only a 5.0.0-rc.1 from before vitest 5.0.0 shipped.
Pairing that v4 provider with `@vitest/browser` 5 kills the suite at startup:
TypeError: Cannot read properties of undefined (reading 'project')
at createBrowserServer (@vitest/browser/dist/index.js:7900:26)
`@vitest/browser-playwright` 5.0.0 is stable and first-party, and Playwright
1.62.1 is already here for the e2e suites, so the browser toolchain costs
nothing new. Only two of the 129 specs touch provider-visible API at all, both
through the provider-agnostic `userEvent`.
Playwright drives the browser over CDP with no separate driver, so the
chromedriver half of the NixOS workaround goes away: the dev shell keeps
`pkgs.chromium` and `CHROME_BIN`, which now reaches the provider as
`launchOptions.executablePath`. CI installs the browser in a step of its own
rather than inside the test step, whose 15-minute cap exists to catch a browser
session that never starts and should not also have to cover a 190 MB download.
Two specs depended on webdriverio behaviour and are fixed rather than skipped:
- The token-cost assertion read `1.234` where it wanted `1,234`.
`toLocaleString()` takes the browser's locale, and Playwright inherits the
host's where the old Chrome defaulted to en-US. Pinning `contextOptions.locale`
keeps the suite from depending on the developer's machine.
- The format painter's drag-selection selected nothing. Playwright's
`dragAndDrop` turns on drag interception, so the press reaches the page as an
HTML5 drag intent instead of selecting text. Driving the press, move and
release over CDP restores what the test is actually for: proving a *native*
pointer interaction has updated the model selection by the time the `mouseup`
listener runs.
Vitest 5 also moved failure screenshots from `.vitest-attachments` to
`.vitest`, which needs ignoring.
Verified: 127 files / 1626 tests green, coverage 99.91/99.54/100/99.98 against
the 99.5 gate. The Nix path is unexercised — `executablePath` is ordinary
Playwright, but it was not run from a dev shell.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
640 lines
24 KiB
YAML
640 lines
24 KiB
YAML
name: Dev
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
- standalone
|
|
- "release/*"
|
|
pull_request:
|
|
branches:
|
|
- main
|
|
- standalone
|
|
- "release/*"
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
env:
|
|
GHCR_REGISTRY: ghcr.io
|
|
DOCKERHUB_REGISTRY: docker.io
|
|
IMAGE_NAME: ${{ github.repository}}
|
|
TEST_TAG: ${{ github.repository}}:test
|
|
|
|
permissions:
|
|
pull-requests: write # for PR comments
|
|
|
|
jobs:
|
|
# Decides which of the two heavyweight suites a given push/PR can actually
|
|
# affect. Both suites also run the shared trilium-core spec set, so anything
|
|
# under that package (or the workspace roots) has to trigger both.
|
|
changes:
|
|
name: Detect affected suites
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
server: ${{ steps.filter.outputs.server }}
|
|
standalone: ${{ steps.filter.outputs.standalone }}
|
|
ckeditor5: ${{ steps.filter.outputs.ckeditor5 }}
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3
|
|
id: filter
|
|
with:
|
|
filters: |
|
|
# Workspace-wide inputs: these change how anything installs or builds.
|
|
# Kept as its own anchor so the ckeditor5 filter can pick it up
|
|
# without inheriting the much wider trilium-core closure below.
|
|
workspace: &workspace
|
|
- 'pnpm-lock.yaml'
|
|
- 'pnpm-workspace.yaml'
|
|
- 'package.json'
|
|
- 'tsconfig*.json'
|
|
- '.npmrc'
|
|
- '.nvmrc'
|
|
# pnpm-workspace.yaml patches @excalidraw/excalidraw, so editing a
|
|
# patch changes what actually gets installed.
|
|
- 'patches/**'
|
|
- '.github/workflows/dev.yml'
|
|
# apps/server and apps/standalone each include
|
|
# ../../packages/trilium-core/src/**/*.spec.ts in their vitest
|
|
# `include` — the standalone suite exists precisely to re-run that
|
|
# set under happy-dom + sql.js — so both need core and everything
|
|
# core pulls in. turndown-plugin-gfm is here because trilium-core
|
|
# depends on it; it is not a direct dependency of either app.
|
|
core: &core
|
|
- 'packages/trilium-core/**'
|
|
- 'packages/commons/**'
|
|
- 'packages/turndown-plugin-gfm/**'
|
|
- 'packages/trilium-backup-container/**'
|
|
- 'packages/highlightjs/**'
|
|
server:
|
|
- *workspace
|
|
- *core
|
|
- 'apps/server/**'
|
|
# Widest closure in the repo: apps/standalone depends on eight
|
|
# workspace packages. It reaches into apps/client too, but only
|
|
# through ../../client/src/index.js, which main.spec.ts mocks — no
|
|
# client code executes in this suite, so apps/client is left out.
|
|
standalone:
|
|
- *workspace
|
|
- *core
|
|
- 'apps/standalone/**'
|
|
- 'packages/ckeditor5/**'
|
|
- 'packages/codemirror/**'
|
|
- 'packages/share-theme/**'
|
|
- 'packages/splitjs/**'
|
|
# Narrowest closure of the three: the aggregate depends only on
|
|
# commons. Note this filter does not guard the t()/translation-key
|
|
# contract — apps/client/src/services/i18n.spec.ts reads
|
|
# packages/ckeditor5/src off disk to enforce that, and it runs in
|
|
# test_dev, which is ungated.
|
|
ckeditor5:
|
|
- *workspace
|
|
- 'packages/ckeditor5/**'
|
|
- 'packages/commons/**'
|
|
|
|
test_dev:
|
|
name: Test development
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout the repository
|
|
uses: actions/checkout@v7
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
|
|
- name: Set up node & dependencies
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24
|
|
cache: "pnpm"
|
|
- run: pnpm install --frozen-lockfile
|
|
|
|
- name: Typecheck
|
|
run: pnpm typecheck
|
|
|
|
- name: Run the repo-script tests
|
|
run: pnpm scripts:test
|
|
|
|
- name: Run the client-side tests
|
|
id: test-client
|
|
run: pnpm run --filter=client test --coverage
|
|
|
|
- name: Upload client test report
|
|
uses: actions/upload-artifact@v7
|
|
if: always()
|
|
with:
|
|
name: client-test-report
|
|
path: apps/client/test-output/vitest/html/
|
|
retention-days: 30
|
|
|
|
- name: Upload client coverage to Codecov
|
|
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
|
if: ${{ !cancelled() && steps.test-client.outcome == 'success' }}
|
|
with:
|
|
files: apps/client/test-output/vitest/coverage/lcov.info
|
|
flags: client
|
|
disable_search: true
|
|
fail_ci_if_error: false
|
|
|
|
- name: Upload client test results to Codecov
|
|
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
|
if: ${{ !cancelled() && steps.test-client.outcome != 'skipped' }}
|
|
with:
|
|
report_type: test_results
|
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
files: apps/client/test-output/vitest/junit.xml
|
|
flags: client
|
|
disable_search: true
|
|
fail_ci_if_error: false
|
|
|
|
- name: Run the desktop tests
|
|
id: test-desktop
|
|
run: pnpm run --filter=desktop test --coverage
|
|
|
|
- name: Upload desktop coverage to Codecov
|
|
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
|
if: ${{ !cancelled() && steps.test-desktop.outcome == 'success' }}
|
|
with:
|
|
files: apps/desktop/test-output/vitest/coverage/lcov.info
|
|
flags: desktop
|
|
disable_search: true
|
|
fail_ci_if_error: false
|
|
|
|
- name: Upload desktop test results to Codecov
|
|
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
|
if: ${{ !cancelled() && steps.test-desktop.outcome != 'skipped' }}
|
|
with:
|
|
report_type: test_results
|
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
files: apps/desktop/test-output/vitest/junit.xml
|
|
flags: desktop
|
|
disable_search: true
|
|
fail_ci_if_error: false
|
|
|
|
- name: Run the commons tests
|
|
id: test-commons
|
|
run: pnpm run --filter=commons test --coverage
|
|
|
|
- name: Upload commons coverage to Codecov
|
|
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
|
if: ${{ !cancelled() && steps.test-commons.outcome == 'success' }}
|
|
with:
|
|
files: packages/commons/test-output/vitest/coverage/lcov.info
|
|
flags: commons
|
|
disable_search: true
|
|
fail_ci_if_error: false
|
|
|
|
- name: Upload commons test results to Codecov
|
|
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
|
if: ${{ !cancelled() && steps.test-commons.outcome != 'skipped' }}
|
|
with:
|
|
report_type: test_results
|
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
files: packages/commons/test-output/vitest/junit.xml
|
|
flags: commons
|
|
disable_search: true
|
|
fail_ci_if_error: false
|
|
|
|
- name: Run the codemirror tests
|
|
id: test-codemirror
|
|
run: pnpm run --filter=codemirror test --coverage
|
|
|
|
- name: Upload codemirror coverage to Codecov
|
|
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
|
if: ${{ !cancelled() && steps.test-codemirror.outcome == 'success' }}
|
|
with:
|
|
files: packages/codemirror/test-output/vitest/coverage/lcov.info
|
|
flags: codemirror
|
|
disable_search: true
|
|
fail_ci_if_error: false
|
|
|
|
- name: Upload codemirror test results to Codecov
|
|
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
|
if: ${{ !cancelled() && steps.test-codemirror.outcome != 'skipped' }}
|
|
with:
|
|
report_type: test_results
|
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
files: packages/codemirror/test-output/vitest/junit.xml
|
|
flags: codemirror
|
|
disable_search: true
|
|
fail_ci_if_error: false
|
|
|
|
- name: Run the highlightjs tests
|
|
id: test-highlightjs
|
|
run: pnpm run --filter=highlightjs test --coverage
|
|
|
|
- name: Upload highlightjs coverage to Codecov
|
|
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
|
if: ${{ !cancelled() && steps.test-highlightjs.outcome == 'success' }}
|
|
with:
|
|
files: packages/highlightjs/test-output/vitest/coverage/lcov.info
|
|
flags: highlightjs
|
|
disable_search: true
|
|
fail_ci_if_error: false
|
|
|
|
- name: Upload highlightjs test results to Codecov
|
|
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
|
if: ${{ !cancelled() && steps.test-highlightjs.outcome != 'skipped' }}
|
|
with:
|
|
report_type: test_results
|
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
files: packages/highlightjs/test-output/vitest/junit.xml
|
|
flags: highlightjs
|
|
disable_search: true
|
|
fail_ci_if_error: false
|
|
|
|
- name: Run the pdfjs-viewer tests
|
|
id: test-pdfjs-viewer
|
|
run: pnpm run --filter=pdfjs-viewer test --coverage
|
|
|
|
- name: Upload pdfjs-viewer coverage to Codecov
|
|
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
|
if: ${{ !cancelled() && steps.test-pdfjs-viewer.outcome == 'success' }}
|
|
with:
|
|
files: packages/pdfjs-viewer/test-output/vitest/coverage/lcov.info
|
|
flags: pdfjs-viewer
|
|
disable_search: true
|
|
fail_ci_if_error: false
|
|
|
|
- name: Upload pdfjs-viewer test results to Codecov
|
|
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
|
if: ${{ !cancelled() && steps.test-pdfjs-viewer.outcome != 'skipped' }}
|
|
with:
|
|
report_type: test_results
|
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
files: packages/pdfjs-viewer/test-output/vitest/junit.xml
|
|
flags: pdfjs-viewer
|
|
disable_search: true
|
|
fail_ci_if_error: false
|
|
|
|
- name: Run the rest of the tests
|
|
run: pnpm run --filter=\!client --filter=\!standalone --filter=\!server --filter=\!desktop --filter=\!commons --filter=\!ckeditor5 --filter=\!codemirror --filter=\!highlightjs --filter=\!pdfjs-viewer test
|
|
|
|
# The two suites below are split out of test_dev so they run concurrently with
|
|
# it (and each other) rather than queueing behind the client/package suites.
|
|
#
|
|
# Each job always starts and gates its *steps* on the filter, rather than
|
|
# carrying a job-level `if:`. A job skipped at the job level reports no result
|
|
# to a branch-protection required check, and propagates the skip through
|
|
# `needs:` to build_docker. Gating the steps keeps the job green and the
|
|
# dependency graph intact on a run that touches neither suite; the cost is one
|
|
# checkout on an unaffected run.
|
|
test_server:
|
|
name: Test server
|
|
runs-on: ubuntu-latest
|
|
needs: changes
|
|
env:
|
|
AFFECTED: ${{ needs.changes.outputs.server }}
|
|
steps:
|
|
- name: Checkout the repository
|
|
if: env.AFFECTED == 'true'
|
|
uses: actions/checkout@v7
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
|
|
if: env.AFFECTED == 'true'
|
|
- name: Set up node & dependencies
|
|
if: env.AFFECTED == 'true'
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24
|
|
cache: "pnpm"
|
|
- name: Install dependencies
|
|
if: env.AFFECTED == 'true'
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
- name: Run the server-side tests
|
|
id: test-server
|
|
if: env.AFFECTED == 'true'
|
|
run: pnpm run --filter=server test --coverage
|
|
|
|
- name: Upload server test report
|
|
uses: actions/upload-artifact@v7
|
|
if: ${{ !cancelled() && steps.test-server.outcome != 'skipped' }}
|
|
with:
|
|
name: server-test-report
|
|
path: apps/server/test-output/vitest/html/
|
|
retention-days: 30
|
|
|
|
- name: Upload server coverage to Codecov
|
|
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
|
if: ${{ !cancelled() && steps.test-server.outcome == 'success' }}
|
|
with:
|
|
files: apps/server/test-output/vitest/coverage/lcov.info
|
|
flags: server
|
|
disable_search: true
|
|
fail_ci_if_error: false
|
|
|
|
- name: Upload server test results to Codecov
|
|
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
|
if: ${{ !cancelled() && steps.test-server.outcome != 'skipped' }}
|
|
with:
|
|
report_type: test_results
|
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
files: apps/server/test-output/vitest/junit.xml
|
|
flags: server
|
|
disable_search: true
|
|
fail_ci_if_error: false
|
|
|
|
test_standalone:
|
|
name: Test standalone
|
|
runs-on: ubuntu-latest
|
|
needs: changes
|
|
env:
|
|
AFFECTED: ${{ needs.changes.outputs.standalone }}
|
|
steps:
|
|
- name: Checkout the repository
|
|
if: env.AFFECTED == 'true'
|
|
uses: actions/checkout@v7
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
|
|
if: env.AFFECTED == 'true'
|
|
- name: Set up node & dependencies
|
|
if: env.AFFECTED == 'true'
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24
|
|
cache: "pnpm"
|
|
- name: Install dependencies
|
|
if: env.AFFECTED == 'true'
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
- name: Run the standalone tests
|
|
id: test-standalone
|
|
if: env.AFFECTED == 'true'
|
|
# Runs the same trilium-core spec set as the server suite, but in
|
|
# happy-dom + sql.js WASM via BrowserSqlProvider (see
|
|
# apps/standalone/src/test_setup.ts). Catches differences
|
|
# between the Node-side and browser-side runtimes.
|
|
run: pnpm run --filter=standalone test --coverage
|
|
|
|
- name: Upload standalone coverage to Codecov
|
|
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
|
if: ${{ !cancelled() && steps.test-standalone.outcome == 'success' }}
|
|
with:
|
|
files: apps/standalone/test-output/vitest/coverage/lcov.info
|
|
flags: standalone
|
|
disable_search: true
|
|
fail_ci_if_error: false
|
|
|
|
- name: Upload standalone test results to Codecov
|
|
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
|
if: ${{ !cancelled() && steps.test-standalone.outcome != 'skipped' }}
|
|
with:
|
|
report_type: test_results
|
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
files: apps/standalone/test-output/vitest/junit.xml
|
|
flags: standalone
|
|
disable_search: true
|
|
fail_ci_if_error: false
|
|
|
|
# The two shards the suite was already split into now run as separate jobs
|
|
# rather than back-to-back in one step, and a merge job evaluates the coverage
|
|
# gate over the combined blob reports. Sharding exists for renderer memory, not
|
|
# speed (see the comment on the test step); running the shards concurrently is
|
|
# what makes it also a speedup.
|
|
test_ckeditor5:
|
|
name: Test CKEditor 5 (shard ${{ matrix.shard }})
|
|
runs-on: ubuntu-latest
|
|
needs: changes
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
shard: [1, 2]
|
|
env:
|
|
AFFECTED: ${{ needs.changes.outputs.ckeditor5 }}
|
|
steps:
|
|
- name: Checkout the repository
|
|
if: env.AFFECTED == 'true'
|
|
uses: actions/checkout@v7
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
|
|
if: env.AFFECTED == 'true'
|
|
- name: Set up node & dependencies
|
|
if: env.AFFECTED == 'true'
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24
|
|
cache: "pnpm"
|
|
- name: Install dependencies
|
|
if: env.AFFECTED == 'true'
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
- name: Install Playwright's Chromium
|
|
if: env.AFFECTED == 'true'
|
|
run: pnpm exec playwright install --with-deps chromium
|
|
|
|
- name: Run the CKEditor 5 aggregate tests
|
|
id: test-ckeditor5
|
|
if: env.AFFECTED == 'true'
|
|
# The suite drives a real headless Chromium through Playwright. When the browser session
|
|
# fails to start, vitest waits on it rather than erroring, so cap the step instead of
|
|
# letting it sit until the job's default timeout.
|
|
timeout-minutes: 15
|
|
run: |
|
|
# Browser mode keeps one page for the whole run, and v8 coverage data accumulates in it:
|
|
# measured locally, the heap reaches ~850MB by the 100th spec file with --coverage against
|
|
# ~240MB without it. That is where a CI runner's renderer gives out — the session either
|
|
# drops mid-run or stops responding. Each shard is ~60 files, peaking around 500MB. The
|
|
# thresholds are zeroed here and evaluated once over the merged report instead, so the
|
|
# gate still covers the whole suite rather than each shard separately.
|
|
pnpm run --filter=ckeditor5 test --shard=${{ matrix.shard }}/${{ strategy.job-total }} \
|
|
--reporter=blob --coverage \
|
|
--coverage.thresholds.lines=0 --coverage.thresholds.functions=0 \
|
|
--coverage.thresholds.branches=0 --coverage.thresholds.statements=0
|
|
|
|
# Vitest names blobs `.vitest-reports/blob-<index>-<count>.json`, so the two
|
|
# shards produce distinct filenames and merge-multiple cannot clobber them.
|
|
# That directory is dot-prefixed, and upload-artifact skips hidden paths
|
|
# unless told otherwise — without include-hidden-files it silently matches
|
|
# nothing.
|
|
- name: Upload the shard blob report
|
|
uses: actions/upload-artifact@v7
|
|
if: ${{ !cancelled() && steps.test-ckeditor5.outcome == 'success' }}
|
|
with:
|
|
name: ckeditor5-blob-${{ matrix.shard }}
|
|
path: packages/ckeditor5/.vitest-reports/
|
|
include-hidden-files: true
|
|
if-no-files-found: error
|
|
retention-days: 1
|
|
|
|
test_ckeditor5_merge:
|
|
name: CKEditor 5 coverage gate
|
|
runs-on: ubuntu-latest
|
|
needs:
|
|
- changes
|
|
- test_ckeditor5
|
|
env:
|
|
AFFECTED: ${{ needs.changes.outputs.ckeditor5 }}
|
|
steps:
|
|
- name: Checkout the repository
|
|
if: env.AFFECTED == 'true'
|
|
uses: actions/checkout@v7
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
|
|
if: env.AFFECTED == 'true'
|
|
- name: Set up node & dependencies
|
|
if: env.AFFECTED == 'true'
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24
|
|
cache: "pnpm"
|
|
- name: Install dependencies
|
|
if: env.AFFECTED == 'true'
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
- name: Download the shard blob reports
|
|
if: env.AFFECTED == 'true'
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
pattern: ckeditor5-blob-*
|
|
merge-multiple: true
|
|
path: packages/ckeditor5/.vitest-reports
|
|
|
|
# Re-runs no tests; it replays the blobs to produce the junit and lcov
|
|
# output and to evaluate the package's real coverage thresholds over the
|
|
# whole suite.
|
|
- name: Merge the shard reports and evaluate the coverage gate
|
|
id: test-ckeditor5
|
|
if: env.AFFECTED == 'true'
|
|
run: pnpm run --filter=ckeditor5 test --mergeReports --coverage
|
|
|
|
- name: Upload ckeditor5 coverage to Codecov
|
|
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
|
if: ${{ !cancelled() && steps.test-ckeditor5.outcome == 'success' }}
|
|
with:
|
|
files: packages/ckeditor5/test-output/vitest/coverage/lcov.info
|
|
flags: ckeditor5
|
|
disable_search: true
|
|
fail_ci_if_error: false
|
|
|
|
- name: Upload ckeditor5 test results to Codecov
|
|
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
|
if: ${{ !cancelled() && steps.test-ckeditor5.outcome != 'skipped' }}
|
|
with:
|
|
report_type: test_results
|
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
files: packages/ckeditor5/test-output/vitest/junit.xml
|
|
flags: ckeditor5
|
|
disable_search: true
|
|
fail_ci_if_error: false
|
|
|
|
# Deliberately ungated: this validates that the client and server build and
|
|
# that the image assembles, none of which depends on a test outcome. Waiting
|
|
# for the suites put ~4m of Docker work in series behind the slowest of them
|
|
# for no signal. It now runs alongside them, so the workflow finishes with the
|
|
# longest test job rather than after it.
|
|
#
|
|
# The trade is that a push whose tests fail still spends runner time building
|
|
# images. That is the accepted cost of taking the Docker work off the critical
|
|
# path; the concurrency group above still cancels superseded runs.
|
|
build_docker:
|
|
name: Build Docker image
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
persist-credentials: false
|
|
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
|
|
- name: Set up node & dependencies
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24
|
|
cache: "pnpm"
|
|
- name: Install dependencies
|
|
run: pnpm install --frozen-lockfile
|
|
- name: Update build info
|
|
run: pnpm run chore:update-build-info
|
|
- name: Trigger client build
|
|
run: pnpm client:build
|
|
env:
|
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
- name: Trigger server build
|
|
run: pnpm run server:build
|
|
- uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
|
|
- uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
|
|
with:
|
|
context: apps/server
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
test_docker:
|
|
name: Check Docker build
|
|
runs-on: ubuntu-latest
|
|
# Kept: build_docker populates the type=gha buildx cache this job reads. The
|
|
# two together (~4m) still finish well inside the slowest test job, so
|
|
# breaking the chain would buy nothing and would leave both jobs racing to
|
|
# write the same cache.
|
|
needs:
|
|
- build_docker
|
|
strategy:
|
|
matrix:
|
|
include:
|
|
- dockerfile: Dockerfile.alpine
|
|
- dockerfile: Dockerfile
|
|
steps:
|
|
- name: Checkout the repository
|
|
uses: actions/checkout@v7
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
|
|
- name: Set up node & dependencies
|
|
uses: actions/setup-node@v7
|
|
with:
|
|
node-version: 24
|
|
cache: "pnpm"
|
|
- name: Install dependencies
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
- name: Update build info
|
|
run: pnpm run chore:update-build-info
|
|
- name: Trigger build
|
|
run: pnpm server:build
|
|
|
|
- name: Set IMAGE_NAME to lowercase
|
|
run: echo "IMAGE_NAME=${IMAGE_NAME,,}" >> $GITHUB_ENV
|
|
- name: Set TEST_TAG to lowercase
|
|
run: echo "TEST_TAG=${TEST_TAG,,}" >> $GITHUB_ENV
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
|
|
|
|
- name: Build and export to Docker
|
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
|
|
with:
|
|
context: apps/server
|
|
file: apps/server/${{ matrix.dockerfile }}
|
|
load: true
|
|
tags: ${{ env.TEST_TAG }}
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
|
|
- name: Validate container run output
|
|
run: |
|
|
CONTAINER_ID=$(docker run -d --log-driver=journald --rm --name trilium_local ${{ env.TEST_TAG }})
|
|
echo "Container ID: $CONTAINER_ID"
|
|
|
|
- name: Wait for the healthchecks to pass
|
|
uses: stringbean/docker-healthcheck-action@a958d329225ccbd485766815734e01c335e62bd4 # v3.0.0
|
|
with:
|
|
container: trilium_local
|
|
wait-time: 50
|
|
require-status: running
|
|
require-healthy: true
|
|
|
|
# Print the entire log of the container thus far, regardless if the healthcheck failed or succeeded
|
|
- name: Print entire log
|
|
if: always()
|
|
run: journalctl -u docker CONTAINER_NAME=trilium_local --no-pager
|