-
Notifications
You must be signed in to change notification settings - Fork 1
feat: add npm distribution with platform-specific packages #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
khooihzhz
wants to merge
3
commits into
main
Choose a base branch
from
feat/npm-distribution
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| { | ||
| "name": "@coingecko/cg-darwin-arm64", | ||
| "version": "0.0.0", | ||
| "description": "CoinGecko CLI - Real Time & Historical Crypto Data (macOS ARM64)", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/coingecko/coingecko-cli.git" | ||
| }, | ||
| "license": "MIT", | ||
| "os": ["darwin"], | ||
| "cpu": ["arm64"], | ||
| "files": ["cg"] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| { | ||
| "name": "@coingecko/cg-darwin-x64", | ||
| "version": "0.0.0", | ||
| "description": "CoinGecko CLI - Real Time & Historical Crypto Data (macOS x64)", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/coingecko/coingecko-cli.git" | ||
| }, | ||
| "license": "MIT", | ||
| "os": ["darwin"], | ||
| "cpu": ["x64"], | ||
| "files": ["cg"] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| { | ||
| "name": "@coingecko/cg-linux-arm64", | ||
| "version": "0.0.0", | ||
| "description": "CoinGecko CLI - Real Time & Historical Crypto Data (Linux ARM64)", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/coingecko/coingecko-cli.git" | ||
| }, | ||
| "license": "MIT", | ||
| "os": ["linux"], | ||
| "cpu": ["arm64"], | ||
| "files": ["cg"] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| { | ||
| "name": "@coingecko/cg-linux-x64", | ||
| "version": "0.0.0", | ||
| "description": "CoinGecko CLI - Real Time & Historical Crypto Data (Linux x64)", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/coingecko/coingecko-cli.git" | ||
| }, | ||
| "license": "MIT", | ||
| "os": ["linux"], | ||
| "cpu": ["x64"], | ||
| "files": ["cg"] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| { | ||
| "name": "@coingecko/cg-win32-arm64", | ||
| "version": "0.0.0", | ||
| "description": "CoinGecko CLI - Real Time & Historical Crypto Data (Windows ARM64)", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/coingecko/coingecko-cli.git" | ||
| }, | ||
| "license": "MIT", | ||
| "os": ["win32"], | ||
| "cpu": ["arm64"], | ||
| "files": ["cg.exe"] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| { | ||
| "name": "@coingecko/cg-win32-x64", | ||
| "version": "0.0.0", | ||
| "description": "CoinGecko CLI - Real Time & Historical Crypto Data (Windows x64)", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/coingecko/coingecko-cli.git" | ||
| }, | ||
| "license": "MIT", | ||
| "os": ["win32"], | ||
| "cpu": ["x64"], | ||
| "files": ["cg.exe"] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| #!/usr/bin/env node | ||
|
|
||
| "use strict"; | ||
|
|
||
| const { execFileSync } = require("child_process"); | ||
| const path = require("path"); | ||
| const os = require("os"); | ||
|
|
||
| // Map Node.js platform/arch to npm package names | ||
| const PLATFORMS = { | ||
| "darwin arm64": "@coingecko/cg-darwin-arm64", | ||
| "darwin x64": "@coingecko/cg-darwin-x64", | ||
| "linux arm64": "@coingecko/cg-linux-arm64", | ||
| "linux x64": "@coingecko/cg-linux-x64", | ||
| "win32 arm64": "@coingecko/cg-win32-arm64", | ||
| "win32 x64": "@coingecko/cg-win32-x64", | ||
| }; | ||
|
|
||
| function getBinaryPath() { | ||
| const platform = os.platform(); | ||
| const arch = os.arch(); | ||
| const key = `${platform} ${arch}`; | ||
| const pkg = PLATFORMS[key]; | ||
|
|
||
| if (!pkg) { | ||
| throw new Error( | ||
| `Unsupported platform: ${platform} ${arch}. ` + | ||
| `Supported: ${Object.keys(PLATFORMS).join(", ")}` | ||
| ); | ||
| } | ||
|
|
||
| const binary = platform === "win32" ? "cg.exe" : "cg"; | ||
|
|
||
| try { | ||
| // resolve the platform package from this package's location | ||
| const pkgDir = path.dirname(require.resolve(`${pkg}/package.json`)); | ||
| return path.join(pkgDir, binary); | ||
| } catch { | ||
| throw new Error( | ||
| `The platform package ${pkg} is not installed. ` + | ||
| `This usually means your package manager excluded optional dependencies. ` + | ||
| `Try reinstalling with: npm install @coingecko/cg` | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| const binary = getBinaryPath(); | ||
|
|
||
| try { | ||
| execFileSync(binary, process.argv.slice(2), { stdio: "inherit" }); | ||
| } catch (err) { | ||
| if (err.status !== undefined) { | ||
| process.exit(err.status); | ||
| } | ||
| throw err; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| { | ||
| "name": "@coingecko/cg", | ||
| "version": "0.0.0", | ||
| "description": "CoinGecko CLI - Real Time & Historical Crypto Data", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/coingecko/coingecko-cli.git" | ||
| }, | ||
| "license": "MIT", | ||
| "bin": { | ||
| "cg": "bin/cg.js" | ||
| }, | ||
| "files": [ | ||
| "bin/cg.js" | ||
| ], | ||
| "optionalDependencies": { | ||
| "@coingecko/cg-darwin-arm64": "0.0.0", | ||
| "@coingecko/cg-darwin-x64": "0.0.0", | ||
| "@coingecko/cg-linux-arm64": "0.0.0", | ||
| "@coingecko/cg-linux-x64": "0.0.0", | ||
| "@coingecko/cg-win32-arm64": "0.0.0", | ||
| "@coingecko/cg-win32-x64": "0.0.0" | ||
| }, | ||
| "engines": { | ||
| "node": ">=20" | ||
| }, | ||
| "keywords": [ | ||
| "coingecko", | ||
| "crypto", | ||
| "cryptocurrency", | ||
| "bitcoin", | ||
| "cli" | ||
| ] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,162 @@ | ||
| #!/bin/sh | ||
| set -eu | ||
|
|
||
| # Publish CoinGecko CLI to npm as platform-specific packages. | ||
| # Called from CI after goreleaser has built the archives. | ||
| # | ||
| # Usage: VERSION=1.2.3 scripts/npm-publish.sh | ||
| # | ||
| # Expects: | ||
| # - goreleaser dist/ directory with archives and checksums.txt | ||
| # - NPM_TOKEN environment variable (or .npmrc already configured) | ||
| # | ||
| # Safety: | ||
| # - Verifies archive checksums against goreleaser's checksums.txt before extracting | ||
| # - Aborts if any platform archive is missing (won't publish broken umbrella) | ||
| # - Skips already-published versions for retry safety after partial failures | ||
| # - Uses node to rewrite package.json versions (works regardless of current value) | ||
| # - Publishes with --provenance for supply-chain verification (requires id-token: write) | ||
|
|
||
| SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" | ||
| ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" | ||
| NPM_DIR="$ROOT_DIR/npm" | ||
| DIST_DIR="$ROOT_DIR/dist" | ||
|
|
||
| if [ -z "${VERSION:-}" ]; then | ||
| echo "Error: VERSION environment variable is required" | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "Publishing @coingecko/cg v${VERSION} to npm" | ||
|
|
||
| # Mapping: goreleaser os_arch -> npm package directory + binary name | ||
| # darwin_arm64 -> cg-darwin-arm64/cg | ||
| # darwin_amd64 -> cg-darwin-x64/cg | ||
| # linux_arm64 -> cg-linux-arm64/cg | ||
| # linux_amd64 -> cg-linux-x64/cg | ||
| # windows_arm64 -> cg-win32-arm64/cg.exe | ||
| # windows_amd64 -> cg-win32-x64/cg.exe | ||
|
|
||
| # set_version <file> <version> [dependency_version] | ||
| # Rewrites version (and optionalDependencies versions) in a package.json. | ||
| set_version() { | ||
| node -e " | ||
| const fs = require('fs'); | ||
| const pkg = JSON.parse(fs.readFileSync('$1', 'utf8')); | ||
| pkg.version = '$2'; | ||
| if ('$3' !== '' && pkg.optionalDependencies) { | ||
| for (const k of Object.keys(pkg.optionalDependencies)) { | ||
| pkg.optionalDependencies[k] = '$3'; | ||
| } | ||
| } | ||
| fs.writeFileSync('$1', JSON.stringify(pkg, null, 2) + '\n'); | ||
| " | ||
| } | ||
|
|
||
| # is_published <package_name> <version> | ||
| # Returns 0 if the exact version is already on the registry. | ||
| is_published() { | ||
| npm view "$1@$2" version >/dev/null 2>&1 | ||
| } | ||
|
|
||
| # verify_checksum <file> | ||
| # Verifies a file against goreleaser's checksums.txt. Aborts on mismatch. | ||
| verify_checksum() { | ||
| local file="$1" | ||
| local filename | ||
| filename=$(basename "$file") | ||
| local expected | ||
| expected=$(grep " ${filename}$" "${DIST_DIR}/checksums.txt" | awk '{print $1}') | ||
| if [ -z "$expected" ]; then | ||
| echo "Error: no checksum entry for ${filename} in checksums.txt" | ||
| exit 1 | ||
| fi | ||
| local actual | ||
| if ! command -v sha256sum >/dev/null 2>&1; then | ||
| echo "Error: sha256sum not found" | ||
| exit 1 | ||
| fi | ||
| actual=$(sha256sum "$file" | awk '{print $1}') | ||
| if [ "$expected" != "$actual" ]; then | ||
| echo "Error: checksum mismatch for ${filename}" | ||
| echo " Expected: ${expected}" | ||
| echo " Actual: ${actual}" | ||
| exit 1 | ||
| fi | ||
| } | ||
|
|
||
| # Phase 1: Verify all platform archives exist and match checksums | ||
| echo "Verifying platform archives..." | ||
| CHECKSUMS_FILE="${DIST_DIR}/checksums.txt" | ||
| if [ ! -f "$CHECKSUMS_FILE" ]; then | ||
| echo "Error: ${CHECKSUMS_FILE} not found. Cannot verify archive integrity." | ||
| exit 1 | ||
| fi | ||
| PLATFORMS="darwin:arm64:cg-darwin-arm64:cg:tar.gz | ||
| darwin:amd64:cg-darwin-x64:cg:tar.gz | ||
| linux:arm64:cg-linux-arm64:cg:tar.gz | ||
| linux:amd64:cg-linux-x64:cg:tar.gz | ||
| windows:arm64:cg-win32-arm64:cg.exe:zip | ||
| windows:amd64:cg-win32-x64:cg.exe:zip" | ||
|
|
||
| MISSING="" | ||
| echo "$PLATFORMS" | while IFS=: read -r goos goarch npm_dir binary ext; do | ||
| archive="${DIST_DIR}/cg_${VERSION}_${goos}_${goarch}.${ext}" | ||
| if [ ! -f "$archive" ]; then | ||
| echo " MISSING: ${archive}" | ||
| touch "${DIST_DIR}/.npm-missing" | ||
| else | ||
| verify_checksum "$archive" | ||
| fi | ||
| done | ||
|
|
||
| if [ -f "${DIST_DIR}/.npm-missing" ]; then | ||
| rm -f "${DIST_DIR}/.npm-missing" | ||
| echo "Error: one or more platform archives are missing. Aborting npm publish." | ||
| exit 1 | ||
| fi | ||
| echo " All archives present and checksums verified." | ||
|
|
||
| # Phase 2: Extract, version-stamp, and publish each platform package | ||
| echo "$PLATFORMS" | while IFS=: read -r goos goarch npm_dir binary ext; do | ||
| pkg_name="@coingecko/${npm_dir}" | ||
| pkg_dir="${NPM_DIR}/${npm_dir}" | ||
| archive="cg_${VERSION}_${goos}_${goarch}.${ext}" | ||
| archive_path="${DIST_DIR}/${archive}" | ||
|
|
||
| if is_published "$pkg_name" "$VERSION"; then | ||
| echo " ${pkg_name}@${VERSION} already published, skipping" | ||
| continue | ||
| fi | ||
|
|
||
| echo " Extracting ${archive}..." | ||
| tmpdir=$(mktemp -d) | ||
| if [ "$ext" = "tar.gz" ]; then | ||
| tar -xzf "$archive_path" -C "$tmpdir" | ||
| else | ||
| unzip -q "$archive_path" -d "$tmpdir" | ||
| fi | ||
|
|
||
| cp "${tmpdir}/${binary}" "${pkg_dir}/${binary}" | ||
| chmod +x "${pkg_dir}/${binary}" | ||
| rm -rf "$tmpdir" | ||
|
|
||
| set_version "${pkg_dir}/package.json" "$VERSION" "" | ||
|
|
||
| echo " Publishing ${pkg_name}@${VERSION}..." | ||
| npm publish "${pkg_dir}" --access public --provenance | ||
| done | ||
|
|
||
| # Phase 3: Version-stamp and publish the umbrella package | ||
| UMBRELLA_DIR="${NPM_DIR}/cg" | ||
|
|
||
| if is_published "@coingecko/cg" "$VERSION"; then | ||
| echo " @coingecko/cg@${VERSION} already published, skipping" | ||
| else | ||
| set_version "${UMBRELLA_DIR}/package.json" "$VERSION" "$VERSION" | ||
|
|
||
| echo " Publishing @coingecko/cg@${VERSION}..." | ||
| npm publish "${UMBRELLA_DIR}" --access public --provenance | ||
khooihzhz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| fi | ||
|
|
||
| echo "Done! Published @coingecko/cg@${VERSION} and all platform packages." | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.