Skip to content

fix(nix): give the devShell every tool the test suite shells out to - #3768

Merged
max-sixty merged 2 commits into
mainfrom
nix-devshell-shell-tests
Aug 7, 2026
Merged

max-sixty merged 2 commits into
mainfrom
nix-devshell-shell-tests

Conversation

@max-sixty

@max-sixty max-sixty commented Aug 7, 2026 •

Copy link
Copy Markdown
Owner

devShells.default listed bash, zsh, fish under a # For shell integration tests comment, but that feature drives two more shells and shells out to jq. So nix develop could not run --features shell-integration-tests, which is what the repo's own gate runs (.config/wt.toml → cargo insta test … --all-features). This adds nushell, powershell and jq.

The same dependency claim was stated, wrongly, in three other places. All four now name the real set:

Where Was Now
flake.nix devShell bash, zsh, fish + nushell, powershell, jq
Cargo.toml feature comment bash, zsh, fish + nu, pwsh, jq
tests/CLAUDE.md bash/zsh/fish + PTY + nushell, pwsh, jq
docs/content/faq.md bash, zsh, fish, nushell + pwsh, jq

flake.nix also referenced a CLAUDE.md → "Shell/PTY Integration Tests" heading that exists nowhere in the repo; it now points at the section that does.

Verification

There is no nix on the machine this was written on, so the two claims were checked separately rather than by entering the shell.

Is the list right? A symlink farm modelling a devShell's PATH — nixpkgs stdenv's own tools plus the candidate list, and nothing else — with the full --all-features suite run under it. configure_pty_command propagates the test process's PATH into PTY children, so this reaches the shell tests.

Runs (the control is what makes the failures attributable)
PATH Result
Full ambient PATH (control) 4572 passed, 0 failed
stdenv + every tool the suite needs 4572 passed, 0 failed
…minus pwsh 3 shell_powershell tests fail
…minus jq test_worktree_remove_hook_skips_path_holding_no_worktree fails
…minus python3 / lsof / ps 6 failed: 2 for_each/post_start (python3), 1 remove::test_remove_reap_kills_process (lsof), 3 pgid/process-probe (ps)

The control run matters: it establishes that every failure above is caused by the withheld tool rather than by a local flake.

The last row is about what the suite needs, not what the shell was missing — see the correction below.

Does the flake still evaluate? nixos/nix in a container, evaluating devShells.<system>.default for all four systems flake-utils covers, against unmodified main as a control. All four evaluate, and every tool resolves on each.

Not verified: nothing here was built, only evaluated, so a package that evaluates but fails to build would not have been caught. The nightly nix-flake job runs nix flake check on PRs touching flake.nix, which covers that on x86_64-linux.

A correction: python3/procps/lsof were never missing

The first version of this PR also added python3, procps and lsof, claiming the shell could not run a plain cargo test. That was wrong, and worktrunk-bot caught it.

craneLib.devShell sets inputsFrom = builtins.attrValues checks ++ inputsFrom, and mkShell folds each inputsFrom derivation's nativeBuildInputs into its own. checks includes worktrunk-tests, whose nativeBuildInputs already carry git, python3, procps and lsof — so the devShell inherited all four. Evaluating the unmodified main tree confirms it: its x86_64-linux devShell derivation already contains python3, procps and lsof, and contains no nushell, powershell or jq.

The symlink farm could not have caught this: it modelled stdenv plus the literal packages list, so crane's inherited inputs were invisible to it by construction. The experiment established what the suite needs; it said nothing about what the shell already had.

Those three lines are dropped. git remains listed in both places — pre-existing, and left alone here.

A guard I added and then removed

powershell first went in behind lib.meta.availableOn, because nixos-unstable's PowerShell has no x86_64-darwin source. Testing that guard against nixpkgs HEAD showed the actual cause: nixpkgs 26.11 dropped Intel macOS wholesale, so the entire flake fails to evaluate there regardless of the guard. On every system nixpkgs still supports, PowerShell has a build — the guard protected against nothing, and its comment justified it with the wrong mechanism. Removed; powershell is listed plainly with the other shells.

Notes

task setup-web checks for bash zsh fish nu and not pwsh/jq — the same gap in a different environment, left alone here since its install mechanics are unrelated.

This was written by Claude Code on behalf of max-sixty

The `packages` list carried bash/zsh/fish under a "shell integration
tests" comment, but that feature also drives nushell and pwsh, and its
Claude-hook tests pipe the hook payload through jq. python3, procps and
lsof were missing too, so even a plain `cargo test` failed in the shell.

The same dependency list was stated wrongly in three other places —
Cargo.toml's feature comment, tests/CLAUDE.md, and the FAQ — so all four
now name the real set, and the flake's stale cross-reference to a
"Shell/PTY Integration Tests" heading (which does not exist) now points
at the section that does.

Verified by running the suite with PATH restricted to nixpkgs stdenv
plus this list: everything passes. Withholding python3/lsof/ps from that
PATH fails exactly six tests; withholding pwsh fails three more and jq
one. The flake evaluates on all four systems flake-utils covers.

@worktrunk-bot worktrunk-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The shell and jq additions check out: shell_powershell.rs is #![cfg(feature = "shell-integration-tests")], the jq-piping hook test at tests/integration_tests/config_show.rs is under the same gate, and the tests/CLAUDE.md → "Feature Flags, Not Runtime Skipping" heading the flake now points at exists. One note on the other three packages, inline.

Comment thread flake.nix Outdated
`craneLib.devShell` sets `inputsFrom = builtins.attrValues checks`, and
mkShell folds each one's `nativeBuildInputs` into its own, so the
`worktrunk-tests` check already put python3, procps and lsof on the
shell's PATH. Listing them again was belt-and-suspenders.

Evaluating the unmodified main tree confirms it: its x86_64-linux
devShell derivation already contains all three, and contains no nushell,
powershell or jq. The symlink-farm experiment modelled stdenv plus the
literal `packages` list, so crane's inherited inputs were invisible to
it — it measured what the suite needs, not what the shell already had.
@max-sixty
max-sixty merged commit 497551e into main Aug 7, 2026
47 checks passed
@max-sixty
max-sixty deleted the nix-devshell-shell-tests branch August 7, 2026 23:56
max-sixty added a commit that referenced this pull request Aug 8, 2026
…r web setup (#3776)

Three follow-ups from #3768, plus a bug the verification turned up.

**The flake stops declaring outputs for `x86_64-darwin`.** nixpkgs drops
Intel macOS in 26.11: evaluating anything for that system against
`nixos-unstable` (`26.11pre-git`) throws. The rev `flake.lock` pins is
26.05-era, so it still evaluates today, carrying nixpkgs' own warning
that "26.05 will be the last release to support x86_64-darwin". Naming
three systems rather than `eachDefaultSystem` drops Nix support for
Intel Macs now, ahead of that bump. Release binaries are untouched:
`dist-workspace.toml` still ships `x86_64-apple-darwin` and nightly
still tests it on `macos-15-intel`.

**`git` leaves the devShell's `packages`.** It arrives with the
`checks`, which crane folds in via `inputsFrom`, the same mechanism that
already supplied `python3`, `procps` and `lsof`.

**`task setup-web` installs `pwsh` and `jq`.** Without them Claude Code
web can't run `--features shell-integration-tests`, which is what the
pre-merge gate runs. PowerShell comes from the release `.deb` rather
than the tarball, because pwsh aborts at startup without libicu and only
the `.deb` declares that dependency for apt to resolve. The verification
loop runs each tool instead of looking for it on PATH, since the tarball
install left a `pwsh` that was on PATH and still aborted.

**A `set -e` abort found while testing that.** The `sources.list.d`
cleanup was an `&&` chain, and under `set -e` a chain ending false takes
the whole task down. This one ends false on an unmatched glob and on a
`.list` file with no `[` line, so setup was dying before it installed
anything on a stock Debian box as well as an empty one. It's an `if`
now.

## Verification

No `nix` on the machine this was written on, so the flake was checked in
a `nixos/nix` container and the Taskfile block in an amd64 Debian one.

<details>
<summary>flake: three systems evaluate, x86_64-darwin is gone, git
survives its deletion</summary>

```
== devShell evaluates per system ==
x86_64-linux     OK   g172vwl0g339zsxx9l6mz5pca6w9jbcx-nix-shell.drv
aarch64-linux    OK   pgvq71zs48bx3naddncms954jyqpl0bl-nix-shell.drv
aarch64-darwin   OK   d17q1772si0x0hj1lgpnin8wiq4zlpr2-nix-shell.drv
x86_64-darwin    FAIL: flake does not provide attribute 'devShells.x86_64-darwin.default'

== systems the flake declares ==
["aarch64-darwin","aarch64-linux","x86_64-linux"]

== tools in the x86_64-linux devShell ==
  git: present        jq: present         nushell: present
  powershell: present python3: present    procps: present
  lsof: present       fish: present       zsh: present
  bash: present       gh: present         pre-commit: present

== nixfmt --check flake.nix ==
  clean (exit 0)
```

The x86_64-darwin claim, checked against nixpkgs directly rather than
inferred:

```
== nixos-unstable lib.version ==
"26.11pre-git"
== x86_64-darwin eval on nixos-unstable ==
  error, pointing at release-notes#x86_64-darwin-26.11
== x86_64-darwin eval on the pinned rev (flake.lock) ==
evaluation warning: Nixpkgs 26.05 will be the last release to support x86_64-darwin
"hello-2.12.3"
```

Not verified: nothing was built, only evaluated. The nightly `nix-flake`
job runs `nix flake check` on PRs touching `flake.nix`, which covers
that on x86_64-linux.

</details>

<details>
<summary>setup-web: the block run under Task's own interpreter, in an
amd64 Debian container</summary>

The edited block was extracted into a minimal Taskfile and run by `task`
itself, so mvdan/sh parses it rather than bash. `curl` and nushell are
container prereqs, not part of what's under test.

```
=== running the extracted block under Task ===
Installing shell-integration test dependencies...
pwsh installed
bash available
zsh available
fish available
nu available
pwsh available
jq available
task exit: 0

=== does the installed pwsh actually run? ===
7.6.4
jq-1.6
/usr/bin/pwsh

=== rerun is idempotent ===
Installing shell-integration test dependencies...
bash available   zsh available   fish available
nu available     pwsh available  jq available
```

Two earlier runs are why the shape changed. The first died at the
`sources.list.d` glob. The second installed PowerShell from the release
tarball: every tool reported "available" and `pwsh` then aborted with
`Couldn't find a valid ICU package installed on the system`, which is
what moved the install to the `.deb` and the check from `command -v` to
`--version`.

</details>

`cargo run -- hook pre-merge --yes` passes: 4574 tests, 1 skipped.

## Notes

`task setup-web` still requires nushell to be present rather than
installing it, unchanged here.

> _This was written by Claude Code on behalf of max-sixty_

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
social4hyq pushed a commit to social4hyq/homebrew-core that referenced this pull request Sep 20, 2026
worktrunk 0.73.0

Created-by: HarmonybrewBot
Commit-by: HarmonybrewBot
Merged-by: HarmonybrewBot
Description: Created by `brew bump`

---

Created with `brew bump-formula-pr`.<details>
  <summary>release notes</summary>
  <pre>## Release Notes

### Fixed

- **`wt remove` refuses a registered path that now holds a different repository**: A clone made at a stale registration's path was removed whole, uncommitted work included — and wt routed the user there, since the dirty gate read the occupant's files as this worktree's and offered `--force` as the cure. Removal now compares the directory's git dir against this repository's; `--force` waives uncommitted changes, not the check for whose directory it is. ([#3785](max-sixty/worktrunk#3785))

- **The Nix flake names three systems, dropping Intel macOS**: nixpkgs drops `x86_64-darwin` in 26.11, so the flake would stop evaluating there once `flake.lock` advances past it. (Breaking: `nix build`, `nix run`, and the home-manager module no longer resolve on Intel macOS. Release binaries are unaffected and still ship for it.) ([#3776](max-sixty/worktrunk#3776))

- **`NO_COLOR` and a redirected stream reach every surface**: Escapes still landed in progressive `wt list`, `-v` diagnostics, clap's error tips, and parts of stderr — the deprecation warning, the `wt config update` preview, the `[y/N]` prompt — so a redirected log carried escapes on one line and not the next. Color now resolves in one place. ([#3777](max-sixty/worktrunk#3777), [#3771](max-sixty/worktrunk#3771))

- **A trailing separator no longer hides the branch**: Git's ref format forbids a name ending in `/`, and shell completion produces exactly that spelling whenever a `docs` directory sits beside the branch, so `wt switch docs/` never had a candidate. Selectors are normalized before resolution now — `wt remove`, merge targets, `--base`, and the `pre-switch` hook's `target` alike. ([#3785](max-sixty/worktrunk#3785))

- **A path holding no worktree is reported as a path**: `wt remove ../repo.ghost` answered `No branch named …` and pointed at a listing it could never appear in; `wt switch` and `wt merge` offered `--create <path>`, which git rejects; and `wt config state marker set --branch <path>` silently stored state keyed by a path. ([#3773](max-sixty/worktrunk#3773), thanks @judewang for reporting)

- **A failed GitLab project lookup carries `glab`'s own verdict**: `wt switch mr:<n>` on a fork MR answered a 401, a 404, and a network failure with the same `Failed to fetch project 456`, swallowing the output every other `remote_ref` failure path forwards. A non-project response body now says so too. ([#3799](max-sixty/worktrunk#3799))

- **A deleted-and-recreated worktree directory is reported, not leaked as git's exit 128**: An `rm -rf` followed by a `mkdir` passes the `Path::exists()` probe, so `wt switch`, `wt merge`, `wt step push`, and `wt remove` walked into a raw git failure. All four now name the missing worktree and the `git worktree prune` that clears it. ([#3785](max-sixty/worktrunk#3785))

### Internal

- **Library API rework** (Breaking library API): `cargo-semver-checks` fails four lints — `GitError` gained `WorktreeNotFoundAtPath` and `WorktreePathNotOurs`, shifting seven later discriminants, its `DetachedHead` variant gained a `worktree` field, `ResolvedWorktree` gained `NoWorktreeAtPath`, and `Repository::resolve_worktree_name` was removed. ([#3785](max-sixty/worktrunk#3785), [#3773](max-sixty/worktrunk#3773))

- **Tests and benches spawn a pinned `wt` binary**: a concurrent `cargo` removes and recreates `target/debug/wt` as it uplifts, so spawns hit a one-off `NotFound`; every spawn now routes through a hardlinked pin. ([#3784](max-sixty/worktrunk#3784), [#3792](max-sixty/worktrunk#3792))

- **The nix devShell and `task setup-web` install what the test suite drives**: both were missing `nushell`, `pwsh`, and `jq`, which `--features shell-integration-tests` shells out to. ([#3768](max-sixty/worktrunk#3768), [#3776](max-sixty/worktrunk#3776))

- **Benchmark fixtures reduced to two provenance-based bases**: `Generated` builds a repository locally and `Imported` copies the pinned `rust-lang/rust` corpus, with worktree, branch, and remote-ref populations as parameters. ([#3761](max-sixty/worktrunk#3761))

## Install worktrunk 0.73.0

### Install prebuilt binaries via shell script

```sh
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-installer.sh | sh && wt config shell install
```

### Install prebuilt binaries via powershell script

```sh
powershell -ExecutionPolicy Bypass -c "irm https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-installer.ps1 | iex"; git-wt config shell install
```

### Install prebuilt binaries via Homebrew

```sh
brew install worktrunk && wt config shell install
```

## Download worktrunk 0.73.0

|  File  | Platform | Checksum |
|--------|----------|----------|
| [worktrunk-aarch64-apple-darwin.tar.xz](https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-aarch64-apple-darwin.tar.xz) | Apple Silicon macOS | [checksum](https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-aarch64-apple-darwin.tar.xz.sha256) |
| [worktrunk-x86_64-apple-darwin.tar.xz](https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-x86_64-apple-darwin.tar.xz) | Intel macOS | [checksum](https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-x86_64-apple-darwin.tar.xz.sha256) |
| [worktrunk-x86_64-pc-windows-msvc.zip](https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-x86_64-pc-windows-msvc.zip.sha256) |
| [worktrunk-aarch64-unknown-linux-musl.tar.xz](https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-aarch64-unknown-linux-musl.tar.xz) | ARM64 MUSL Linux | [checksum](https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-aarch64-unknown-linux-musl.tar.xz.sha256) |
| [worktrunk-x86_64-unknown-linux-musl.tar.xz](https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-x86_64-unknown-linux-musl.tar.xz) | x64 MUSL Linux | [checksum](https://github.com/max-sixty/worktrunk/releases/download/v0.73.0/worktrunk-x86_64-unknown-linux-musl.tar.xz.sha256) |



### Install via Cargo

```sh
cargo install worktrunk && wt config shell install
```

### Install via Winget (Windows)

```sh
winget install max-sixty.worktrunk && git-wt config shell install
```

### Install via AUR (Arch Linux)

```sh
paru worktrunk-bin && wt config shell install
```
</pre>
  <p>View the full release notes at <a href="https://github.com/max-sixty/worktrunk/releases/tag/v0.73.0">https://github.com/max-sixty/worktrunk/releases/tag/v0.73.0</a>.</p>
</details>
<hr>

See merge request: Harmonybrew/homebrew-core!16463
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants