Skip to content

v1.0.2

v1.0.2 #10

Workflow file for this run

name: publish
on:
push:
tags: ['v*']
permissions:
id-token: write # npm Trusted Publishing OIDC
contents: write # GitHub Release creation
concurrency:
group: publish
cancel-in-progress: false
jobs:
publish:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: '22.14.0'
registry-url: https://registry.npmjs.org
- name: Use npm with Trusted Publishing support
# Pinned exact (>=11.5.1 required for Trusted Publishing); bump deliberately.
run: npm install -g npm@11.16.0
- name: Verify tag matches package.json version
run: |
set -eo pipefail
TAG_VERSION="${GITHUB_REF_NAME#v}"
PKG_VERSION="$(node -p 'require("./package.json").version')"
if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then
echo "::error::Tag v${TAG_VERSION} does not match package.json version ${PKG_VERSION}"
exit 1
fi
- name: Verify publishable file set
run: |
set -eo pipefail
PACK_JSON="$(npm pack --dry-run --json)"
PACK_JSON="${PACK_JSON}" node <<'NODE'
const data = JSON.parse(process.env.PACK_JSON)
const files = data[0].files.map((file) => file.path).sort()
const expected = [
'CHANGELOG.md',
'LICENSE',
'README.md',
'bin/appfigures',
'dist/af.js',
'package.json',
'server.json',
]
if (JSON.stringify(files) !== JSON.stringify(expected)) {
console.error(`Expected npm pack files ${JSON.stringify(expected)}, got ${JSON.stringify(files)}`)
process.exit(1)
}
NODE
- name: Extract release notes
run: |
set -eo pipefail
node - "${GITHUB_REF_NAME#v}" > release-notes.md <<'NODE'
const fs = require('fs')
const version = process.argv[2]
const content = fs.readFileSync('CHANGELOG.md', 'utf8')
const escaped = version.replace(/[.+*?^$(){}|[\]\\]/g, '\\$&')
const headerRe = new RegExp(`^## \\[${escaped}\\]`)
const nextHeaderRe = /^## \[/
const captured = []
let inSection = false
for (const line of content.split('\n')) {
if (inSection && nextHeaderRe.test(line)) break
if (headerRe.test(line)) {
inSection = true
continue
}
if (inSection) captured.push(line)
}
if (!inSection) {
console.error(`No CHANGELOG section found for version ${version}`)
process.exit(1)
}
process.stdout.write(captured.join('\n').trim() + '\n')
NODE
- name: Publish to npm
run: |
set -eo pipefail
NAME="$(node -p 'require("./package.json").name')"
VERSION="$(node -p 'require("./package.json").version')"
TAG="$(node -e 'const version = process.argv[1]; const match = version.match(/^\d+\.\d+\.\d+-([0-9A-Za-z]+)/); if (match) process.stdout.write(match[1]);' "${VERSION}")"
if npm view "${NAME}@${VERSION}" version >/dev/null 2>&1; then
echo "${NAME}@${VERSION} is already published; skipping npm publish"
exit 0
fi
if [ -n "$TAG" ]; then
npm publish --tag "$TAG"
else
npm publish
fi
# Publish the registry listing after npm publish (the entry references
# @appfigures/cli@<version>, which must exist on npm first).
# Bump MCP_PUBLISHER_VERSION/_SHA256 together from the release checksums.txt.
- name: Install mcp-publisher
env:
MCP_PUBLISHER_VERSION: '1.7.9'
MCP_PUBLISHER_SHA256: 'ab128162b0616090b47cf245afe0a23f3ef08936fdce19074f5ba0a4469281ac'
run: |
set -eo pipefail
curl -fsSL -o mcp-publisher.tar.gz \
"https://github.com/modelcontextprotocol/registry/releases/download/v${MCP_PUBLISHER_VERSION}/mcp-publisher_linux_amd64.tar.gz"
echo "${MCP_PUBLISHER_SHA256} mcp-publisher.tar.gz" | sha256sum -c -
tar xz -f mcp-publisher.tar.gz mcp-publisher
rm -f mcp-publisher.tar.gz
- name: Stamp release version into server.json
run: |
set -eo pipefail
VERSION="${GITHUB_REF_NAME#v}" node <<'NODE'
const fs = require('fs')
const version = process.env.VERSION
const server = JSON.parse(fs.readFileSync('server.json', 'utf8'))
server.version = version
server.packages[0].version = version
fs.writeFileSync('server.json', JSON.stringify(server, null, '\t') + '\n')
NODE
- name: Publish to MCP Registry
run: |
set -eo pipefail
# Derive the hex key from the PEM secret; remove the file after.
printf '%s' "${{ secrets.MCP_REGISTRY_PRIVATE_KEY }}" > key.pem
./mcp-publisher login dns --domain appfigures.com \
--private-key "$(openssl pkey -in key.pem -noout -text | grep -A3 'priv:' | tail -n +2 | tr -d ' :\n')"
rm -f key.pem
./mcp-publisher publish
- name: Create GitHub Release
env:
GH_TOKEN: ${{ github.token }}
run: |
set -eo pipefail
if gh release view "${GITHUB_REF_NAME}" >/dev/null 2>&1; then
echo "Release ${GITHUB_REF_NAME} already exists; skipping"
exit 0
fi
VERSION="${GITHUB_REF_NAME#v}"
gh release create "${GITHUB_REF_NAME}" \
--title "@appfigures/cli v${VERSION}" \
--notes-file release-notes.md