Files
webstudio/.github/workflows/release.yml
T
Oleg Isonen 1f4095cf9a fix: Improve generated MCP documentation (#5991)
## Summary

- render the generated MCP version as visible body content immediately
below the page heading
- keep the GitBook navigation label stable as `MCP`
- stamp only the CLI version placeholder during release publication,
leaving Markdown content owned by the template
- remove empty `{}` blocks from the rendered MCP argument examples while
preserving meaningful examples and complete structured JSON data

## Root cause

GitBook uses the `SUMMARY.md` link label as the published page heading
and suppresses the Markdown H1 from the document body. The generated
version was therefore present in source but absent from the rendered
page.

The release workflow also coupled version stamping to the complete
rendered Markdown line. It now replaces and verifies only the standard
`0.0.0-webstudio-version` placeholder.

## Verification

- live page structure inspected: published H1 is `MCP`
- MCP manual regression test demonstrated failing before empty argument
blocks were filtered, then passing after the fix
- release placeholder stamping simulated against the generated page
- `pnpm --filter webstudio exec vitest run src/commands/man.test.ts`
- `pnpm --filter @webstudio-is/project-build typecheck`
- `pnpm --filter webstudio typecheck`
- `pnpm check:generated-docs`
- `pnpm lint`
- `pnpm oxfmt --check packages/project-build/src/mcp.ts
packages/cli/src/commands/man.ts packages/cli/src/commands/man.test.ts`
- `git diff --check`

Fixture inputs and outputs are unaffected.

## Todo

- [x] Generate the release version as visible GitBook body content.
- [x] Decouple release stamping from the rendered Markdown content.
- [x] Remove empty MCP argument example blocks.
- [x] Validate generated output and regression coverage.
- [ ] Merge this pull request.
- [ ] Publish the latest released revision to the `docs` branch.
- [ ] Verify the version on the live GitBook page.

Ref #5986
2026-08-03 20:21:35 +02:00

178 lines
6.5 KiB
YAML

name: Release
on:
push:
tags:
- "[0-9]+.[0-9]+.[0-9]+"
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/github-script@v7
with:
script: |
const latestRelease = await github.rest.repos.getLatestRelease({
owner: context.repo.owner,
repo: context.repo.repo,
})
const commits = await github.rest.repos.compareCommitsWithBasehead({
owner: context.repo.owner,
repo: context.repo.repo,
basehead: `refs/tags/${latestRelease.data.tag_name}...${context.ref}`,
})
const groups = {
feat: [`## Features\n`],
fix: [`## Fixes\n`],
docs: [`## Documentation\n`],
experimental: [`## Experimental\n`],
other: [`## Other changes\n`],
}
for (const commit of commits.data.commits) {
const match = commit.commit.message.match(/^(?<type>\w+)\s*:\s*(?<message>.+)\n*/)
const type = match?.groups?.type
const message = match?.groups?.message
if (type && message) {
const availableType = type in groups ? type : 'other'
const capitalized = message[0].toLocaleUpperCase() + message.slice(1)
groups[availableType].push(`- ${capitalized}`)
}
}
const tag_name = context.ref.slice('refs/tags/'.length)
const fullChangelog = `**Full Changelog**: https://github.com/${context.repo.owner}/${context.repo.repo}/compare/${latestRelease.data.tag_name}...${tag_name}`
const changelog = Object.values(groups)
.filter(lines => lines.length > 1)
.map(lines => lines.join('\n'))
.concat(fullChangelog)
.join('\n\n')
console.info(changelog)
await github.rest.repos.createRelease({
owner: context.repo.owner,
repo: context.repo.repo,
tag_name,
name: tag_name,
body: changelog,
})
publish:
runs-on: ubuntu-latest
permissions:
contents: write
environment:
name: development
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref }} # tag name
- uses: ./.github/actions/submodules-checkout
with:
submodules-ssh-key: ${{ secrets.PRIVATE_GITHUB_DEPLOY_TOKEN }}
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- id: version
run: echo "value=$(echo ${{ github.ref }} | sed 's/refs\/tags\///')" >> $GITHUB_OUTPUT
- id: registry-baseline
name: Resolve pre-publish CLI baseline
run: echo "value=$(npm view webstudio@latest version)" >> "$GITHUB_OUTPUT"
- name: bump version to ${{ steps.version.outputs.value }}
run: |
pnpx replace-in-files-cli \
--string="0.0.0-webstudio-version" \
--replacement="${{ steps.version.outputs.value }}" \
"**/package.json"
- name: pnpm instal
run: pnpm install --ignore-scripts
- run: pnpm --filter="webstudio..." build
- run: pnpm --filter="webstudio..." dts
- name: Creating .npmrc
run: |
cat << EOF > "$HOME/.npmrc"
//registry.npmjs.org/:_authToken=$NPM_TOKEN
EOF
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- run: pnpm -r publish --access public --no-git-checks
- name: Wait for exact CLI registry artifact
env:
VERSION: ${{ steps.version.outputs.value }}
run: |
for attempt in $(seq 1 30); do
integrity=$(npm view "webstudio@$VERSION" dist.integrity --json 2>/dev/null || true)
if [ -n "$integrity" ] && [ "$integrity" != "null" ]; then
exit 0
fi
sleep 10
done
echo "Exact registry artifact webstudio@$VERSION was not observable with integrity metadata." >&2
exit 1
- name: Gate exact published CLI against baseline
id: registry-smoke
env:
DATABASE_URL: postgres://
AUTH_SECRET: test
WEBSTUDIO_RELEASE_SMOKE_TOKEN_BUDGET: 6000
WEBSTUDIO_RELEASE_SMOKE_CANDIDATE: webstudio@${{ steps.version.outputs.value }}
WEBSTUDIO_RELEASE_SMOKE_BASELINE: webstudio@${{ steps.registry-baseline.outputs.value }}
WEBSTUDIO_RELEASE_SMOKE_EXPECT_REGISTRY_VERSION: ${{ steps.version.outputs.value }}
WEBSTUDIO_RELEASE_SMOKE_REPORT: ${{ github.workspace }}/artifacts/cli-release-smoke.json
run: pnpm --filter webstudio test:release-smoke:registry
- name: Upload published CLI comparison report
if: ${{ always() && (steps.registry-smoke.outcome == 'success' || steps.registry-smoke.outcome == 'failure') }}
uses: actions/upload-artifact@v4
with:
name: cli-release-smoke-${{ steps.version.outputs.value }}
path: artifacts/cli-release-smoke.json
if-no-files-found: error
publish-docs:
needs: [release, publish]
runs-on: ubuntu-latest
concurrency:
group: publish-docs
cancel-in-progress: false
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: docs
- name: Publish released documentation snapshot
env:
RELEASE_SHA: ${{ github.sha }}
RELEASE_VERSION: ${{ github.ref_name }}
run: |
if git merge-base --is-ancestor "$RELEASE_SHA" HEAD; then
echo "The docs branch already contains release $RELEASE_VERSION or a newer revision."
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git merge --no-edit "$RELEASE_SHA"
git checkout "$RELEASE_SHA" -- docs/university/mcp.md
CLI_VERSION_PLACEHOLDER="0.0.0-webstudio-version"
grep -Fq "$CLI_VERSION_PLACEHOLDER" docs/university/mcp.md
sed -i.bak "s/$CLI_VERSION_PLACEHOLDER/$RELEASE_VERSION/g" docs/university/mcp.md
rm docs/university/mcp.md.bak
! grep -Fq "$CLI_VERSION_PLACEHOLDER" docs/university/mcp.md
grep -Fq "$RELEASE_VERSION" docs/university/mcp.md
git add docs/university/mcp.md
git commit -m "docs: publish Webstudio CLI $RELEASE_VERSION"
git push origin docs