ci: run BATS test suite on push and PR (#520)

* ci: run BATS test suite on push and PR

The /tests/ directory has 186 BATS tests
(launcher-common, launcher-xrdp-detection, and four
cowork-*.bats files) but no workflow ever invoked `bats`
— the entire suite was effectively inert.

A regression in launcher-common.sh or
cowork-vm-service.js would not fail any check,
including the BATS suite added by PR #395.

Add a standalone tests.yml workflow that:
- installs bats + nodejs
- runs `bats tests/*.bats`
- executes on every PR
- executes on pushes to main

Push triggers are path-filtered to:
- tests/
- scripts/
- .github/workflows/tests.yml

PR triggers remain unfiltered so required-check
behaviour stays predictable.

Kept this standalone rather than extending
test-artifacts.yml so unit tests run in seconds
instead of waiting for full artifact builds.

This can be promoted to a build gate later once
it proves stable in CI.

CODEOWNERS
- adds /.github/workflows/tests.yml under @sabiut
- keeps /tests/cowork-*.bats ownership with @RayCharlizard

This PR only enables CI coverage for existing tests
and does not modify cowork test logic.

* fix(tests): unset XDG_CONFIG_HOME in cowork-bwrap-config setup

The "doctor: reports custom bwrap mounts" and "doctor: warns
about disabled critical mount /usr" tests failed in CI but
passed locally.

Root cause:

- _doctor_check_bwrap_mounts in scripts/doctor.sh resolves
  the config dir via ${XDG_CONFIG_HOME:-$HOME/.config}/Claude
- The test setup() only sandboxes HOME via TEST_TMP
- GitHub Actions runners export XDG_CONFIG_HOME ambient
- Function reads the runner's real config dir, not the test
  fixture, and silently emits no output
- Assertions on /opt/tools, WARN, etc. fail

Surfaced by PR #520 wiring BATS into CI for the first time;
the bug existed before but was hidden by the suite never
running.

Fix: unset XDG_CONFIG_HOME in setup() so the function falls
back to \$HOME/.config (which is sandboxed). Comment in the
file documents why HOME alone is insufficient.

Verified: 186/186 pass with XDG_CONFIG_HOME set ambient
(reproduces CI env).
This commit is contained in:
Sum Abiut
2026-04-27 11:48:21 +11:00
committed by GitHub
parent 7f4cf49431
commit 0217a2c0e1
3 changed files with 52 additions and 0 deletions

1
.github/CODEOWNERS vendored
View File

@@ -73,6 +73,7 @@
/scripts/doctor.sh @sabiut
/.github/workflows/test-artifacts.yml @sabiut
/.github/workflows/test-flags.yml @sabiut
/.github/workflows/tests.yml @sabiut
# Shared review — either owner can approve.
# TROUBLESHOOTING is mostly the --doctor user-facing guide; lint

45
.github/workflows/tests.yml vendored Normal file
View File

@@ -0,0 +1,45 @@
name: BATS Tests
run-name: |
BATS: ${{
github.event_name == 'pull_request' && format('PR #{0} by @{1} - {2}', github.event.pull_request.number, github.actor, github.event.pull_request.title) ||
github.event_name == 'push' && github.event.head_commit && format('Push by @{0} - {1}', github.actor, github.event.head_commit.message) ||
format('{0} triggered by @{1}', github.event_name, github.actor)
}}
on:
push:
branches:
- main
paths:
- "tests/**"
- "scripts/**"
- ".github/workflows/tests.yml"
pull_request:
branches: [main]
workflow_dispatch:
permissions:
contents: read
concurrency:
group: bats-${{ github.ref }}
cancel-in-progress: true
jobs:
bats:
name: BATS unit tests
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install BATS and Node.js
run: |
sudo apt-get update
sudo apt-get install -y bats nodejs
- name: Run BATS test suite
# Cowork tests load scripts/cowork-vm-service.js via `node` —
# the `nodejs` install above is what they need.
run: bats --print-output-on-failure tests/*.bats

View File

@@ -46,6 +46,12 @@ function assertDeepEqual(actual, expected, msg) {
setup() {
TEST_TMP=$(mktemp -d)
export TEST_TMP
# The doctor checks resolve config via ${XDG_CONFIG_HOME:-$HOME/.config}.
# Sandboxing HOME alone is insufficient because GitHub Actions runners
# (and many user environments) export XDG_CONFIG_HOME ambient, which
# overrides the per-test HOME and makes the function read the wrong dir.
unset XDG_CONFIG_HOME
}
teardown() {