Skip to content

feat(release): add npm package and automated npm publish#4

Merged
Miss-you merged 3 commits into
mainfrom
feat/npm-publish
Feb 18, 2026
Merged

feat(release): add npm package and automated npm publish#4
Miss-you merged 3 commits into
mainfrom
feat/npm-publish

Conversation

@Miss-you

Copy link
Copy Markdown
Owner

Summary

  • Add npm distribution support for codetok so users can install via npm install -g codetok.
  • Add tag-driven automated npm publishing after GitHub Release publishing.

Changes

  • Added npm package scaffold under npm/:
    • npm/package.json
    • npm/bin/codetok.js
    • npm/scripts/install.mjs
    • npm/README.md
    • npm/LICENSE
  • postinstall now downloads the matching binary from GitHub Releases and verifies SHA256 via checksums.txt.
  • Updated release workflow (.github/workflows/release.yml):
    • keep existing GoReleaser release job
    • add publish-npm job (runs after release job)
    • set npm version from git tag (vX.Y.Z -> X.Y.Z) and publish to npm
  • Updated docs:
    • README.md
    • README_zh.md
  • Updated .gitignore for npm package artifacts while preserving tracked launcher script.

Validation

  • npm pack --dry-run (in npm/)
  • make test
  • make lint
  • make vet
  • make build

Notes

  • Requires repository secret NPM_TOKEN for npm publish job.
  • After merge, pushing a v* tag will publish both GitHub Release artifacts and npm package.

Copilot AI review requested due to automatic review settings February 18, 2026 10:53

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adds npm package distribution support for the codetok CLI tool, enabling users to install via npm install -g codetok. The package downloads pre-built binaries from GitHub Releases during postinstall, supporting macOS, Linux, and Windows on x64 and arm64 architectures. The release workflow is extended to automatically publish the npm package after creating GitHub releases.

Changes:

  • Added npm package scaffold with launcher script, postinstall downloader, and package configuration
  • Extended the release workflow to automatically publish to npm after GitHub release creation
  • Updated documentation (README.md and README_zh.md) with npm installation instructions and release automation notes

Reviewed changes

Copilot reviewed 7 out of 10 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
npm/package.json Defines npm package metadata, dependencies, and configuration
npm/bin/codetok.js Node.js launcher script that spawns the downloaded native binary
npm/scripts/install.mjs Postinstall script that downloads and verifies platform-specific binaries from GitHub Releases
npm/README.md Documentation for the npm package installation and troubleshooting
npm/LICENSE MIT license file for the npm package
npm/vendor/.gitkeep Placeholder to ensure vendor directory exists in repository
.github/workflows/release.yml Added publish-npm job to automate npm publishing after GitHub releases
README.md Added npm installation section and release automation notes
README_zh.md Chinese version of README.md updates
.gitignore Updated to track npm launcher script while ignoring downloaded binaries and dependencies

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread npm/scripts/install.mjs Outdated
const vendorDir = path.join(pkgRoot, 'vendor');

const project = 'codetok';
const owner = 'Miss-you';

Copilot AI Feb 18, 2026

Copy link

Choose a reason for hiding this comment

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

The repository owner is inconsistent with the rest of the codebase. Throughout the project (go.mod, README.md, package.json), the repository is referenced as 'miss-you' (all lowercase), but here it's 'Miss-you' (with capital M and Y). While GitHub web URLs are case-insensitive, this inconsistency could cause issues with API calls or downloads. Change to 'miss-you' to match the established convention.

Suggested change
const owner = 'Miss-you';
const owner = 'miss-you';

Copilot uses AI. Check for mistakes.
Comment thread npm/scripts/install.mjs
Comment on lines +159 to +198
async function downloadToFile(url, destPath, redirects = 0) {
if (redirects > maxRedirects) {
throw new Error(`too many redirects while downloading ${url}`);
}

return new Promise((resolve, reject) => {
const req = https.get(
url,
{
headers: {
'User-Agent': 'codetok-npm-installer',
},
},
(res) => {
if (
res.statusCode &&
[301, 302, 303, 307, 308].includes(res.statusCode) &&
res.headers.location
) {
const nextURL = new URL(res.headers.location, url).toString();
res.resume();
downloadToFile(nextURL, destPath, redirects + 1).then(resolve).catch(reject);
return;
}

if (res.statusCode !== 200) {
res.resume();
reject(new Error(`download failed (${res.statusCode}) for ${url}`));
return;
}

const ws = fs.createWriteStream(destPath);
ws.on('error', reject);
ws.on('finish', () => resolve());
res.pipe(ws);
}
);

req.on('error', reject);
});

Copilot AI Feb 18, 2026

Copy link

Choose a reason for hiding this comment

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

The download function lacks timeout handling, which could cause npm installations to hang indefinitely if the download stalls. This is particularly problematic for CI/CD environments and automated installations. Consider adding a timeout (e.g., 30-60 seconds) to the HTTP request using setTimeout on the request object or implementing an AbortController-based timeout mechanism to ensure the installation fails cleanly rather than hanging.

Copilot uses AI. Check for mistakes.
Comment thread npm/scripts/install.mjs Outdated
}

const ws = fs.createWriteStream(destPath);
ws.on('error', reject);

Copilot AI Feb 18, 2026

Copy link

Choose a reason for hiding this comment

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

When the write stream encounters an error, the response stream should be destroyed to prevent memory leaks and ensure clean resource cleanup. Currently, if the write stream fails, the response continues piping data. Add 'res.destroy()' in the write stream error handler to properly clean up the response stream when write operations fail.

Suggested change
ws.on('error', reject);
ws.on('error', (err) => {
res.destroy();
reject(err);
});

Copilot uses AI. Check for mistakes.
env:
TAG: ${{ github.ref_name }}
run: |
VERSION="${TAG#v}"

Copilot AI Feb 18, 2026

Copy link

Choose a reason for hiding this comment

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

The version extraction from the git tag lacks validation. If the tag doesn't match the expected 'vX.Y.Z' format (e.g., if someone pushes 'v1.2' or 'v1.2.3-beta'), the extracted version could be invalid for npm's semantic versioning requirements. Consider adding validation to ensure the extracted version matches npm's semver format before setting it in package.json, or at minimum add a check that the VERSION variable is not empty and contains only valid semver characters.

Suggested change
VERSION="${TAG#v}"
VERSION="${TAG#v}"
# Ensure VERSION is non-empty and matches a valid semantic version
if [ -z "$VERSION" ]; then
echo "Error: VERSION extracted from tag '$TAG' is empty."
exit 1
fi
# Accept versions like 1.2.3 or 1.2.3-beta.1
if ! echo "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$'; then
echo "Error: VERSION '$VERSION' extracted from tag '$TAG' is not a valid semantic version (expected X.Y.Z or X.Y.Z-prerelease)."
exit 1
fi

Copilot uses AI. Check for mistakes.
Comment thread npm/scripts/install.mjs Outdated

const actual = await sha256(filePath);
if (actual !== expected) {
throw new Error(`checksum mismatch for ${archiveName}`);

Copilot AI Feb 18, 2026

Copy link

Choose a reason for hiding this comment

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

The checksum verification error message is not helpful for debugging. When the checksum mismatch occurs, users cannot determine whether the download was corrupted or if there's a mismatch in the release artifacts. Consider including both the expected and actual checksums in the error message (e.g., 'checksum mismatch for ${archiveName}: expected ${expected}, got ${actual}') to help users and maintainers diagnose the issue.

Suggested change
throw new Error(`checksum mismatch for ${archiveName}`);
throw new Error(`checksum mismatch for ${archiveName}: expected ${expected}, got ${actual}`);

Copilot uses AI. Check for mistakes.
@Miss-you
Miss-you merged commit 3c4276f into main Feb 18, 2026
6 checks passed
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