diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b8ee86d..e798069 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,11 +25,17 @@ jobs: include: - target: linux-x64 os: ubuntu-latest + task: ci - target: linux-arm64 os: ubuntu-24.04-arm + task: ci - target: macos-arm64 os: macos-14 + task: ci + - target: linux-x64-ubsan + os: ubuntu-latest + task: ci-ubsan steps: - uses: actions/checkout@v6 - uses: jdx/mise-action@v3 - - run: mise run ci + - run: mise run ${{ matrix.task }} diff --git a/README.md b/README.md index 3dc9fe6..6ec24f8 100644 --- a/README.md +++ b/README.md @@ -184,5 +184,6 @@ The package has four layers: - Run: `mise run ci` - `.github/workflows/ci.yml` runs the same task. Without mise, run the steps in "Native Build" above. +- UBSan build of the addon: `mise run ci-ubsan`. CI runs it as the `linux-x64-ubsan` row. - Packaged-install journeys: [`.agents/skills/verify-libghostty-vt-node/SKILL.md`](https://github.com/coder/libghostty-vt-node/blob/main/.agents/skills/verify-libghostty-vt-node/SKILL.md) - TLA+ model of the native lifecycle: [`.agents/skills/verify-native-lifecycle/SKILL.md`](https://github.com/coder/libghostty-vt-node/blob/main/.agents/skills/verify-native-lifecycle/SKILL.md) diff --git a/mise.toml b/mise.toml index ddfd277..7eba29e 100644 --- a/mise.toml +++ b/mise.toml @@ -14,6 +14,18 @@ run = [ "npm run smoke", ] +[tasks.ci-ubsan] +description = "Build the native addon with UBSan, then run tests and smoke so undefined behavior aborts the run." +run = [ + "npm ci", + "npm run build:libghostty", + # GCC's "undefined" group leaves out float-cast-overflow. + "CXXFLAGS=\"-fsanitize=undefined,float-cast-overflow -fno-sanitize-recover=all\" LDFLAGS=\"-fsanitize=undefined,float-cast-overflow\" npm run build:native", + "nm -u $(find build/Release -name '*.o') | grep -c '__ubsan_handle_.*_abort' > /dev/null || { echo \"error: the addon was built without UBSan\" >&2; exit 1; }", + "npm test", + "npm run smoke", +] + [tasks.release-prebuilds] description = "Build and verify npm-bundled Node-API prebuild artifacts." run = [ diff --git a/native/README.md b/native/README.md index 37f130c..cd522dc 100644 --- a/native/README.md +++ b/native/README.md @@ -67,5 +67,6 @@ C++ declarations: - Run (after `npm ci`): `npm run build:libghostty && npm run build:native && npm test` - Every native test skips when the addon does not load (`test/native-support.ts:nativeSupport`), so check the test output for skips. +- `mise run ci-ubsan` builds the addon with UBSan (Linux, GCC), then runs the tests and smoke. Undefined behavior aborts the run. The task also fails when the addon's object files contain no UBSan checks, which means the flags did not reach g++ (`mise.toml:tasks.ci-ubsan`). - `test/workers.test.ts` checks the per-environment state in child processes with `worker_threads`. `test/terminal.test.ts` covers `feed`, `snapshot`, `resize`, `dispose`, and the `RangeError` cases of the `createTerminal` checks in the addon. No vitest test covers `formatPlain`, `formatHtml`, `includeScrollback`, the cell style fields, or the typed-array errors. - For changes to `TerminalWrap` or `InitAll`, also run the TLA+ lifecycle model: [`.agents/skills/verify-native-lifecycle/SKILL.md`](https://github.com/coder/libghostty-vt-node/blob/main/.agents/skills/verify-native-lifecycle/SKILL.md).