Skip to content

chore(release): bump mcpb manifest.json version to 0.3.0 (#31) #14

chore(release): bump mcpb manifest.json version to 0.3.0 (#31)

chore(release): bump mcpb manifest.json version to 0.3.0 (#31) #14

Workflow file for this run

name: Release
on:
push:
tags:
- "v*.*.*"
workflow_dispatch:
inputs:
release_tag:
description: "Existing release tag to publish (for example: v0.1.1)"
required: true
type: string
jobs:
preflight:
name: Release preflight
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
env:
RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref_name }}
concurrency:
group: npm-release-${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref_name }}
cancel-in-progress: false
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref }}
- uses: actions/setup-node@v4
with:
node-version: 22
registry-url: https://registry.npmjs.org
cache: npm
- name: Use npm 11.5.1+ for OIDC trusted publishing compatibility
run: npm install --global npm@11.5.1
- name: Verify tag matches package suite versions
run: |
TAG_REF="${RELEASE_TAG:-$GITHUB_REF_NAME}"
TAG_VERSION="${TAG_REF#v}"
for pkg in packages/docx-core packages/docx-mcp packages/safe-docx packages/safe-docx-mcpb; do
PKG_VERSION="$(node -p "require('./${pkg}/package.json').version")"
if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then
echo "Tag version ($TAG_VERSION) must match ${pkg}/package.json version ($PKG_VERSION)."
exit 1
fi
done
MANIFEST_VERSION="$(node -e "const fs=require('fs');const m=JSON.parse(fs.readFileSync('./packages/safe-docx-mcpb/manifest.json','utf8'));process.stdout.write(m.version)")"
if [ "$TAG_VERSION" != "$MANIFEST_VERSION" ]; then
echo "Tag version ($TAG_VERSION) must match packages/safe-docx-mcpb/manifest.json version ($MANIFEST_VERSION)."
exit 1
fi
- name: Verify release commit is on main
run: |
git fetch origin main
if ! git merge-base --is-ancestor "$GITHUB_SHA" "origin/main"; then
echo "Release tag commit is not contained in origin/main."
exit 1
fi
- name: Install dependencies (npm ci with retry)
run: |
for attempt in 1 2 3; do
echo "npm ci attempt ${attempt}/3"
if npm ci; then
exit 0
fi
if [ "$attempt" -lt 3 ]; then
sleep $((attempt * 20))
fi
done
echo "npm ci failed after 3 attempts"
exit 1
- name: Build workspaces
run: npm run build
- name: Lint/typecheck workspaces
run: npm run lint:workspaces
- name: Regenerate and verify tool reference docs are committed
run: npm run check:tool-docs
- name: Install site dependencies
run: npm --prefix site ci
- name: Build site and validate internal links
run: npm run check:site
- name: Validate MCPB manifest/tool contract
run: npm run check:mcpb-manifest
- name: Guard against duplicate publish
run: |
TAG_REF="${RELEASE_TAG:-$GITHUB_REF_NAME}"
VERSION="${TAG_REF#v}"
for pkg in @usejunior/docx-core @usejunior/docx-mcp @usejunior/safe-docx; do
if npm view "$pkg@$VERSION" version >/dev/null 2>&1; then
echo "$pkg@$VERSION already exists on npm."
exit 1
fi
echo "$pkg@$VERSION not yet published."
done
- name: Test workspaces
run: npm run test
- name: Package-level smoke tests
run: |
npm run test:run -w @usejunior/docx-core
npm run test:run -w @usejunior/docx-mcp
npm run test:run -w @usejunior/safe-docx
npm run test:run -w @usejunior/safedocx-mcpb
- name: Package coverage ratchet
run: |
npm run test:coverage:packages
npm run coverage:packages:check
- name: Validate OpenSpec traceability coverage
run: npm run check:spec-coverage
- name: Validate Allure hierarchy labels
run: npm run check:allure-labels
- name: Enforce Allure filename migration policy
run: npm run check:allure-filenames
- name: Validate Allure quality conventions
run: npm run check:allure-quality
- name: Verify package contents (dry-run)
run: |
for pkg in packages/docx-core packages/docx-mcp packages/safe-docx; do
echo "Dry-run pack: $pkg"
(cd "$pkg" && npm pack --dry-run)
done
- name: Sanitize npm auth for public npx fetches
run: |
unset NODE_AUTH_TOKEN
npm config delete //registry.npmjs.org/:_authToken || true
- name: Isolated package runtime smoke test
run: |
pack_dir="$(mktemp -d)"
run_dir="$(mktemp -d)"
core_tgz="$(cd packages/docx-core && npm pack --silent --pack-destination "$pack_dir")"
mcp_tgz="$(cd packages/docx-mcp && npm pack --silent --pack-destination "$pack_dir")"
safe_tgz="$(cd packages/safe-docx && npm pack --silent --pack-destination "$pack_dir")"
pushd "$run_dir"
npm init -y >/dev/null
for attempt in 1 2 3; do
echo "runtime smoke attempt ${attempt}/3"
rm -rf node_modules package-lock.json
if npm install --no-audit --no-fund "$pack_dir/$core_tgz" "$pack_dir/$mcp_tgz" "$pack_dir/$safe_tgz" >/dev/null \
&& ./node_modules/.bin/safe-docx --help; then
popd
rm -rf "$pack_dir" "$run_dir"
exit 0
fi
if [ "$attempt" -lt 3 ]; then
sleep $((attempt * 20))
fi
done
popd
rm -rf "$pack_dir" "$run_dir"
echo "runtime smoke failed after 3 attempts"
exit 1
- name: Build and pack safe-docx MCP bundle
run: npm run pack:mcpb
publish-suite:
name: Publish package suite
needs: preflight
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
env:
RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref_name }}
concurrency:
group: npm-release-${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref_name }}
cancel-in-progress: false
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref }}
- uses: actions/setup-node@v4
with:
node-version: 22
registry-url: https://registry.npmjs.org
cache: npm
- name: Use npm 11.5.1+ for OIDC trusted publishing compatibility
run: npm install --global npm@11.5.1
- name: Install dependencies (npm ci with retry)
run: |
for attempt in 1 2 3; do
echo "npm ci attempt ${attempt}/3"
if npm ci; then
exit 0
fi
if [ "$attempt" -lt 3 ]; then
sleep $((attempt * 20))
fi
done
echo "npm ci failed after 3 attempts"
exit 1
- name: Build publishable packages
run: |
npm run build -w @usejunior/docx-core
npm run build -w @usejunior/docx-mcp
npm run build -w @usejunior/safe-docx
- name: Publish to npm (trusted publishing)
run: |
TAG_REF="${RELEASE_TAG:-$GITHUB_REF_NAME}"
VERSION="${TAG_REF#v}"
unset NODE_AUTH_TOKEN
npm config delete //registry.npmjs.org/:_authToken || true
# Publish in dependency order.
for entry in "@usejunior/docx-core:packages/docx-core" "@usejunior/docx-mcp:packages/docx-mcp" "@usejunior/safe-docx:packages/safe-docx"; do
PKG_NAME="${entry%%:*}"
PKG_DIR="${entry##*:}"
if npm view "$PKG_NAME@$VERSION" version >/dev/null 2>&1; then
echo "$PKG_NAME@$VERSION already exists on npm."
exit 1
fi
echo "Publishing $PKG_NAME from $PKG_DIR"
(cd "$PKG_DIR" && npm publish --access public --provenance)
done
ensure-release:
name: Create or update GitHub Release
needs: publish-suite
runs-on: ubuntu-latest
permissions:
contents: write
env:
RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref_name }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref }}
- name: Create GitHub Release with auto-generated notes
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ env.RELEASE_TAG }}
generate_release_notes: true
publish-mcpb-asset:
name: Publish safe-docx MCP bundle asset
needs: [preflight, publish-suite, ensure-release]
runs-on: ubuntu-latest
permissions:
contents: write
env:
RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref_name }}
concurrency:
group: npm-release-${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref_name }}
cancel-in-progress: false
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref }}
- uses: actions/setup-node@v4
with:
node-version: 22
registry-url: https://registry.npmjs.org
cache: npm
- name: Use npm 11.5.1+ for OIDC trusted publishing compatibility
run: npm install --global npm@11.5.1
- name: Install dependencies (npm ci with retry)
run: |
for attempt in 1 2 3; do
echo "npm ci attempt ${attempt}/3"
if npm ci; then
exit 0
fi
if [ "$attempt" -lt 3 ]; then
sleep $((attempt * 20))
fi
done
echo "npm ci failed after 3 attempts"
exit 1
- name: Sanitize npm auth for public npx fetches
run: |
unset NODE_AUTH_TOKEN
npm config delete //registry.npmjs.org/:_authToken || true
- name: Build and pack safe-docx MCP bundle
run: npm run pack:mcpb
- name: Generate MCP bundle checksum
run: |
sha256sum packages/safe-docx-mcpb/safe-docx.mcpb > packages/safe-docx-mcpb/safe-docx.mcpb.sha256
- name: Attach safe-docx.mcpb to GitHub release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ env.RELEASE_TAG }}
files: |
packages/safe-docx-mcpb/safe-docx.mcpb
packages/safe-docx-mcpb/safe-docx.mcpb.sha256
fail_on_unmatched_files: true
update-changelog-data:
name: Update changelog data and open PR
needs: publish-mcpb-asset
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
env:
RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref_name }}
GH_TOKEN: ${{ github.token }}
steps:
- uses: actions/checkout@v4
with:
ref: main
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- name: Generate changelog data
run: node scripts/generate_changelog_data.mjs
- name: Check for changes
id: diff
run: |
if git diff --quiet -- site/src/_raw/changelog.json; then
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
- name: Create PR with updated changelog data
if: steps.diff.outputs.changed == 'true'
run: |
BRANCH="chore/changelog-update-${RELEASE_TAG}"
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
# Create or reset branch
git checkout -B "$BRANCH"
git add site/src/_raw/changelog.json
git commit -m "$(cat <<'EOF'
chore(site): update changelog data for ${{ env.RELEASE_TAG }}
Auto-generated by the release workflow after assets were published.
EOF
)"
git push --force-with-lease origin "$BRANCH"
# Only create PR if one doesn't already exist for this branch
EXISTING=$(gh pr list --head "$BRANCH" --state open --json number --jq '.[0].number // empty')
if [ -z "$EXISTING" ]; then
gh pr create \
--title "chore(site): update changelog data for ${RELEASE_TAG}" \
--body "Auto-generated by the release workflow. Merging this updates the trust site changelog." \
--head "$BRANCH" \
--base main
else
echo "PR #${EXISTING} already exists for branch ${BRANCH} — skipping creation."
fi