Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 20 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,19 @@ jobs:
with:
node-version: "24"
package-manager-cache: false
- name: Provision pinned configuration parser explicitly
run: ./setup-sync.sh
# --ci requires zsh for the zsh launcher and completion cases; dash, the
# image's /bin/sh, runs install.sh in the standalone end-to-end test,
# and GNU Stow builds its folded Stow layouts. standalone-e2e.sh skips
# those cases without Stow, so the step fails unless their heading is in
# the output; `shell: bash` adds pipefail, so a failing run.sh fails too.
- name: Install zsh and GNU Stow
run: sudo apt-get update && sudo apt-get install --yes --no-install-recommends zsh stow
- name: Run behavior tests with required CI prerequisites
run: /bin/bash ./tests/run.sh --ci
shell: bash
run: |
/bin/bash ./tests/run.sh --ci | tee "$RUNNER_TEMP/tests.log"
grep -Fqx '==> refusals: destinations in directories GNU Stow folded into another repository' "$RUNNER_TEMP/tests.log" ||
{ echo '::error::standalone-e2e.sh skipped its folded Stow cases.'; exit 1; }
# The same steps pre-commit/action@v3.0.1 runs, without its unmaintained
# actions/cache@v4 pin (Node 20). Same cache path and key.
- name: Install pre-commit
Expand Down Expand Up @@ -64,9 +73,12 @@ jobs:
with:
node-version: "24"
package-manager-cache: false
- name: Provision pinned configuration parser explicitly
run: ./setup-sync.sh
- name: Run behavior tests with system Bash and BSD utilities
# macOS ships zsh, which --ci requires; install it only if the image lacks it.
- name: Check for zsh
run: command -v zsh || brew install zsh
# The tests run under /bin/bash 3.2, and the standalone end-to-end test
# runs install.sh under /bin/sh and drives the launchers through its links.
- name: Run behavior tests with system Bash, /bin/sh and BSD utilities
run: /bin/bash ./tests/run.sh --ci
- name: Check that tests left no file behind
run: |
Expand All @@ -84,16 +96,12 @@ jobs:
# The runner's default core.autocrlf stays on, so the LF check below
# proves .gitattributes, not a runner setting.
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: "3.12"
# run.ps1 runs only the Node suite of the Claude Code helpers.
- uses: actions/setup-node@v6
with:
node-version: "24"
package-manager-cache: false
- name: Provision pinned configuration parser explicitly
run: ./setup-sync.ps1
# stow-all.ps1 runs the POSIX sh helpers under Git Bash, where a CRLF
# The launchers and completions are shell scripts, where a CRLF
# `set -eu` fails.
- name: Check that the working tree has LF line endings
run: |
Expand Down
65 changes: 32 additions & 33 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,27 @@ repos:
hooks:
- id: shellcheck
args: [--severity=warning]
files: (\.sh$|/\.local/bin/[^/]+-sync$|/\.local/bin/(codex|claude)-as$|/bash-completion/completions/.*$)
files: (\.sh$|^bin/(codex|claude)-as$|^completions/bash/.*$)
types: [file]

# The upstream hook selects the shell type, which identify does not give the
# extension-less completions; each hook checks every file its pattern names
# instead.
- repo: https://github.com/scop/pre-commit-shfmt
rev: v3.14.1-1
hooks:
- id: shfmt
args: [-w, -i, "4", -ci, -ln, bash]
files: (\.sh$|/\.local/bin/codex-as$|/bash-completion/completions/.*$)
exclude: ^(setup-sync\.sh|lib/sync-runtime\.sh)$
files: (\.sh$|^bin/codex-as$|^completions/bash/.*$)
exclude: ^install\.sh$
types: [file]
- id: shfmt
args: [-w, -i, "4", -ci, -ln, posix]
files: (/\.local/bin/([^/]+-sync|claude-as)$|^(setup-sync\.sh|lib/sync-runtime\.sh)$)
files: ^(bin/claude-as|install\.sh)$
types: [file]
- id: shfmt
args: [-w, -i, "4", -ci, -ln, zsh]
files: /custom/completions/_[^/]+$
# The upstream hook selects the shell type, which identify does not
# give the extension-less completions; every file the pattern names
# is checked instead.
files: ^completions/zsh/_[^/]+$
types: [file]

- repo: local
Expand All @@ -64,47 +65,45 @@ repos:
entry: '[^\x09\x0a\x0d\x20-\x7e]'
types: [file]
files: '(?i)(\.(md|markdown|mdx|rst|txt)$|(^|/)(README|CHANGELOG|CONTRIBUTING|AUTHORS|LICENSE|NOTICE)(\.[^/]*)?$)'
# The engine suites below load lib/; in dotfiles the installer and
# doctor hooks covered engine edits, and those hooks do not exist here.
- id: structured-config-sync
name: structured configuration merge and safe writes
entry: tests/config-sync.sh
language: script
pass_filenames: false
files: ^(lib/.*|requirements-sync\.txt|setup-sync\.(sh|ps1)|tests/(test_config_sync\.py|config-sync\.sh|fixtures/codex-config\.toml)|common/(claude|codex)/\.local/bin/.*)$
- id: ai-config-sync
name: ai config and rules sync
entry: tests/ai-config-sync.sh
language: script
pass_filenames: false
files: ^(lib/.*|common/(claude|codex)/.*|tests/(ai-config-sync\.sh|fixtures/(claude-settings\.json|portable\.rules)))$
- id: claude-customizations
name: Claude status line, notifications and Git hook guard
entry: node --test tests/claude-customizations.cjs
language: system
pass_filenames: false
files: ^(common/claude/.*|tests/(claude-customizations\.cjs|fixtures/claude-settings\.json))$
- id: codex-config-sync
name: codex config sync behavior
entry: tests/codex-config-sync.sh
language: script
pass_filenames: false
files: ^(lib/.*|common/codex/\.local/bin/codex-config-sync|tests/codex-config-sync\.sh)$
files: ^(helpers/.*|tests/(claude-customizations\.cjs|fixtures/claude-settings\.json))$
- id: codex-as
name: Codex account views and native sharing (isolated Bash/zsh)
entry: tests/codex-as.sh
language: script
pass_filenames: false
files: ^(common/codex/\.local/(bin/codex-as|lib/codex-as/.*)|tests/(codex-as\.sh|test_codex_as\.py|test_codex_sharing_native\.py|fixtures/(zsh|bash)_aliases))$
files: ^(bin/codex-as|lib/(codex-as|coding-agent-kit)/.*|tests/(codex-as\.sh|test_codex_as\.py|test_codex_sharing_native\.py|fixtures/(zsh|bash)_aliases))$
- id: account-enrollment
name: account enrollment and completion (isolated HOME and native CLI fakes)
entry: tests/account-enrollment.sh
language: script
pass_filenames: false
files: ^(common/(codex|claude)/.*|tests/(account-enrollment\.sh|test_account_enrollment\.py))$
files: ^(bin/.*|lib/.*|completions/.*|tests/(account-enrollment\.sh|test_account_enrollment\.py|test_codex_as\.py))$
- id: config
name: kit configuration, launcher location and metadata queries (isolated HOME)
entry: tests/config.sh
language: script
pass_filenames: false
files: ^(bin/.*|lib/.*|completions/.*|docs/account-launchers\.md|tests/(config\.sh|test_config\.py|test_codex_as\.py))$
- id: test-entrypoints
name: test entry points and dotfiles knob hygiene
name: test entry points and kit knob hygiene
entry: tests/test-entrypoints.sh
language: script
pass_filenames: false
files: ^(tests/.*\.(sh|ps1)|lib/.*|common/.*)$
files: ^(tests/(.*\.(sh|ps1)|test_config\.py)|bin/.*|lib/.*|completions/.*|helpers/.*|install\.sh)$
- id: contract
name: public contract (paths, modes, no symlinks, CI job names)
entry: tests/contract.sh
language: script
pass_filenames: false
files: ^(bin/.*|lib/.*|completions/.*|helpers/.*|docs/.*|install\.sh|\.github/workflows/ci\.yml|tests/(contract\.sh|claude-customizations\.cjs|fixtures/claude-settings\.json))$
- id: standalone-e2e
name: standalone install and launchers without dotfiles (temporary HOME, fakes)
entry: tests/standalone-e2e.sh
language: script
pass_filenames: false
files: ^(install\.sh|bin/.*|lib/.*|completions/.*|docs/account-launchers\.md|tests/standalone-e2e\.sh)$
Loading
Loading