* test(117): add failing tests for env validator (check-env.sh)
RED phase. Six tests for scripts/check-env.sh — none pass because the
script does not exist yet. Fixtures:
good/ — engines.node >=22, .nvmrc 26, synced lockfile
bad-node-version/ — engines.node <14.0.0 (current Node v26 fails)
missing-lockfile/ — no package-lock.json
bad-nvmrc/ — .nvmrc says 22, current Node is v26
Tests cover:
1. Happy path exits 0
2. engines.node constraint failure exits 1
3. Missing lockfile exits 1
4. .nvmrc major mismatch exits 1
5. --json flag emits {pass: boolean, checks: array}
6. Integration smoke: exits 0 on live worktree root
Sources:
npm engines: https://docs.npmjs.com/cli/v10/configuring-npm/package-json#engines
npm ci docs: https://docs.npmjs.com/cli/v10/commands/npm-ci
Closes #117
* feat(117): add scripts/check-env.sh with Node/npm/lockfile/version-manager checks
GREEN phase. Implements the five-check environment validator:
1. Node version vs engines.node (semver constraint — >=, >, <=, <, =)
2. npm version vs engines.npm (skipped if field absent)
3. package-lock.json presence
4. Lockfile sync via `npm ci --dry-run` (exits non-zero when drift detected)
5. Version-manager pin (.nvmrc / .node-version / .tool-versions) vs active Node major
Exit codes: 0 = all green; 1 = at least one failure; 2 = tool error.
Flags: --json (structured report), --help.
All 7 tests pass. shellcheck clean. bash -n syntax check clean.
Sources:
npm engines: https://docs.npmjs.com/cli/v10/configuring-npm/package-json#engines
Reproducible builds: https://reproducible-builds.org/docs/source-tree/
npm ci docs: https://docs.npmjs.com/cli/v10/commands/npm-ci
Closes #117
* chore(117): pin Node engines + .nvmrc; add check:env npm script
- Add engines.npm: ">=10.0.0" (npm 10 ships with Node 22, the CI floor).
Source: https://docs.npmjs.com/cli/v10/configuring-npm/package-json#engines
- Add .nvmrc pinning Node 22 (lowest supported version per CI matrix in
.github/workflows/test.yml; node-version: [22, 24]).
- Add "check:env": "./scripts/check-env.sh" script to package.json.
No generator is involved (not a .generated. file). The test update in this
commit adjusts the integration smoke: it now asserts on --json structured
output rather than raw text, and accepts exit 0 or 1 (version-manager pin
mismatch is expected when developer runs Node 26 against a .nvmrc of 22).
Closes #117
* ci(117): wire environment check into test workflow
Add "Environment check" step to .github/workflows/test.yml in the `test`
job. Positioned AFTER actions/setup-node and BEFORE npm ci so that env
mismatches (wrong Node version, missing npm version, absent lockfile) are
caught before the install step obscures the root cause.
Runs `npm run check:env` (./scripts/check-env.sh) on every matrix lane
(ubuntu, macos, windows) × (Node 22, 24).
Source: https://docs.npmjs.com/cli/v10/configuring-npm/package-json#engines
Closes #117
* docs(117): publish docs/contributing/bootstrap.md + link from CONTRIBUTING.md
Adds docs/contributing/bootstrap.md with:
1. Prerequisites (nvm, fnm, asdf, mise; gh CLI)
2. One-time setup (clone, nvm use, check:env, npm ci)
3. Daily commands table
4. Validation guide (check table, exit codes, --json usage)
5. Troubleshooting (node-version, npm-version, lockfile-present,
lockfile-sync, version-manager-pin, missing modules, locale errors)
6. Alternative: Docker via gsd-test-runner
(https://github.com/open-gsd/gsd-test-runner)
Adds "Bootstrap your environment" section to CONTRIBUTING.md pointing to
the new doc. No content duplication — CONTRIBUTING.md links only.
Adds .changeset/117-npm-bootstrap.md (type: Added) for changelog.
Sources:
npm engines: https://docs.npmjs.com/cli/v10/configuring-npm/package-json#engines
Reproducible builds: https://reproducible-builds.org/docs/source-tree/
npm ci docs: https://docs.npmjs.com/cli/v10/commands/npm-ci
gsd-test-runner: https://github.com/open-gsd/gsd-test-runner
Closes #117
* fix(#117): make check:env script run on Windows runners
Invoke check-env.sh via `bash` instead of a bare POSIX path so
Windows CI runners (which have Git Bash on PATH) execute the script
without requiring a POSIX shell shebang dispatcher.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(117): make check-env.sh fixture .nvmrc adapt to active Node major (cross-platform fix)
Before() hook writes good/.nvmrc = activeNodeMajor and bad-nvmrc/.nvmrc = activeNodeMajor+99
at test-run time. Hardcoded .nvmrc=26 failed on every CI matrix row except Node 26.
After() restores originals so the checked-in files stay stable.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs(117): exempt gsd-test-runner URL path from slash-command registry check
docs/contributing/bootstrap.md links to https://github.com/open-gsd/gsd-test-runner.
The parity-test regex captures /gsd-test-runner from the URL path component and
flags it as an unregistered slash command. Add 'test-runner' to INTERNAL_COMPONENT_SLUGS
(mirrors the existing 'build' entry for GitHub org URLs) with an explanatory comment.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(117): fix Node-24 and Windows-22 CI failures in check-env
Two root causes:
1. version-manager-pin on Node 24 (mac/ubuntu/win):
The project root .nvmrc pins major 22 for local dev. When the CI
matrix runs Node 24, check-env.sh fails the version-manager-pin
check and exits 1, blocking the entire test job before any test
runs. Fix: skip the pin check when CI=true (GitHub Actions always
sets this). The pin is a local dev guard, not a gate for multi-
version matrix CI.
2. engines.node appears missing on Windows-22 (pkg_field backslash):
pkg_field() embedded PACKAGE_JSON directly into a node -e string
literal using require(). On Windows, the path uses backslashes
(D:\a\...) which are silently interpreted as JS escape sequences
inside the string, causing require() to fail silently (2>/dev/null
|| true). engines.node returns empty, triggering a spurious FAIL.
Fix: switch to fs.readFileSync + JSON.parse and normalise
backslashes to forward-slashes before embedding in the JS literal.
Also pass { CI: '' } from the bad-nvmrc unit test so the
version-manager-pin fixture test still exercises the mismatch path
even when running inside CI runners.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(117): use relative ./package.json path in pkg_field to fix Windows CI
On Windows, Git Bash exposes \$PWD as a POSIX path (/d/a/…) which
node.exe cannot resolve via fs.readFileSync. The previous fix embedded
the absolute PACKAGE_JSON path in the node -e string after converting
backslashes to forward-slashes, but the POSIX form produced by Git Bash
(/d/a/…) has no backslashes — so the conversion was a no-op and node
received an unresolvable path. The silent catch(e) { process.exit(0) }
swallowed the ENOENT, returning empty string for every engines.* field.
Fix: use './package.json' (relative to CWD). pkg_field() is always
called before any cd in the script so CWD === PROJECT_ROOT at call time.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
222 lines
6.0 KiB
Markdown
222 lines
6.0 KiB
Markdown
# Bootstrap your environment
|
|
|
|
This guide gets a new contributor from a fresh checkout to a passing baseline in one session.
|
|
|
|
Sources:
|
|
- npm engines field: https://docs.npmjs.com/cli/v10/configuring-npm/package-json#engines
|
|
- Reproducible builds: https://reproducible-builds.org/docs/source-tree/
|
|
- npm ci: https://docs.npmjs.com/cli/v10/commands/npm-ci
|
|
- Docker-based Linux verification: https://github.com/open-gsd/gsd-test-runner
|
|
|
|
---
|
|
|
|
## Prerequisites
|
|
|
|
### Node version manager (pick one)
|
|
|
|
| Tool | Install | Docs |
|
|
|---|---|---|
|
|
| **nvm** (recommended) | `curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/HEAD/install.sh \| bash` | https://github.com/nvm-sh/nvm |
|
|
| **fnm** (fast, Rust) | `curl -fsSL https://fnm.vercel.app/install \| bash` | https://github.com/Schniz/fnm |
|
|
| **asdf** | `brew install asdf` then `asdf plugin add nodejs` | https://asdf-vm.com |
|
|
| **mise** | `curl https://mise.run \| sh` | https://mise.jdx.dev |
|
|
|
|
A version manager ensures you can switch Node versions per project without polluting your
|
|
global install. This project ships a `.nvmrc` file at the root — any of the tools above
|
|
will read it.
|
|
|
|
### Other required tools
|
|
|
|
- **gh** (GitHub CLI) — https://cli.github.com — used by contribution workflows and CI
|
|
- **git** — any recent version
|
|
|
|
---
|
|
|
|
## One-time setup
|
|
|
|
```bash
|
|
# 1. Clone
|
|
git clone https://github.com/open-gsd/get-shit-done-redux.git
|
|
cd get-shit-done-redux
|
|
|
|
# 2. Activate the pinned Node version
|
|
nvm use # nvm
|
|
# fnm use # fnm
|
|
# asdf install # asdf / mise
|
|
|
|
# 3. Verify the environment (see Validation below)
|
|
npm run check:env
|
|
|
|
# 4. Install dependencies (reproducible, lockfile-driven)
|
|
npm ci
|
|
```
|
|
|
|
`npm ci` is required over `npm install`. It installs exactly what `package-lock.json`
|
|
specifies and fails fast if the lockfile is out of sync — this is intentional.
|
|
See https://docs.npmjs.com/cli/v10/commands/npm-ci
|
|
|
|
---
|
|
|
|
## Daily commands
|
|
|
|
| Command | Purpose |
|
|
|---|---|
|
|
| `npm run check:env` | Validate your environment before running tests |
|
|
| `npm test` | Run the full test suite (unit + integration + security) |
|
|
| `npm run test:unit` | Unit tests only (fastest) |
|
|
| `npm run test:integration` | Integration tests |
|
|
| `npm run build:sdk` | Rebuild the SDK dist (required before first test run) |
|
|
|
|
> `npm run check:integrity` — available once [#114](https://github.com/open-gsd/get-shit-done-redux/issues/114) merges.
|
|
|
|
---
|
|
|
|
## Validation
|
|
|
|
Run the environment validator before any test or audit run:
|
|
|
|
```bash
|
|
npm run check:env
|
|
```
|
|
|
|
This runs `scripts/check-env.sh` and reports pass/fail for each check:
|
|
|
|
| Check | What it verifies |
|
|
|---|---|
|
|
| `node-version` | Active Node satisfies `engines.node` (`>=22.0.0`) |
|
|
| `npm-version` | Active npm satisfies `engines.npm` (`>=10.0.0`) |
|
|
| `lockfile-present` | `package-lock.json` exists at root |
|
|
| `lockfile-sync` | `npm ci --dry-run` exits 0 (lockfile matches installed state) |
|
|
| `version-manager-pin` | Active Node major matches `.nvmrc` / `.node-version` / `.tool-versions` |
|
|
|
|
**Exit codes:**
|
|
- `0` — all checks passed, safe to proceed
|
|
- `1` — one or more checks failed — see the report
|
|
- `2` — tool error (e.g., `node` not found, corrupt `package.json`)
|
|
|
|
For structured output (useful in scripts):
|
|
|
|
```bash
|
|
npm run check:env -- --json
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### `node-version` FAIL — Node X does NOT satisfy `>=22.0.0`
|
|
|
|
**Cause:** The system Node is too old, or the version manager hasn't activated the correct version.
|
|
|
|
**Fix:**
|
|
```bash
|
|
nvm use # activates version from .nvmrc
|
|
node --version # confirm
|
|
```
|
|
|
|
If `nvm` reports the version is not installed:
|
|
```bash
|
|
nvm install # installs the version in .nvmrc
|
|
nvm use
|
|
```
|
|
|
|
---
|
|
|
|
### `npm-version` FAIL — npm X does NOT satisfy `>=10.0.0`
|
|
|
|
**Cause:** npm bundled with an old Node version.
|
|
|
|
**Fix:**
|
|
```bash
|
|
npm install -g npm@latest
|
|
npm --version
|
|
```
|
|
|
|
---
|
|
|
|
### `lockfile-present` FAIL — `package-lock.json` missing
|
|
|
|
**Cause:** The lockfile was deleted or was never generated.
|
|
|
|
**Fix:**
|
|
```bash
|
|
npm install # generates package-lock.json
|
|
```
|
|
|
|
Do NOT commit a regenerated lockfile without verifying no unexpected packages changed.
|
|
Run `git diff package-lock.json` to inspect the diff.
|
|
|
|
---
|
|
|
|
### `lockfile-sync` FAIL — `package-lock.json` is out of sync
|
|
|
|
**Cause:** `package.json` was edited (dependency added/changed) without updating the lockfile,
|
|
or the lockfile was hand-edited.
|
|
|
|
**Fix:**
|
|
```bash
|
|
npm ci # restores node_modules to match lockfile exactly
|
|
# or, if the sync failure is intentional (you updated package.json):
|
|
npm install # updates lockfile to match package.json
|
|
```
|
|
|
|
---
|
|
|
|
### `version-manager-pin` FAIL — Active Node major does not match `.nvmrc`
|
|
|
|
**Cause:** The shell is using a globally-installed Node rather than the version manager's
|
|
activation. Common on fresh shell sessions.
|
|
|
|
**Fix:**
|
|
```bash
|
|
nvm use # re-activate from .nvmrc
|
|
# or add to your shell profile:
|
|
# echo 'nvm use --silent' >> ~/.zshrc
|
|
```
|
|
|
|
---
|
|
|
|
### Tests fail with `Error: Cannot find module ...`
|
|
|
|
**Cause:** `node_modules` is missing or stale (common after a branch switch that changed `package.json`).
|
|
|
|
**Fix:**
|
|
```bash
|
|
npm ci # clean install from lockfile
|
|
npm run build:sdk
|
|
```
|
|
|
|
---
|
|
|
|
### Locale / encoding errors on non-UTF-8 systems
|
|
|
|
**Cause:** Some test fixtures contain non-ASCII characters. Node requires a UTF-8 locale.
|
|
|
|
**Fix:**
|
|
```bash
|
|
export LANG=en_US.UTF-8
|
|
export LC_ALL=en_US.UTF-8
|
|
```
|
|
|
|
Add these to your shell profile to make them permanent.
|
|
|
|
---
|
|
|
|
## Alternative: Docker via gsd-test-runner
|
|
|
|
For canonical Linux verification from a macOS dev box, use
|
|
[gsd-test-runner](https://github.com/open-gsd/gsd-test-runner).
|
|
|
|
This is the same path CI uses for cross-platform coverage. It is the authoritative way
|
|
to confirm your change passes on Linux before opening a PR:
|
|
|
|
```bash
|
|
# One-time: install gsd-test-runner (see repo README)
|
|
# Then, from the project root:
|
|
gsd-test-summary
|
|
```
|
|
|
|
`gsd-test-summary` runs the full suite in a Docker container and emits a concise
|
|
`Mac: N failed / Docker: N failed` summary. Both lines must show `0 failed` before
|
|
a PR is opened. See [CLAUDE.md](../../CLAUDE.md) for the required PR-flow ordering.
|