From 9f086c2316dfdddd072fe016c040f216eed4d373 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 18 Jul 2026 18:15:51 +0000 Subject: [PATCH 1/4] fix(pkgset): stop duplicating global PATH/GOPATH entries Base Go environments already embed the global pkgset. Copying that file to *@global and appending again doubled prefixes. Special-case global in pkgset-create, align the installer, and add regression coverage (#8). Co-authored-by: Brian Thompson --- ChangeLog | 6 ++ binscripts/gvm-installer | 9 +- ...26-07-18-001-fix-global-pkgset-dup-plan.md | 101 ++++++++++++++++++ scripts/ci-smoke.sh | 7 ++ scripts/pkgset-create | 32 +++--- tests/gvm_pkgset_global_comment_test.sh | 25 +++++ 6 files changed, 159 insertions(+), 21 deletions(-) create mode 100644 docs/plans/2026-07-18-001-fix-global-pkgset-dup-plan.md create mode 100644 tests/gvm_pkgset_global_comment_test.sh diff --git a/ChangeLog b/ChangeLog index b38f228..ba3436e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,12 @@ All notable changes to gvm2 are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/). +## [Unreleased] + +### Fixed + +- Stop duplicating `GOPATH`/`PATH` when creating the `global` pkgset environment (`pkgset-create` and installer `system@global`) (#8). + ## [1.2.0] - 2026-07-14 ### Added diff --git a/binscripts/gvm-installer b/binscripts/gvm-installer index 375b9b1..08910b2 100755 --- a/binscripts/gvm-installer +++ b/binscripts/gvm-installer @@ -41,15 +41,8 @@ export GOPATH; GOPATH="$GVM_DEST/$GVM_NAME/pkgsets/system/global" export PATH; PATH="$GVM_DEST/$GVM_NAME/pkgsets/system/global/bin:$GOROOT/bin:$GVM_ROOT/bin:\$PATH" EOF - # create system@global pkgset + # create system@global pkgset (base system env already embeds global) cp $GVM_DEST/$GVM_NAME/environments/system $GVM_DEST/$GVM_NAME/environments/system@global - # @TODO: This is here for consistency with 'gvm pkgset create' which adds - # some duplicated entries when the pkgset is 'global'. Need to fix it! - cat << EOF >> $GVM_DEST/$GVM_NAME/environments/system@global -export gvm_pkgset_name="global" -export GOPATH; GOPATH="$GVM_DEST/$GVM_NAME/pkgsets/system/global:\$GOPATH" -export PATH; PATH="$GVM_DEST/$GVM_NAME/pkgsets/system/global/bin:\$PATH" -EOF } BRANCH=${1:-master} diff --git a/docs/plans/2026-07-18-001-fix-global-pkgset-dup-plan.md b/docs/plans/2026-07-18-001-fix-global-pkgset-dup-plan.md new file mode 100644 index 0000000..8648398 --- /dev/null +++ b/docs/plans/2026-07-18-001-fix-global-pkgset-dup-plan.md @@ -0,0 +1,101 @@ +--- +title: Fix global pkgset env duplication - Plan +type: fix +date: 2026-07-18 +artifact_contract: ce-unified-plan/v1 +artifact_readiness: implementation-ready +product_contract_source: ce-plan-bootstrap +execution: code +origin: https://github.com/brianrobt/gvm2/issues/8 +--- + +# Fix global pkgset env duplication - Plan + +## Goal Capsule + +Stop writing duplicated `GOPATH` / `PATH` prefixes into `*@global` environment files. +`pkgset-create` is the source of truth; the installer mirrors the clean behavior. +Done when new `global` pkgset files have a single global path prefix and a regression test covers both paths. + +## Product Contract + +### Summary + +Base Go environment files already embed the `global` pkgset. Copying that file to `$go@global` and appending global prefixes again doubles PATH/GOPATH. Fix creation so `@global` is a clean copy for the global case. + +### Problem Frame + +When a Go version is installed, `scripts/install` `create_enviroment` writes `environments/$GO_NAME` with `gvm_pkgset_name=global` and global `GOPATH`/`PATH` already set, then calls `gvm pkgset create global`. That command copies the base file to `$GO_NAME@global` and appends the same global prefixes again. + +The installer does the same for system Go: write `environments/system` with global baked in, copy to `system@global`, then append again (with an explicit `@TODO`). + +Duplicate entries are usually harmless but pollute env files and confuse PATH debugging. + +### Requirements + +- R1. `gvm pkgset create global` must not prepend a second copy of the global pkgset `GOPATH`/`PATH` when the base env already includes them. +- R2. Fresh installer `system@global` must match the clean shape (copy of `system`, no redundant append block). +- R3. Non-`global` pkgsets keep current behavior (copy base, then prepend named pkgset paths and overlays). +- R4. Existing installs are not migrated; only newly created env files are fixed. + +### Scope Boundaries + +- In scope: `scripts/pkgset-create`, `binscripts/gvm-installer`, regression coverage. +- Out of scope: rewriting already-installed `@global` files; #9 nil-hash TODOs; P3 features. + +### Acceptance Examples + +- AE1. After `gvm pkgset create global` on a base env that already has global paths, `$go@global` contains one `pkgsets/$go/global` GOPATH assignment chain without `global:…:global`. +- AE2. After installer with an existing system Go, `system@global` equals `system` (or differs only by harmless metadata), with no second GOPATH/PATH append block. + +## Planning Contract + +### Key Technical Decisions + +- KTD1. Special-case `global` in `pkgset-create`: after copying the base env, skip the GOPATH/PATH (and redundant `gvm_pkgset_name`) appends. Overlay block already skips `global`. +- KTD2. Installer: `cp system system@global` only; delete the `@TODO` append block. +- KTD3. Do not try to detect "already has global" via string parsing of env files — the product invariant is that base envs always embed global (`create_enviroment` / installer). Name-based special case matches that invariant and the existing `!= global` overlay gate. +- KTD4. No migration of existing user env files in this change. + +### Assumptions + +- Base environment files for every Go version always embed the global pkgset before `@global` is created (true for current `install` and installer paths). + +## Implementation Units + +### U1. Fix `pkgset-create` for global + +**Goal:** Creating the `global` pkgset no longer doubles PATH/GOPATH. +**Requirements:** R1, R3 +**Dependencies:** none +**Files:** `scripts/pkgset-create`, `tests/gvm_pkgset_global_comment_test.sh` (new) +**Approach:** When `target_set_name` is `global`, copy the base environment to `$go@global` and stop (dirs still created as today). For all other names, keep the current append + overlay behavior. +**Execution note:** Prefer a lightweight `tf` comment test that can assert env-file shape after a controlled `pkgset create global`, or a small shell helper under tests if comment-test setup is too heavy. +**Test scenarios:** +- Happy path: with a fake/minimal `GVM_ROOT` whose base env already has global GOPATH/PATH, `pkgset create global` yields `@global` without a second `GOPATH="…/global:$GOPATH"` line. +- Edge: non-global pkgset still gets prepended GOPATH/PATH and overlay block. +- Error: creating an already-existing pkgset still fatals. +**Verification:** New test passes; manual inspection of generated `@global` shows no duplicate prefix. + +### U2. Align installer `system@global` + +**Goal:** Installer no longer copies the buggy append shape. +**Requirements:** R2 +**Dependencies:** U1 (behaviorally aligned; can land in same commit) +**Files:** `binscripts/gvm-installer` +**Approach:** Keep directory creation and `system` env write; `cp` to `system@global`; remove append + `@TODO`. +**Test scenarios:** +- Happy path: after installer with `GOROOT`/system Go present, `system@global` has no trailing duplicate GOPATH/PATH exports beyond what `system` already contains. +**Verification:** Diff `system` vs `system@global` is empty (or only intentional), smoke/CI install still succeeds. + +## Verification Contract + +- Run the new pkgset global regression test via the existing `tf` suite path (or equivalent local invocation). +- Smoke: installer completes; `gvm pkgset create` for a non-global name still works if exercised. +- No ChangeLog bump required unless shipping a release note in the same PR (optional one-liner under Fixed for next version). + +## Definition of Done + +- U1 and U2 landed; `@TODO` removed from installer. +- Regression test covers the global duplication case. +- Issue #8 addressed (close manually if bot lacks permission). diff --git a/scripts/ci-smoke.sh b/scripts/ci-smoke.sh index 8cd1e6e..b045f04 100755 --- a/scripts/ci-smoke.sh +++ b/scripts/ci-smoke.sh @@ -7,10 +7,17 @@ source "$GVM_DEST/gvm/scripts/gvm" echo "GVM_VERSION=${GVM_VERSION:-} HEXDUMP_PATH=${HEXDUMP_PATH:-}" test -n "$GVM_VERSION" test -n "$HEXDUMP_PATH" +# system@global is only created when an existing Go was detected at install time +if [ -f "$GVM_DEST/gvm/environments/system@global" ]; then + ! grep -q 'global:$GOPATH' "$GVM_DEST/gvm/environments/system@global" + diff -q "$GVM_DEST/gvm/environments/system" "$GVM_DEST/gvm/environments/system@global" +fi gvm install go1.22.12 -B gvm use go1.22.12 go version | grep -E 'go1\.22\.12' gvm list --porcelain | grep -F 'go1.22.12' +# install creates $go@global via pkgset create; must not duplicate global GOPATH +! grep -q 'global:$GOPATH' "$GVM_DEST/gvm/environments/go1.22.12@global" spaced="$GVM_DEST/dir with spaces" mkdir -p "$spaced" cd "$spaced" diff --git a/scripts/pkgset-create b/scripts/pkgset-create index 20eea82..5e115e7 100755 --- a/scripts/pkgset-create +++ b/scripts/pkgset-create @@ -33,6 +33,14 @@ mkdir -p "$target_top/pkgsets/$gvm_go_name/$target_set_name" || display_fatal "Could not create packageset folder" cp "$GVM_ROOT/environments/$gvm_go_name" "$target_top/environments/$gvm_go_name@$target_set_name" || display_fatal "Could copy environment" + +# Base Go environments already embed the global pkgset (see scripts/install +# create_enviroment and binscripts/gvm-installer). Copying alone is enough for +# global; re-appending GOPATH/PATH would duplicate those prefixes. +if [ "${target_set_name}" = "global" ]; then + exit 0 +fi + echo "export gvm_pkgset_name=\"$target_set_name_str\"" >> "$target_top/environments/$gvm_go_name@$target_set_name" || display_fatal "Could not extend environment" echo "export GOPATH; GOPATH=\"$add_gopath:\$GOPATH\"" >> "$target_top/environments/$gvm_go_name@$target_set_name" || @@ -40,16 +48,14 @@ echo "export GOPATH; GOPATH=\"$add_gopath:\$GOPATH\"" >> "$target_top/environmen echo "export PATH; PATH=\"$add_path:\$PATH\"" >> "$target_top/environments/$gvm_go_name@$target_set_name" || display_fatal "Could not extend environment" -if [ "${target_set_name}" != "global" ]; then - echo "# Package Set-Specific Overrides" >> "${GVM_ROOT}/environments/${gvm_go_name}@${target_set_name}" - echo "export GVM_OVERLAY_PREFIX; GVM_OVERLAY_PREFIX=\"\${GVM_ROOT}/pkgsets/${gvm_go_name}/${target_set_name}/overlay\"" >> "${GVM_ROOT}/environments/${gvm_go_name}@${target_set_name}" - mkdir -p "${GVM_ROOT}/pkgsets/${gvm_go_name}/${target_set_name}/overlay/"{bin,lib/pkgconfig} - echo "export PATH; PATH=\"${GVM_ROOT}/pkgsets/${gvm_go_name}/${target_set_name}/bin:\${GVM_OVERLAY_PREFIX}/bin:\${PATH}\"" >> "$GVM_ROOT/environments/${gvm_go_name}@${target_set_name}" || - display_fatal "Could not extend environment" - echo "export LD_LIBRARY_PATH; LD_LIBRARY_PATH=\"\${GVM_OVERLAY_PREFIX}/lib:\${LD_LIBRARY_PATH}\"" >> "${GVM_ROOT}/environments/${gvm_go_name}@${target_set_name}" || - display_fatal "Could not extend environment" - echo "export DYLD_LIBRARY_PATH; DYLD_LIBRARY_PATH=\"\${GVM_OVERLAY_PREFIX}/lib:\${DYLD_LIBRARY_PATH}\"" >> "${GVM_ROOT}/environments/${gvm_go_name}@${target_set_name}" || - display_fatal "Could not extend environment" - echo "export PKG_CONFIG_PATH; PKG_CONFIG_PATH=\"\${GVM_OVERLAY_PREFIX}/lib/pkgconfig:\${PKG_CONFIG_PATH}\"" >> "${GVM_ROOT}/environments/${gvm_go_name}@${target_set_name}" || - display_fatal "Could not extend environment" -fi +echo "# Package Set-Specific Overrides" >> "${GVM_ROOT}/environments/${gvm_go_name}@${target_set_name}" +echo "export GVM_OVERLAY_PREFIX; GVM_OVERLAY_PREFIX=\"\${GVM_ROOT}/pkgsets/${gvm_go_name}/${target_set_name}/overlay\"" >> "${GVM_ROOT}/environments/${gvm_go_name}@${target_set_name}" +mkdir -p "${GVM_ROOT}/pkgsets/${gvm_go_name}/${target_set_name}/overlay/"{bin,lib/pkgconfig} +echo "export PATH; PATH=\"${GVM_ROOT}/pkgsets/${gvm_go_name}/${target_set_name}/bin:\${GVM_OVERLAY_PREFIX}/bin:\${PATH}\"" >> "$GVM_ROOT/environments/${gvm_go_name}@${target_set_name}" || + display_fatal "Could not extend environment" +echo "export LD_LIBRARY_PATH; LD_LIBRARY_PATH=\"\${GVM_OVERLAY_PREFIX}/lib:\${LD_LIBRARY_PATH}\"" >> "${GVM_ROOT}/environments/${gvm_go_name}@${target_set_name}" || + display_fatal "Could not extend environment" +echo "export DYLD_LIBRARY_PATH; DYLD_LIBRARY_PATH=\"\${GVM_OVERLAY_PREFIX}/lib:\${DYLD_LIBRARY_PATH}\"" >> "${GVM_ROOT}/environments/${gvm_go_name}@${target_set_name}" || + display_fatal "Could not extend environment" +echo "export PKG_CONFIG_PATH; PKG_CONFIG_PATH=\"\${GVM_OVERLAY_PREFIX}/lib/pkgconfig:\${PKG_CONFIG_PATH}\"" >> "${GVM_ROOT}/environments/${gvm_go_name}@${target_set_name}" || + display_fatal "Could not extend environment" diff --git a/tests/gvm_pkgset_global_comment_test.sh b/tests/gvm_pkgset_global_comment_test.sh new file mode 100644 index 0000000..dd6d2de --- /dev/null +++ b/tests/gvm_pkgset_global_comment_test.sh @@ -0,0 +1,25 @@ +source $GVM_ROOT/scripts/gvm + +## Synthetic Go env whose base file already embeds the global pkgset +mkdir -p "$GVM_ROOT/gos/duptest" "$GVM_ROOT/pkgsets/duptest" "$GVM_ROOT/environments" +cat > "$GVM_ROOT/environments/duptest" < Date: Sat, 18 Jul 2026 18:25:24 +0000 Subject: [PATCH 2/4] fix(ci): retry flaky Go binary downloads; stop committing plans Ubuntu bash smoke failed on a transient go.dev download, not the pkgset env checks. Retry binary downloads and ensure the archive dir exists. Also remove the committed plan doc, gitignore docs/plans and docs/brainstorms, and add a Cursor rule against committing plan files. Co-authored-by: Brian Thompson --- .cursor/rules/no-commit-plan-files.mdc | 15 +++ .gitignore | 4 + ...26-07-18-001-fix-global-pkgset-dup-plan.md | 101 ------------------ scripts/ci-smoke.sh | 10 +- scripts/install | 32 ++++-- 5 files changed, 51 insertions(+), 111 deletions(-) create mode 100644 .cursor/rules/no-commit-plan-files.mdc delete mode 100644 docs/plans/2026-07-18-001-fix-global-pkgset-dup-plan.md diff --git a/.cursor/rules/no-commit-plan-files.mdc b/.cursor/rules/no-commit-plan-files.mdc new file mode 100644 index 0000000..0e4a3a5 --- /dev/null +++ b/.cursor/rules/no-commit-plan-files.mdc @@ -0,0 +1,15 @@ +--- +description: Never commit local planning/brainstorm artifacts to the git repo +alwaysApply: true +--- + +# No committed plan files + +Do **not** commit planning or brainstorm artifacts to this repository. + +- Keep plans locally under `docs/plans/` (gitignored) or outside the repo +- Keep brainstorm/requirements drafts under `docs/brainstorms/` (gitignored) or outside the repo +- Do not add `docs/plans/**` or `docs/brainstorms/**` in commits, PRs, or release trees +- Implementation work, tests, and user-facing docs belong in the repo; ce-plan / ce-brainstorm outputs do not + +If a plan was committed by mistake, remove it from the branch and ensure `.gitignore` still covers those paths. diff --git a/.gitignore b/.gitignore index aaa9c45..9e33b27 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,7 @@ tmp/ scripts/gvm Gemfile.lock .vagrant/ + +# Local planning artifacts — do not commit (see .cursor/rules) +docs/plans/ +docs/brainstorms/ diff --git a/docs/plans/2026-07-18-001-fix-global-pkgset-dup-plan.md b/docs/plans/2026-07-18-001-fix-global-pkgset-dup-plan.md deleted file mode 100644 index 8648398..0000000 --- a/docs/plans/2026-07-18-001-fix-global-pkgset-dup-plan.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Fix global pkgset env duplication - Plan -type: fix -date: 2026-07-18 -artifact_contract: ce-unified-plan/v1 -artifact_readiness: implementation-ready -product_contract_source: ce-plan-bootstrap -execution: code -origin: https://github.com/brianrobt/gvm2/issues/8 ---- - -# Fix global pkgset env duplication - Plan - -## Goal Capsule - -Stop writing duplicated `GOPATH` / `PATH` prefixes into `*@global` environment files. -`pkgset-create` is the source of truth; the installer mirrors the clean behavior. -Done when new `global` pkgset files have a single global path prefix and a regression test covers both paths. - -## Product Contract - -### Summary - -Base Go environment files already embed the `global` pkgset. Copying that file to `$go@global` and appending global prefixes again doubles PATH/GOPATH. Fix creation so `@global` is a clean copy for the global case. - -### Problem Frame - -When a Go version is installed, `scripts/install` `create_enviroment` writes `environments/$GO_NAME` with `gvm_pkgset_name=global` and global `GOPATH`/`PATH` already set, then calls `gvm pkgset create global`. That command copies the base file to `$GO_NAME@global` and appends the same global prefixes again. - -The installer does the same for system Go: write `environments/system` with global baked in, copy to `system@global`, then append again (with an explicit `@TODO`). - -Duplicate entries are usually harmless but pollute env files and confuse PATH debugging. - -### Requirements - -- R1. `gvm pkgset create global` must not prepend a second copy of the global pkgset `GOPATH`/`PATH` when the base env already includes them. -- R2. Fresh installer `system@global` must match the clean shape (copy of `system`, no redundant append block). -- R3. Non-`global` pkgsets keep current behavior (copy base, then prepend named pkgset paths and overlays). -- R4. Existing installs are not migrated; only newly created env files are fixed. - -### Scope Boundaries - -- In scope: `scripts/pkgset-create`, `binscripts/gvm-installer`, regression coverage. -- Out of scope: rewriting already-installed `@global` files; #9 nil-hash TODOs; P3 features. - -### Acceptance Examples - -- AE1. After `gvm pkgset create global` on a base env that already has global paths, `$go@global` contains one `pkgsets/$go/global` GOPATH assignment chain without `global:…:global`. -- AE2. After installer with an existing system Go, `system@global` equals `system` (or differs only by harmless metadata), with no second GOPATH/PATH append block. - -## Planning Contract - -### Key Technical Decisions - -- KTD1. Special-case `global` in `pkgset-create`: after copying the base env, skip the GOPATH/PATH (and redundant `gvm_pkgset_name`) appends. Overlay block already skips `global`. -- KTD2. Installer: `cp system system@global` only; delete the `@TODO` append block. -- KTD3. Do not try to detect "already has global" via string parsing of env files — the product invariant is that base envs always embed global (`create_enviroment` / installer). Name-based special case matches that invariant and the existing `!= global` overlay gate. -- KTD4. No migration of existing user env files in this change. - -### Assumptions - -- Base environment files for every Go version always embed the global pkgset before `@global` is created (true for current `install` and installer paths). - -## Implementation Units - -### U1. Fix `pkgset-create` for global - -**Goal:** Creating the `global` pkgset no longer doubles PATH/GOPATH. -**Requirements:** R1, R3 -**Dependencies:** none -**Files:** `scripts/pkgset-create`, `tests/gvm_pkgset_global_comment_test.sh` (new) -**Approach:** When `target_set_name` is `global`, copy the base environment to `$go@global` and stop (dirs still created as today). For all other names, keep the current append + overlay behavior. -**Execution note:** Prefer a lightweight `tf` comment test that can assert env-file shape after a controlled `pkgset create global`, or a small shell helper under tests if comment-test setup is too heavy. -**Test scenarios:** -- Happy path: with a fake/minimal `GVM_ROOT` whose base env already has global GOPATH/PATH, `pkgset create global` yields `@global` without a second `GOPATH="…/global:$GOPATH"` line. -- Edge: non-global pkgset still gets prepended GOPATH/PATH and overlay block. -- Error: creating an already-existing pkgset still fatals. -**Verification:** New test passes; manual inspection of generated `@global` shows no duplicate prefix. - -### U2. Align installer `system@global` - -**Goal:** Installer no longer copies the buggy append shape. -**Requirements:** R2 -**Dependencies:** U1 (behaviorally aligned; can land in same commit) -**Files:** `binscripts/gvm-installer` -**Approach:** Keep directory creation and `system` env write; `cp` to `system@global`; remove append + `@TODO`. -**Test scenarios:** -- Happy path: after installer with `GOROOT`/system Go present, `system@global` has no trailing duplicate GOPATH/PATH exports beyond what `system` already contains. -**Verification:** Diff `system` vs `system@global` is empty (or only intentional), smoke/CI install still succeeds. - -## Verification Contract - -- Run the new pkgset global regression test via the existing `tf` suite path (or equivalent local invocation). -- Smoke: installer completes; `gvm pkgset create` for a non-global name still works if exercised. -- No ChangeLog bump required unless shipping a release note in the same PR (optional one-liner under Fixed for next version). - -## Definition of Done - -- U1 and U2 landed; `@TODO` removed from installer. -- Regression test covers the global duplication case. -- Issue #8 addressed (close manually if bot lacks permission). diff --git a/scripts/ci-smoke.sh b/scripts/ci-smoke.sh index b045f04..b3938cb 100755 --- a/scripts/ci-smoke.sh +++ b/scripts/ci-smoke.sh @@ -9,7 +9,10 @@ test -n "$GVM_VERSION" test -n "$HEXDUMP_PATH" # system@global is only created when an existing Go was detected at install time if [ -f "$GVM_DEST/gvm/environments/system@global" ]; then - ! grep -q 'global:$GOPATH' "$GVM_DEST/gvm/environments/system@global" + if grep -q 'global:$GOPATH' "$GVM_DEST/gvm/environments/system@global"; then + echo "FAIL: system@global has duplicated global GOPATH prefix" >&2 + exit 1 + fi diff -q "$GVM_DEST/gvm/environments/system" "$GVM_DEST/gvm/environments/system@global" fi gvm install go1.22.12 -B @@ -17,7 +20,10 @@ gvm use go1.22.12 go version | grep -E 'go1\.22\.12' gvm list --porcelain | grep -F 'go1.22.12' # install creates $go@global via pkgset create; must not duplicate global GOPATH -! grep -q 'global:$GOPATH' "$GVM_DEST/gvm/environments/go1.22.12@global" +if grep -q 'global:$GOPATH' "$GVM_DEST/gvm/environments/go1.22.12@global"; then + echo "FAIL: go1.22.12@global has duplicated global GOPATH prefix" >&2 + exit 1 +fi spaced="$GVM_DEST/dir with spaces" mkdir -p "$spaced" cd "$spaced" diff --git a/scripts/install b/scripts/install index 0aecf07..06465eb 100755 --- a/scripts/install +++ b/scripts/install @@ -214,15 +214,31 @@ download_binary() { GO_BINARY_URL="${GO_BINARY_BASE_URL}/${GO_BINARY_FILE}" GO_BINARY_PATH=${GVM_ROOT}/archive/${GO_BINARY_FILE} - if [ ! -f $GO_BINARY_PATH ]; then - curl -s -f -L $GO_BINARY_URL > ${GO_BINARY_PATH} - - if [[ $? -ne 0 ]]; then - display_error "Failed to download binary go" - rm -rf $GO_INSTALL_ROOT - rm -f $GO_BINARY_PATH + if [ ! -f "$GO_BINARY_PATH" ]; then + mkdir -p "${GVM_ROOT}/archive" || { + display_error "Failed to create archive directory" + rm -rf "$GO_INSTALL_ROOT" exit 1 - fi + } + # go.dev occasionally flakes under parallel CI; retry before failing. + _dl_attempt=1 + _dl_max=3 + while [ "${_dl_attempt}" -le "${_dl_max}" ]; do + if curl -sS -f -L --retry 2 --retry-delay 1 \ + -o "${GO_BINARY_PATH}" "${GO_BINARY_URL}"; then + break + fi + rm -f "${GO_BINARY_PATH}" + if [ "${_dl_attempt}" -eq "${_dl_max}" ]; then + display_error "Failed to download binary go" + rm -rf "$GO_INSTALL_ROOT" + exit 1 + fi + display_warning "Binary download failed (attempt ${_dl_attempt}/${_dl_max}); retrying..." + _dl_attempt=$((_dl_attempt + 1)) + sleep "${_dl_attempt}" + done + unset _dl_attempt _dl_max fi tar zxf ${GO_BINARY_PATH} -C $GO_INSTALL_ROOT --strip-components 1 >> "${GVM_ROOT}/logs/go-${GO_NAME}-download-binary" 2>&1 From 5536cf0f1beccd3217bbc6bafe23f315faf530cd Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 19 Jul 2026 12:06:57 +0000 Subject: [PATCH 3/4] fix(test): avoid tf heredoc hang in pkgset global suite tf executes each line as its own command, so `cat < --- .github/workflows/ci.yml | 2 ++ tests/gvm_pkgset_global_comment_test.sh | 13 ++++--------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 940cd84..208d068 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,7 @@ jobs: smoke: name: smoke / ${{ matrix.os }} / ${{ matrix.shell }} runs-on: ${{ matrix.os }} + timeout-minutes: 30 strategy: fail-fast: false matrix: @@ -55,6 +56,7 @@ jobs: suite: name: suite / ${{ matrix.os }} runs-on: ${{ matrix.os }} + timeout-minutes: 45 strategy: fail-fast: false matrix: diff --git a/tests/gvm_pkgset_global_comment_test.sh b/tests/gvm_pkgset_global_comment_test.sh index dd6d2de..0f56d4a 100644 --- a/tests/gvm_pkgset_global_comment_test.sh +++ b/tests/gvm_pkgset_global_comment_test.sh @@ -1,14 +1,9 @@ source $GVM_ROOT/scripts/gvm -## Synthetic Go env whose base file already embeds the global pkgset +## Synthetic Go env whose base file already embeds the global pkgset. +## Note: tf runs each line as its own command — never use multi-line heredocs. mkdir -p "$GVM_ROOT/gos/duptest" "$GVM_ROOT/pkgsets/duptest" "$GVM_ROOT/environments" -cat > "$GVM_ROOT/environments/duptest" < "$GVM_ROOT/environments/duptest" gvm_go_name=duptest "$GVM_ROOT/scripts/pkgset-create" global # status=0 test -f "$GVM_ROOT/environments/duptest@global" # status=0 @@ -18,7 +13,7 @@ diff -q "$GVM_ROOT/environments/duptest" "$GVM_ROOT/environments/duptest@global" ## Non-global pkgsets still prepend paths gvm_go_name=duptest "$GVM_ROOT/scripts/pkgset-create" myset # status=0 -grep 'pkgsets/duptest/myset:\$GOPATH' "$GVM_ROOT/environments/duptest@myset" # status=0 +grep 'pkgsets/duptest/myset:$GOPATH' "$GVM_ROOT/environments/duptest@myset" # status=0 grep 'Package Set-Specific Overrides' "$GVM_ROOT/environments/duptest@myset" # status=0 ## Cleanup From fcf7cd129a7f6bb49026da3453f31dcb6eea9b21 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 19 Jul 2026 12:09:30 +0000 Subject: [PATCH 4/4] chore: keep Cursor rules local-only Remove .cursor/rules from the repo and gitignore .cursor/. AI prompts and rules stay on the machine unless explicitly requested in source control. Co-authored-by: Brian Thompson --- .cursor/rules/no-commit-plan-files.mdc | 15 --------------- .gitignore | 3 ++- 2 files changed, 2 insertions(+), 16 deletions(-) delete mode 100644 .cursor/rules/no-commit-plan-files.mdc diff --git a/.cursor/rules/no-commit-plan-files.mdc b/.cursor/rules/no-commit-plan-files.mdc deleted file mode 100644 index 0e4a3a5..0000000 --- a/.cursor/rules/no-commit-plan-files.mdc +++ /dev/null @@ -1,15 +0,0 @@ ---- -description: Never commit local planning/brainstorm artifacts to the git repo -alwaysApply: true ---- - -# No committed plan files - -Do **not** commit planning or brainstorm artifacts to this repository. - -- Keep plans locally under `docs/plans/` (gitignored) or outside the repo -- Keep brainstorm/requirements drafts under `docs/brainstorms/` (gitignored) or outside the repo -- Do not add `docs/plans/**` or `docs/brainstorms/**` in commits, PRs, or release trees -- Implementation work, tests, and user-facing docs belong in the repo; ce-plan / ce-brainstorm outputs do not - -If a plan was committed by mistake, remove it from the branch and ensure `.gitignore` still covers those paths. diff --git a/.gitignore b/.gitignore index 9e33b27..51837ec 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ scripts/gvm Gemfile.lock .vagrant/ -# Local planning artifacts — do not commit (see .cursor/rules) +# Local-only AI / planning artifacts — do not commit +.cursor/ docs/plans/ docs/brainstorms/