Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 25 additions & 23 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ name: Release

on:
push:
tags:
- "v*"
branches:
- main

permissions:
contents: read

concurrency:
group: release-${{ github.ref_name }}
group: release
cancel-in-progress: false

jobs:
Expand All @@ -18,43 +18,45 @@ jobs:
timeout-minutes: 20
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Verify tag is on main
run: |
git fetch origin main:refs/remotes/origin/main
git merge-base --is-ancestor "$GITHUB_SHA" origin/main
- uses: actions/setup-node@v5
with:
node-version: 24
registry-url: https://registry.npmjs.org
- run: npm ci
- name: Verify package version matches tag
run: |
node --input-type=module <<'EOF'
import { readFileSync } from "node:fs";

const tag = process.env.GITHUB_REF_NAME;
const version = tag?.startsWith("v") ? tag.slice(1) : undefined;
const packageJson = JSON.parse(readFileSync("package.json", "utf8"));

if (!version || packageJson.version !== version) {
throw new Error(`Tag ${tag} does not match ${packageJson.name}@${packageJson.version}`);
}
EOF
- run: npm run check
- run: npm run typecheck
- run: npm run build
- name: Pack tarball
run: npm pack --pack-destination "$RUNNER_TEMP"
- name: Test packaged import
run: |
eve_version=$(node -p 'require("./package.json").devDependencies.eve')
smoke_directory=$(mktemp -d)
cd "$smoke_directory"
npm init -y >/dev/null
npm install "$RUNNER_TEMP"/supermemory-eve-*.tgz eve@0.31.3
npm install "$RUNNER_TEMP"/supermemory-eve-*.tgz "eve@$eve_version"
node --input-type=module --eval 'import("@supermemory/eve").then((module) => { if (typeof module.default !== "function") process.exit(1); })'
- name: Check whether version is published
id: publication
run: |
node --input-type=module <<'EOF'
import { appendFileSync, readFileSync } from "node:fs";

const { name, version } = JSON.parse(readFileSync("package.json", "utf8"));
const response = await fetch(
`https://registry.npmjs.org/${encodeURIComponent(name)}/${encodeURIComponent(version)}`,
{ signal: AbortSignal.timeout(30_000) },
);

if (!response.ok && response.status !== 404) {
throw new Error(`npm registry returned ${response.status} for ${name}@${version}`);
}

appendFileSync(process.env.GITHUB_OUTPUT, `publish=${response.status === 404}\n`);
console.log(response.status === 404 ? `Publishing ${name}@${version}` : `${name}@${version} is already published; skipping`);
EOF
- name: Publish to npm
if: steps.publication.outputs.publish == 'true'
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,10 @@ npm run typecheck
npm run build
npm pack --dry-run
```

### Publishing

Pushes to `main` run the release workflow. After checks and a packaged-import smoke test pass,
the workflow publishes the version in `package.json` if it is not already on npm. Bump the
package version and update `package-lock.json` to ship a new release; no Git tag is required.
Publishing requires the repository's `NPM_TOKEN` Actions secret.