Add npm publishing and update documentation#719
Conversation
PR #719 Multi-Agent Review: "Add npm publishing and update documentation"Repository: kosli-dev/cli | Author: jbrejner | Status: DRAFT
Branch: The Review PanelFour agents with distinct personas reviewed this PR independently, then their findings were synthesized. Here's who was on the panel:
Unanimous Verdict: DO NOT MERGE (yet)All four agents independently reached the same conclusion: the PR has a sound architectural foundation (the esbuild-style per-platform binary distribution pattern is well-chosen) but has several blocking issues that would result in a non-functional npm package if published today. This aligns with the PR's own DRAFT status and the author's listed TODOs. The Big Three: Issues Every Agent FlaggedThese three issues were independently identified by all four reviewers, making them the highest-confidence findings: 1. The Missing
|
|
Claude finished @jbrejner's task in 3m 54s —— View job Code Review: Add npm publishing and update documentation
Static Analysis
SummaryThe PR is in solid shape after the many rounds of feedback. The esbuild-style platform-package pattern is well-chosen for enterprise/air-gapped environments, the rationale is sound, and most earlier review findings have been addressed. Here's what remains: Remaining Issues1. 2. Tree diagram formatting ( 3. What's Working Well
|
cec0e37 to
43e9885
Compare
- Clean up temp file on jq/mv failure for wrapper package.json update, consistent with the platform loop - Pass --provenance to npm publish when running in GitHub Actions
…SLI_GORELEASERPRO }} — that's the standard way the goreleaser-action picks up the pro license.
- Test npm install -g @kosli/cli on all 6 supported platforms - Trigger on release (published) to test newly published packages - Also trigger on push/PR to npm/**, .goreleaser.yml, and scripts/npm-publish.sh
… but it's not available in all GitHub org configuration
4bc3fb0 to
6c960ed
Compare
| # Also update the optionalDependencies version references in the wrapper | ||
| tmp="$(mktemp)" | ||
| jq --arg v "$VERSION" '.optionalDependencies = (.optionalDependencies | with_entries(.value = $v))' \ | ||
| npm/wrapper/package.json > "$tmp" && mv "$tmp" npm/wrapper/package.json || { rm -f "$tmp"; exit 1; } |
There was a problem hiding this comment.
Bug: Missing cleanup on jq failure. The platform loop on line 38 has || { rm -f "$tmp"; exit 1; }, but this wrapper update doesn't. If jq or mv fails, the temp file leaks and the wrapper package.json is silently left unchanged.
| npm/wrapper/package.json > "$tmp" && mv "$tmp" npm/wrapper/package.json || { rm -f "$tmp"; exit 1; } | |
| jq --arg v "$VERSION" '.optionalDependencies = (.optionalDependencies | with_entries(.value = $v))' \ | |
| npm/wrapper/package.json > "$tmp" && mv "$tmp" npm/wrapper/package.json || { rm -f "$tmp"; exit 1; } |
There was a problem hiding this comment.
Already fixed — line 44 has || { rm -f "$tmp"; exit 1; }. No change needed.
npm pack silently succeeds even if the binary is absent, producing a broken package. Each platform package now checks for bin/kosli (or bin/kosli.exe on Windows) before packing; the wrapper also checks for install.js.
I do not understand your question ? |
… for executable check to address @dangrondahl ai review kosli version false negatives in install.js
| "install.js" | ||
| ], | ||
| "scripts": { | ||
| "prepack": "test -f bin/kosli || (echo 'ERROR: bin/kosli is missing' && exit 1) && test -f install.js || (echo 'ERROR: install.js is missing' && exit 1)", |
There was a problem hiding this comment.
Bug: Misleading second error when bin/kosli is missing. Due to shell operator precedence, if bin/kosli is missing, the (exit 1) only exits the subshell — then && short-circuits, then the second || triggers, printing "ERROR: install.js is missing" even though install.js may be fine.
Use && to chain the two checks independently:
| "prepack": "test -f bin/kosli || (echo 'ERROR: bin/kosli is missing' && exit 1) && test -f install.js || (echo 'ERROR: install.js is missing' && exit 1)", | |
| "prepack": "{ test -f bin/kosli || { echo 'ERROR: bin/kosli is missing' && exit 1; }; } && { test -f install.js || { echo 'ERROR: install.js is missing' && exit 1; }; }" |
Or simpler — use braces {} instead of subshells () so exit 1 terminates the whole script, not just the subshell.
| │ ├── bin/kosli # the native binary — see below | ||
| │ └── package.json # declares os/cpu fields for platform filtering | ||
| ├── cli-win32-arm64/ # @kosli/cli-win32-arm64 | ||
| │ ├── bin/kosli.exe # the native binary — see below |
There was a problem hiding this comment.
Nit: Tree diagram formatting. Two └── at the same indentation level — the second-to-last should use ├──:
| │ ├── bin/kosli.exe # the native binary — see below | |
| ├── cli-win32-arm64/ # @kosli/cli-win32-arm64 |
There was a problem hiding this comment.
The tree is correct as-is. cli-win32-arm64 uses ├── (not last) and cli-win32-x64 uses └── (last item). No change needed.
| - 'scripts/npm-publish.sh' | ||
| workflow_dispatch: | ||
| release: | ||
| types: [published] |
There was a problem hiding this comment.
Confirm: release: [published] trigger is intentional? The test-npm job's logic handles release events specifically (installing @latest vs @snapshot), so this looks intentional. But @mbevc1 also flagged this — worth a quick confirmation that this is desired.
Code Review: PR #719Phase 1: Static AnalysisAll clear — Phase 2: Issues Found
The version-injection loop (line 39) was fixed to exclude done < <(find npm -name package.json ! -path '*/node_modules/*')But the package list build (line 50) still lacks the same guard: done < <(find npm -name package.json ! -path "npm/wrapper/*" | sort)If done < <(find npm -name package.json ! -path "npm/wrapper/*" ! -path "*/node_modules/*" | sort)Phase 3: What looks good
🤖 Generated with Claude Code |
Fixed — |
|
Re: repeated tree diagram comments on npm/README.md — the tree is correct. |
* Changes required by Gorelase version > 2 * npm-publish script supports conditional publishing. If gorelease in not in "Release" mode, npm packages are not pushed, so we can avoid multitudes of snapshot packages being pushed to public registry * Create npm packages after goreleaser via a hook script The hook runs after. If goreaser is not in release mode, npm will build in dry-run mode, so the packages are not pushed to registry * Update documentation with NPM installation instructions * Switch npm package scope to @kosli * Fix: Add the missing bin/kosli JS Shim * Fix: Token Variable Mismatch * Fix: Silent Postinstall Failures * Update npm/README.md Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> * refactor(npm-publish): replace sed/perl with jq and harden publish script - Use jq instead of sed/perl for JSON version updates (portable across macOS and Linux, handles JSON correctly) - Separate pack and publish into two distinct phases so all packages are packed before any are published - Add npm_publish_with_retry with exponential backoff (3 attempts) - Fail fast with clear error messages on pack or publish failure * Fix: Frontmatter formatting * Consistent formatting of package.json files * Include npm packages in binary provenance processing * Add directory and engines specification to packages * Documention updates: - npx is not supported - package @kosli/cli should be used to install * Fix three issues in npm postinstall and publish script - postinstall: exit 1 on unsupported platform to match bin/kosli shim behaviour - npm-publish.sh: use process substitution instead of pipe to while loop so set -e catches failures inside the loop - npm-publish.sh: fix out-of-scope max_attempts variable in publish error message * Update scripts/npm-publish.sh Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> * Integrate npm package build and publish into GoReleaser pipeline - Copy each platform binary into its npm package dir via per-build post hooks - Run npm-publish.sh after release (dry-run on snapshots) via after hook - Clean npm bin dirs and tarballs before each build via before hooks * Update scripts/npm-publish.sh Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> * Update scripts/npm-publish.sh Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> * Update scripts/npm-publish.sh Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> * Update scripts/npm-publish.sh Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> * Add --provenance flag to npm publish when running in GitHub Actions * Fix temp file leak and add npm provenance in GitHub Actions - Clean up temp file on jq/mv failure for wrapper package.json update, consistent with the platform loop - Pass --provenance to npm publish when running in GitHub Actions * Added distribution: goreleaser-pro and GORELEASER_KEY: ${{ secrets.KOSLI_GORELEASERPRO }} — that's the standard way the goreleaser-action picks up the pro license. * Add npm installation test job to install-script-tests workflow - Test npm install -g @kosli/cli on all 6 supported platforms - Trigger on release (published) to test newly published packages - Also trigger on push/PR to npm/**, .goreleaser.yml, and scripts/npm-publish.sh * Select npm tag snapshot for now * Removed macos-13. macos-13 is the only GitHub-hosted x64 macOS runner but it's not available in all GitHub org configuration * Refine dry-run condition in npm-publish script for clarity * Add prepack scripts to fail fast when binary is missing npm pack silently succeeds even if the binary is absent, producing a broken package. Each platform package now checks for bin/kosli (or bin/kosli.exe on Windows) before packing; the wrapper also checks for install.js. * Exclude node_modules from package.json search in npm-publish script * Refactor binary validation in postinstall script to use fs.accessSync for executable check to address @dangrondahl ai review kosli version false negatives in install.js --------- Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Distribute kosli cli as npm package.
Install globally with
npm install -g @kosli/cliThe above will install the wrapper package which detects the current platform and architecture and then pull the appriate package with the correct binary.
Testable packages exist, they are tagged with "snapshot" so you can test with
npm install -g @kosli/cli --tag snapshot