From 624e4f27f25a5feb35dc2ed45b2426db36a2e9bf Mon Sep 17 00:00:00 2001 From: Marco Pesani Date: Wed, 1 Apr 2026 01:31:32 +0200 Subject: [PATCH 1/3] ci: publish semver prereleases with npm dist-tag beta Made-with: Cursor --- .github/workflows/npm-publish.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 053534b..9667ab2 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -23,4 +23,13 @@ jobs: - run: pnpm format - run: pnpm test - run: pnpm build - - run: pnpm publish --provenance --access public --no-git-checks + - name: Publish to npm + run: | + VERSION=$(node -p "require('./package.json').version") + if [[ "$VERSION" == *-* ]]; then + echo "Publishing prerelease ${VERSION} with dist-tag beta (npm install @bitrefill/cli@beta)" + pnpm publish --provenance --access public --no-git-checks --tag beta + else + echo "Publishing ${VERSION} as latest" + pnpm publish --provenance --access public --no-git-checks + fi From 7ae861273a014905002c27bfe0d00dfa4e2ff9b5 Mon Sep 17 00:00:00 2001 From: Marco Pesani Date: Wed, 1 Apr 2026 01:31:33 +0200 Subject: [PATCH 2/3] docs: add GitHub Release and npm publishing guide Made-with: Cursor --- .github/RELEASING.md | 39 +++++++++++++++++++++++++++++++++++++++ README.md | 2 ++ 2 files changed, 41 insertions(+) create mode 100644 .github/RELEASING.md diff --git a/.github/RELEASING.md b/.github/RELEASING.md new file mode 100644 index 0000000..e1ea09e --- /dev/null +++ b/.github/RELEASING.md @@ -0,0 +1,39 @@ +# Releasing `@bitrefill/cli` to npm + +Publishing runs automatically when a **GitHub Release** is published (see [npm-publish.yml](./workflows/npm-publish.yml)). + +## Prerelease (e.g. `0.2.0-beta.0`) + +1. Merge the version bump on `master` (or your release branch). `package.json` must use a **semver prerelease** (a hyphen in the version, e.g. `0.2.0-beta.0`, `0.2.0-rc.1`). +2. Create and push an annotated tag matching the version: + + ```bash + git checkout master && git pull + git tag -a v0.2.0-beta.0 -m "v0.2.0-beta.0" + git push origin v0.2.0-beta.0 + ``` + +3. On GitHub: **Releases → Draft a new release → Choose tag `v0.2.0-beta.0` →** describe changes → check **Set as a pre-release** (optional but recommended) → **Publish release**. + +4. The workflow publishes to npm with the **`beta`** dist-tag so `latest` stays on the last stable version. Install with: + + ```bash + npm install -g @bitrefill/cli@beta + ``` + +## Stable release (e.g. `0.2.0`) + +1. Merge `package.json` version **`0.2.0`** (no prerelease suffix) and sync CLI/MCP version strings in `src/` if you still duplicate them. +2. Tag and push: + + ```bash + git tag -a v0.2.0 -m "v0.2.0" + git push origin v0.2.0 + ``` + +3. **Publish release** on GitHub (not marked as pre-release). The workflow publishes as **latest**. + +## Requirements + +- **npm:** [Trusted publishing](https://docs.npmjs.com/trusted-publishers) (OIDC) for this repo, or a valid `NPM_TOKEN` if your org uses classic tokens instead. +- **Version:** The tag should match the commit that contains the same `version` in `package.json` as what you intend to ship. diff --git a/README.md b/README.md index a994419..b7be51d 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,8 @@ pnpm build # Compile to dist/ pnpm dev -- --help # Run CLI via tsx without building ``` +Publishing to npm is triggered by [GitHub Releases](https://github.com/bitrefill/cli/releases); see [.github/RELEASING.md](.github/RELEASING.md). + ## Paying **Flow:** `get-product-details` → pick `product_id` + `package_id` → `buy-products` with `--cart_items` and `--payment_method`. From 9a62b3535dafe8dd35eccc66dac0691ba0a3e610 Mon Sep 17 00:00:00 2001 From: Marco Pesani Date: Wed, 1 Apr 2026 01:31:35 +0200 Subject: [PATCH 3/3] chore: bump version to 0.2.0-beta.0 Made-with: Cursor --- package.json | 2 +- src/index.ts | 17 +++++++++++++---- src/init.ts | 5 ++++- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 0edc479..fdbd559 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@bitrefill/cli", - "version": "0.1.1", + "version": "0.2.0-beta.0", "description": "Bitrefill - browse, buy, and manage gift cards, mobile top-ups, and eSIMs", "type": "module", "bin": { diff --git a/src/index.ts b/src/index.ts index 260fdbd..23d63b7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -224,7 +224,10 @@ async function createMcpClient( }; if (!useOAuth) { - const c = new Client({ name: 'bitrefill-cli', version: '0.1.1' }); + const c = new Client({ + name: 'bitrefill-cli', + version: '0.2.0-beta.0', + }); c.onerror = suppressNoise; const t = new StreamableHTTPClientTransport(new URL(url)); await c.connect(t); @@ -234,7 +237,10 @@ async function createMcpClient( const authProvider = createOAuthProvider(url, formatter); const tryConnect = async () => { - const c = new Client({ name: 'bitrefill-cli', version: '0.1.1' }); + const c = new Client({ + name: 'bitrefill-cli', + version: '0.2.0-beta.0', + }); c.onerror = suppressNoise; const t = new StreamableHTTPClientTransport(new URL(url), { authProvider, @@ -252,7 +258,10 @@ async function createMcpClient( const code = await waitForCallback(); formatter.info('Authorization code received.'); - const c = new Client({ name: 'bitrefill-cli', version: '0.1.1' }); + const c = new Client({ + name: 'bitrefill-cli', + version: '0.2.0-beta.0', + }); c.onerror = suppressNoise; const t = new StreamableHTTPClientTransport(new URL(url), { authProvider, @@ -359,7 +368,7 @@ async function main(): Promise { .description( 'Bitrefill CLI - browse, buy, and manage gift cards, mobile top-ups, and eSIMs.\n\nTerms: https://www.bitrefill.com/terms\nPrivacy: https://www.bitrefill.com/privacy' ) - .version('0.1.1') + .version('0.2.0-beta.0') .option( '--api-key ', 'Bitrefill API key (overrides BITREFILL_API_KEY env var)' diff --git a/src/init.ts b/src/init.ts index 2531e01..b477cea 100644 --- a/src/init.ts +++ b/src/init.ts @@ -106,7 +106,10 @@ function resolveInitApiKey(opts: InitOptions): string | undefined { async function validateApiKey(apiKey: string): Promise<{ tools: Tool[] }> { const url = `${BASE_MCP_URL}/${apiKey}`; - const client = new Client({ name: 'bitrefill-cli', version: '0.1.1' }); + const client = new Client({ + name: 'bitrefill-cli', + version: '0.2.0-beta.0', + }); const transport = new StreamableHTTPClientTransport(new URL(url)); try {