Skip to content

Commit 58719eb

Browse files
committed
chore(ci): add release workflow for @openmeter/client
1 parent 50d641a commit 58719eb

12 files changed

Lines changed: 156 additions & 32 deletions

File tree

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Reusable workflow: publish @openmeter/client (the AIP TypeScript SDK) to npm
2+
# via OIDC Trusted Publishing.
3+
#
4+
# npm validates the top-level (caller) workflow filename for trusted publishing,
5+
# not this reusable file. The trusted publisher entry on npmjs.com is therefore
6+
# configured against the caller workflow (e.g. release.yaml) + environment prod.
7+
# See: https://github.com/npm/documentation/issues/1755
8+
9+
name: AIP NPM Release
10+
11+
on:
12+
workflow_call:
13+
inputs:
14+
version:
15+
description: "Version to publish (without leading v; pnpm strips it anyway)."
16+
required: true
17+
type: string
18+
dist-tag:
19+
description: "npm dist-tag to publish under (e.g. latest, beta)."
20+
required: true
21+
type: string
22+
23+
# Restrictive default; the publish job opens id-token: write itself.
24+
permissions:
25+
contents: read
26+
27+
jobs:
28+
publish:
29+
name: Publish @openmeter/client
30+
# npm trusted publishing with provenance currently requires a GitHub-hosted runner.
31+
runs-on: ubuntu-latest
32+
environment: prod
33+
34+
# npm Trusted Publishing: GitHub mints a short-lived OIDC token that npm
35+
# exchanges for a publish token. Requires id-token: write and a matching
36+
# trusted publisher configuration on npmjs.com.
37+
permissions:
38+
contents: read
39+
id-token: write
40+
41+
steps:
42+
- name: Checkout repository
43+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
44+
with:
45+
persist-credentials: false
46+
47+
# Trusted publishing requires npm CLI >= 11.5.1 on PATH so npm can
48+
# perform the OIDC handshake. setup-node provides a current npm and
49+
# writes a registry-scoped .npmrc with no _authToken.
50+
- name: Set up pnpm
51+
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6
52+
with:
53+
package_json_file: api/spec/package.json
54+
55+
- name: Set up Node.js
56+
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
57+
with:
58+
node-version-file: .nvmrc
59+
cache: pnpm
60+
cache-dependency-path: api/spec/pnpm-lock.yaml
61+
registry-url: "https://registry.npmjs.org"
62+
63+
- name: Publish NPM package
64+
run: make -C api/spec publish-aip-sdk
65+
env:
66+
AIP_SDK_RELEASE_VERSION: ${{ inputs.version }}
67+
AIP_SDK_RELEASE_TAG: ${{ inputs.dist-tag }}
68+
NPM_CONFIG_PROVENANCE: "true"

.github/workflows/ci.yaml

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -699,20 +699,6 @@ jobs:
699699
run: |
700700
nix develop --impure .#ci -c go test -v -count=1 ./quickstart/
701701
702-
- name: Run TypeScript SDK example
703-
env:
704-
OPENMETER_URL: http://localhost:48888/api/v3
705-
working-directory: api/spec
706-
run: |
707-
# Build dist/ from src/, then run the quickstart example against it.
708-
nix develop --impure ../../.#ci -c bash -c '
709-
set -euo pipefail
710-
corepack enable >/dev/null 2>&1 || true
711-
pnpm install --frozen-lockfile 2>&1 | tail -5
712-
pnpm --filter @openmeter/sdk run build
713-
node --experimental-strip-types packages/aip-client-javascript/examples/quickstart/main.ts
714-
'
715-
716702
- name: Cleanup Docker Compose
717703
run: docker compose -f docker-compose.yaml -f docker-compose.override.yaml down -v
718704
working-directory: quickstart

.github/workflows/release.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,22 @@ jobs:
261261
contents: read
262262
id-token: write
263263

264+
sdk-aip-release:
265+
name: AIP TypeScript SDK Release
266+
# The AIP SDK (@openmeter/client) shares the repo version and dist-tag with
267+
# @openmeter/sdk, so it reuses the same meta job. Runs on both tag pushes
268+
# (stable/pre-release) and main pushes (per-commit beta). npm's trusted
269+
# publisher entry is keyed on caller workflow file + environment, so this
270+
# caller must serve both channels.
271+
needs: [ sdk-javascript-meta ]
272+
uses: ./.github/workflows/aip-npm-release.yaml
273+
with:
274+
version: ${{ needs.sdk-javascript-meta.outputs.version }}
275+
dist-tag: ${{ needs.sdk-javascript-meta.outputs.dist-tag }}
276+
permissions:
277+
contents: read
278+
id-token: write
279+
264280
sdk-python-release:
265281
name: Python SDK Release
266282
# Python SDK releases are tag-only (dev Python releases live in sdk-python-dev-release.yaml).

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ All generated files have `// Code generated by X, DO NOT EDIT.` headers — neve
9090
2. Run `make gen-api` to regenerate OpenAPI spec and SDKs
9191
3. Run `make generate` to regenerate Go server/client code
9292

93-
The TypeSpec JS client emitted from `api/spec/packages/aip` now lands in `api/spec/packages/aip-client-javascript/`. Treat `api/spec/packages/aip-client-javascript/src/` and its generated `package.json` as emitter output: keep hand-written Playwright config, tests, and helpers outside `src/`, and put test runner dependencies/scripts in the stable `api/spec/package.json` workspace root instead of the generated client package manifest.
93+
The TypeSpec JS client emitted from `api/spec/packages/aip` now lands in `api/spec/packages/aip-client-javascript/`. The emitter regenerates `src/` and `README.md` only; `package.json` is **stable, hand-maintained, and committed** (the emitter's `writeOutput` only writes the paths it lists, so the manifest survives regeneration). Keep hand-written Playwright config, tests, and helpers outside `src/`, and put test-runner dependencies/scripts in the `api/spec/package.json` workspace root rather than the client package manifest. Static publish metadata (`name`, `license`, `homepage`, `repository`) lives directly in the client `package.json`; only the per-release `version` is injected at publish time.
9494

9595
The emitted `api/spec/packages/aip-client-javascript/src/openMeterClient.ts` exposes aggregated sub-client getters on `OpenMeterClient` (e.g. `meters`, `customers`, `features`, `productCatalog`, `subscriptions`, `billing`, `entitlements`). Access operations through those getters, e.g. `sdk.meters.list()`, `sdk.customers.create(...)`, `sdk.productCatalog.createPlan(...)`. Note that resources are grouped by tag, so some operations live under a grouped client rather than a same-named top-level getter (for example plan operations are `sdk.productCatalog.createPlan`, not `sdk.plans.create`).
9696

api/spec/Makefile

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,28 @@ generate: format ## Generate OpenAPI spec
1818
cp packages/legacy/output/openapi.OpenMeterCloud.yaml ../openapi.cloud.yaml
1919
cp packages/aip/output/definitions/metering-and-billing/v3/openapi.Test.yaml ../v3/test/openapi.test.yaml
2020

21+
.PHONY: publish-aip-sdk
22+
publish-aip-sdk: ## Publish the AIP TypeScript SDK (@openmeter/client) to npm
23+
$(call print-target)
24+
@if [ -z "$$AIP_SDK_RELEASE_VERSION" ]; then \
25+
echo "ERROR: AIP_SDK_RELEASE_VERSION is required"; \
26+
echo "Usage: AIP_SDK_RELEASE_VERSION=1.2.3 make publish-aip-sdk [AIP_SDK_RELEASE_TAG=beta]"; \
27+
exit 1; \
28+
fi
29+
30+
@if [ -z "$$AIP_SDK_RELEASE_TAG" ]; then \
31+
echo "ERROR: AIP_SDK_RELEASE_TAG is required"; \
32+
echo "Usage: AIP_SDK_RELEASE_VERSION=1.2.3 make publish-aip-sdk [AIP_SDK_RELEASE_TAG=beta]"; \
33+
exit 1; \
34+
fi
35+
36+
pnpm --frozen-lockfile install
37+
38+
cd packages/aip-client-javascript && \
39+
pnpm version "$${AIP_SDK_RELEASE_VERSION}" --no-git-tag-version && \
40+
CACHE_BUSTER="$$(date --rfc-3339=seconds)" pnpm publish --no-git-checks --access public --tag "$${AIP_SDK_RELEASE_TAG}"
41+
@echo "✅ Published $${AIP_SDK_RELEASE_TAG} AIP TypeScript SDK (@openmeter/client) version $${AIP_SDK_RELEASE_VERSION} with tag $${AIP_SDK_RELEASE_TAG}"
42+
2143
.PHONY: lint
2244
lint: ## Lint OpenAPI spec
2345
$(call print-target)

api/spec/packages/aip-client-javascript/.npmignore

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# package.json "files": ["dist"] is the active publish allowlist and takes
2-
# precedence, so these patterns only take effect if that allowlist is removed.
3-
# They keep dev files and compile-time-only artifacts out of the published
4-
# package in that case.
1+
# This is the active publish surface control for @openmeter/client: package.json
2+
# has no "files" allowlist, so these patterns determine what ships. They keep dev
3+
# files, source maps, and compile-time-only artifacts out of the published
4+
# package, leaving the dist/ runtime and type declarations.
55

66
# Generated conformance guards — compile-time only, no runtime value.
77
*.assert.*

api/spec/packages/aip-client-javascript/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ TypeScript client for the OpenMeter API — usage metering and billing for
44
AI and DevTool companies. This package is generated from the OpenMeter
55
TypeSpec definitions and ships fully-typed request and response models.
66

7+
> [!IMPORTANT]
8+
> This SDK is a work in progress.
9+
>
10+
> This SDK targets the [OpenMeter API v3](https://openmeter.io/docs/api/v3),
11+
> a rewrite of the OpenMeter API following AIP (API Improvement Proposal)
12+
> standardization.
13+
714
## Table of Contents
815

916
- [Installation](#installation)
Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
{
22
"name": "@openmeter/client",
33
"version": "1.0.0",
4-
"files": [
5-
"dist"
6-
],
4+
"license": "Apache-2.0",
5+
"homepage": "https://openmeter.io",
6+
"repository": {
7+
"type": "git",
8+
"url": "git+https://github.com/openmeterio/openmeter.git",
9+
"directory": "api/spec/packages/aip-client-javascript"
10+
},
711
"type": "module",
812
"dependencies": {
913
"ky": "2.0.2",
@@ -14,7 +18,8 @@
1418
"typescript": "5.5.2"
1519
},
1620
"scripts": {
17-
"build": "tsc"
21+
"build": "tsc",
22+
"prepack": "tsc"
1823
},
1924
"exports": {
2025
"./zod": {
@@ -24,10 +29,6 @@
2429
".": {
2530
"types": "./dist/index.d.ts",
2631
"default": "./dist/index.js"
27-
},
28-
"./models": {
29-
"types": "./dist/models/index.d.ts",
30-
"default": "./dist/models/index.js"
3132
}
3233
}
3334
}

api/spec/packages/aip/tspconfig.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ options:
1414
emitter-output-dir: '{output-dir}/../aip-client-javascript'
1515
# The npm package name the generated README installs and imports.
1616
package-name: '@openmeter/client'
17+
# Markdown callout inserted after the README intro.
18+
readme-note: |
19+
> [!IMPORTANT]
20+
> This SDK is a work in progress.
21+
>
22+
> This SDK targets the [OpenMeter API v3](https://openmeter.io/docs/api/v3),
23+
> a rewrite of the OpenMeter API following AIP (API Improvement Proposal)
24+
> standardization.
1725
# Emit per-operation schemas only for the OpenMeter service.
1826
include-services:
1927
- 'OpenMeter'

api/spec/packages/typespec-typescript/src/emitter.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,11 @@ export async function $onEmit(context: EmitContext<ZodEmitterOptions>) {
189189
})
190190
sdkFiles.push({
191191
path: 'README.md',
192-
content: readmeFile(readmeResources, context.options['package-name']),
192+
content: readmeFile(
193+
readmeResources,
194+
context.options['package-name'],
195+
context.options['readme-note'],
196+
),
193197
})
194198

195199
writeOutput(

0 commit comments

Comments
 (0)