Skip to content

Commit c68ffa0

Browse files
philzexedev-shelley
authored andcommitted
fix(shelley): per-world lazycue diff fixture to avoid parallel-step race
The lazycue suite now runs as two parallel Buildkite steps (vue + react) that can land on the same agent and share /tmp. Both processes set up the diff-viewer git fixture at the same fixed path (/tmp/shelley-lazycue-diff-fixture) via setupDiffFixtureRepo (os.RemoveAll + git init), so they raced: one process's RemoveAll ran while the other's `git init` was writing .git/hooks, panicking with "unlinkat .../.git/hooks: directory not empty" and failing the step. Suffix the fixture path with the world (…-vue / …-react) so each process owns its own fixture. The path is still deterministic per world, so the LazyCue description that embeds it hashes to a stable per-world cache key. Regenerated the two cached DSL entries with the new paths (mechanical path swap + rehash, no behavior change); verified both worlds hit cache and pass. Prompt: Now the "vue-rebuild now at ..." lines look ugly. And the Pierre diffs are ugly too. (Follow-up: the parallel lazycue steps from the earlier CI change raced on a shared /tmp fixture.) Co-authored-by: Shelley <shelley@exe.dev>
1 parent 3424a52 commit c68ffa0

3 files changed

Lines changed: 15 additions & 7 deletions

File tree

test/lazycue_test.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -432,9 +432,17 @@ func TestDiffViewerListsAddedModifiedDeleted(t *testing.T) {
432432

433433
// diffFixtureDir is a deterministic path holding a git repo with working-tree
434434
// changes (a modified, a deleted, and a brand-new untracked file). The diff
435-
// viewer's file list is loaded from here. The path is stable so the LazyCue
436-
// description that references it hashes to a consistent cache key.
437-
var diffFixtureDir = filepath.Join(os.TempDir(), "shelley-lazycue-diff-fixture")
435+
// viewer's file list is loaded from here.
436+
//
437+
// The path is per-world: the vue and react lazycue suites run as separate
438+
// processes that may share an agent's /tmp, and a single fixed path would race
439+
// (one process's RemoveAll+git-init stomping the other's, panicking on
440+
// "directory not empty"). The world suffix keeps each process's fixture
441+
// isolated while staying deterministic so the LazyCue description that embeds
442+
// the path hashes to a consistent per-world cache key. lazycueWorld() reads
443+
// LAZYCUE_WORLD, which the harness sets before the process starts, so it is
444+
// valid at package init.
445+
var diffFixtureDir = filepath.Join(os.TempDir(), "shelley-lazycue-diff-fixture-"+lazycueWorld())
438446

439447
// setupDiffFixtureRepo (re)creates a git repo at dir with three kinds of
440448
// working-tree change: a modified tracked file, a deleted tracked file, and a

ui/lazycue/.lazycue/vue/7244604f6f935fb5.json renamed to ui/lazycue/.lazycue/react/c96aac0bb66135be.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
22
"_README": "This file is managed by LazyCue (see shelley/lazycue). Do NOT edit by hand — it is the cached, machine-generated DSL for a self-healing browser test. To change behavior, edit the test description and re-run LazyCue.",
3-
"description": "Navigate to /new?diff=working\u0026cwd=/tmp/shelley-lazycue-diff-fixture . This opens the git diff viewer for the working-tree changes of that repository. Wait for the file picker (a \u003cselect\u003e element with selector \"select.diff-viewer-select\") to be visible. The working tree has exactly four changed files, each appearing as an \u003coption\u003e in that select with a status-symbol prefix: a modified file shown as \"~ tracked_mod.txt\", a deleted file shown as \"- tracked_del.txt\", a brand-new untracked file shown as \"+ untracked_added.txt\", and a modified committed file whose name contains a space shown as \"~ spaced name.txt\". Verify all four options are present, with their full untruncated paths, by running an eval step whose expression is \"(() =\u003e { const opts = Array.from(document.querySelectorAll('select.diff-viewer-select option')).map(o =\u003e o.textContent.trim()); const has = (sym, name) =\u003e opts.some(t =\u003e t.startsWith(sym) \u0026\u0026 t.includes(name)); return has('+','untracked_added.txt') \u0026\u0026 has('~','tracked_mod.txt') \u0026\u0026 has('-','tracked_del.txt') \u0026\u0026 has('~','spaced name.txt') ? 'true' : 'false'; })()\" and expect the result \"true\". Two regression cases matter here: the untracked (added) file must be present with the \"+\" prefix, and the committed file with a space must appear as the full \"spaced name.txt\" (not truncated at the space to \"spaced\").",
3+
"description": "Navigate to /new?diff=working\u0026cwd=/tmp/shelley-lazycue-diff-fixture-react . This opens the git diff viewer for the working-tree changes of that repository. Wait for the file picker (a \u003cselect\u003e element with selector \"select.diff-viewer-select\") to be visible. The working tree has exactly four changed files, each appearing as an \u003coption\u003e in that select with a status-symbol prefix: a modified file shown as \"~ tracked_mod.txt\", a deleted file shown as \"- tracked_del.txt\", a brand-new untracked file shown as \"+ untracked_added.txt\", and a modified committed file whose name contains a space shown as \"~ spaced name.txt\". Verify all four options are present, with their full untruncated paths, by running an eval step whose expression is \"(() =\u003e { const opts = Array.from(document.querySelectorAll('select.diff-viewer-select option')).map(o =\u003e o.textContent.trim()); const has = (sym, name) =\u003e opts.some(t =\u003e t.startsWith(sym) \u0026\u0026 t.includes(name)); return has('+','untracked_added.txt') \u0026\u0026 has('~','tracked_mod.txt') \u0026\u0026 has('-','tracked_del.txt') \u0026\u0026 has('~','spaced name.txt') ? 'true' : 'false'; })()\" and expect the result \"true\". Two regression cases matter here: the untracked (added) file must be present with the \"+\" prefix, and the committed file with a space must appear as the full \"spaced name.txt\" (not truncated at the space to \"spaced\").",
44
"version": 1,
55
"steps": [
66
{
77
"action": "navigate",
8-
"url": "/new?diff=working\u0026cwd=/tmp/shelley-lazycue-diff-fixture"
8+
"url": "/new?diff=working\u0026cwd=/tmp/shelley-lazycue-diff-fixture-react"
99
},
1010
{
1111
"action": "wait_visible",

ui/lazycue/.lazycue/react/7244604f6f935fb5.json renamed to ui/lazycue/.lazycue/vue/b8bc987dd4b8a3a2.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
22
"_README": "This file is managed by LazyCue (see shelley/lazycue). Do NOT edit by hand — it is the cached, machine-generated DSL for a self-healing browser test. To change behavior, edit the test description and re-run LazyCue.",
3-
"description": "Navigate to /new?diff=working\u0026cwd=/tmp/shelley-lazycue-diff-fixture . This opens the git diff viewer for the working-tree changes of that repository. Wait for the file picker (a \u003cselect\u003e element with selector \"select.diff-viewer-select\") to be visible. The working tree has exactly four changed files, each appearing as an \u003coption\u003e in that select with a status-symbol prefix: a modified file shown as \"~ tracked_mod.txt\", a deleted file shown as \"- tracked_del.txt\", a brand-new untracked file shown as \"+ untracked_added.txt\", and a modified committed file whose name contains a space shown as \"~ spaced name.txt\". Verify all four options are present, with their full untruncated paths, by running an eval step whose expression is \"(() =\u003e { const opts = Array.from(document.querySelectorAll('select.diff-viewer-select option')).map(o =\u003e o.textContent.trim()); const has = (sym, name) =\u003e opts.some(t =\u003e t.startsWith(sym) \u0026\u0026 t.includes(name)); return has('+','untracked_added.txt') \u0026\u0026 has('~','tracked_mod.txt') \u0026\u0026 has('-','tracked_del.txt') \u0026\u0026 has('~','spaced name.txt') ? 'true' : 'false'; })()\" and expect the result \"true\". Two regression cases matter here: the untracked (added) file must be present with the \"+\" prefix, and the committed file with a space must appear as the full \"spaced name.txt\" (not truncated at the space to \"spaced\").",
3+
"description": "Navigate to /new?diff=working\u0026cwd=/tmp/shelley-lazycue-diff-fixture-vue . This opens the git diff viewer for the working-tree changes of that repository. Wait for the file picker (a \u003cselect\u003e element with selector \"select.diff-viewer-select\") to be visible. The working tree has exactly four changed files, each appearing as an \u003coption\u003e in that select with a status-symbol prefix: a modified file shown as \"~ tracked_mod.txt\", a deleted file shown as \"- tracked_del.txt\", a brand-new untracked file shown as \"+ untracked_added.txt\", and a modified committed file whose name contains a space shown as \"~ spaced name.txt\". Verify all four options are present, with their full untruncated paths, by running an eval step whose expression is \"(() =\u003e { const opts = Array.from(document.querySelectorAll('select.diff-viewer-select option')).map(o =\u003e o.textContent.trim()); const has = (sym, name) =\u003e opts.some(t =\u003e t.startsWith(sym) \u0026\u0026 t.includes(name)); return has('+','untracked_added.txt') \u0026\u0026 has('~','tracked_mod.txt') \u0026\u0026 has('-','tracked_del.txt') \u0026\u0026 has('~','spaced name.txt') ? 'true' : 'false'; })()\" and expect the result \"true\". Two regression cases matter here: the untracked (added) file must be present with the \"+\" prefix, and the committed file with a space must appear as the full \"spaced name.txt\" (not truncated at the space to \"spaced\").",
44
"version": 1,
55
"steps": [
66
{
77
"action": "navigate",
8-
"url": "/new?diff=working\u0026cwd=/tmp/shelley-lazycue-diff-fixture"
8+
"url": "/new?diff=working\u0026cwd=/tmp/shelley-lazycue-diff-fixture-vue"
99
},
1010
{
1111
"action": "wait_visible",

0 commit comments

Comments
 (0)