Skip to content
Open
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
74 changes: 48 additions & 26 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,58 +1,80 @@
name: Publish

# A tag push publishes. A manual run does everything except publish, so the
# release can be rehearsed from any branch.
# A push to main publishes package.json's version to registry.npmjs.org when
# that version is not on npm yet; bumping the version is the release intent.
# A manual run does everything except publish, so the release can be
# rehearsed from any branch.
on:
push:
tags: ['v*']
branches: [main]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: npm-publish
cancel-in-progress: false

jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
# Required for npm provenance; without it `npm publish --provenance` fails.
id-token: write
# The environment isolates NPM_TOKEN from every other workflow in this repo.
environment:
name: npm-publish
url: https://www.npmjs.com/package/@evomap/dsh-evolver
steps:
# Pinned to a commit: a tag can be moved, and this job holds the npm token.
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4

- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 22
registry-url: https://registry.npmjs.org

- run: npm ci --ignore-scripts --no-audit --no-fund

- run: npm test

- name: Check the tag matches the manifest version
if: startsWith(github.ref, 'refs/tags/v')
run: |
tag="${GITHUB_REF_NAME#v}"
manifest="$(node -p "require('./package.json').version")"
if [ "$tag" != "$manifest" ]; then
echo "tag v$tag does not match package.json $manifest" >&2
exit 1
fi

- name: Check this version is not already on npm
- name: Decide whether this version still needs publishing
id: release
run: |
name="$(node -p "require('./package.json').name")"
version="$(node -p "require('./package.json').version")"
if npm view "$name@$version" version >/dev/null 2>&1; then
echo "$name@$version is already published; bump the version" >&2
exit 1
if npm view "$name@$version" version --registry https://registry.npmjs.org >/dev/null 2>&1; then
echo "$name@$version is already on npm; nothing to publish"
echo "publish=false" >> "$GITHUB_OUTPUT"
else
echo "publish=true" >> "$GITHUB_OUTPUT"
fi
echo "version=$version" >> "$GITHUB_OUTPUT"

- run: npm pack --dry-run

- name: Publish
if: startsWith(github.ref, 'refs/tags/v')
run: npm publish --provenance --access public
# Provenance is off because npm rejects provenance from a private source repository.
- name: Publish to npm
if: github.event_name == 'push' && steps.release.outputs.publish == 'true'
run: |
: "${NPM_TOKEN:?NPM_TOKEN is not set on the npm-publish environment}"
npm_config="$(mktemp)"
trap 'rm -f "$npm_config"' EXIT
chmod 600 "$npm_config"
printf '//registry.npmjs.org/:_authToken=%s\n' "$NPM_TOKEN" > "$npm_config"
NPM_CONFIG_USERCONFIG="$npm_config" NPM_CONFIG_PROVENANCE=false \
npm publish --access public --registry https://registry.npmjs.org
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Verify the package resolves from npm
if: github.event_name == 'push' && steps.release.outputs.publish == 'true'
run: |
name="$(node -p "require('./package.json').name")"
for attempt in 1 2 3 4 5 6; do
if npm view "$name@$VERSION" version --registry https://registry.npmjs.org; then
exit 0
fi
sleep 10
done
echo "$name@$VERSION did not appear on npm after publishing" >&2
exit 1
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
VERSION: ${{ steps.release.outputs.version }}
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ Powered by the [Genome Evolution Protocol](https://evomap.ai) and
[`@evomap/evolver`](https://github.com/EvoMap/evolver).

> **Status:** pre-release `0.1.0`. Local memory, commands, Skill, and the current
> Proxy-backed asset loop are implemented. The npm package is published only when the
> first matching release tag is created.
> Proxy-backed asset loop are implemented. The npm package is published when a
> `package.json` version that is not yet on npm lands on `main`.

## What it does

Expand Down Expand Up @@ -174,7 +174,8 @@ npm pack --dry-run
```

CI validates Node 22 and 24 plus the declared DSH compatibility lines. The release workflow
publishes only a tag whose version matches `package.json`; this task does not create that tag.
publishes to npm on every push to `main` whose `package.json` version is not on npm yet, using
the `NPM_TOKEN` secret of the `npm-publish` environment; a manual run rehearses without publishing.

## License

Expand Down
Loading