-
Notifications
You must be signed in to change notification settings - Fork 1
fix(ci): remove generated artifacts from repo, fix MCPB 404 race condition on Pages #181
Description
Problem
Three related issues with generated artifacts and documentation freshness:
1. MCPB 404 at /downloads/gitlab-mcp-latest.mcpb
URL: https://gitlab-mcp.sw.foundation/downloads/gitlab-mcp-latest.mcpb
Status: Always returns 404
Root cause — race condition between workflows:
Timeline:
1. ci-cd.yml → semantic-release creates release v6.41.1 → fires `release: [published]` event
2. docs.yml is triggered immediately by `release: [published]`
3. ci-cd.yml → mcpb-bundle job starts AFTER semantic-release (needs version output)
4. docs.yml tries to `gh release download "*.mcpb"` → "no assets to download" (not uploaded yet!)
5. docs.yml deploys Pages WITHOUT the .mcpb file
6. mcpb-bundle uploads .mcpb to release (too late, Pages already deployed)
Evidence from ALL recent docs runs:
build Download latest MCPB bundle 2026-01-24T14:29:37Z no assets to download
build Download latest MCPB bundle 2026-01-24T14:16:31Z no assets to download
build Download latest MCPB bundle 2026-01-24T11:18:25Z no assets to download
The .mcpb IS on the release (confirmed: v6.41.1 has gitlab-mcp-6.41.1.mcpb), but it arrives after docs deploy finishes.
2. docs/TOOLS.md committed to git (should be generated artifact)
Currently:
.releaserc.json→@semantic-release/execgeneratesdocs/TOOLS.md.releaserc.json→@semantic-release/gitcommitsdocs/TOOLS.mdto repo- File is tracked in git:
git ls-filesshowsdocs/TOOLS.md - Every release creates a commit with the regenerated file
This is a build artifact that should only exist in CI, not pollute git history.
3. Curated docs out of sync with actual tool capabilities
The curated pages in docs/tools/ (code-review.md, ci-cd.md, project-management.md, repository.md) have fallen behind the auto-generated TOOLS.md. Missing actions/capabilities:
| Tool | Missing from curated docs |
|---|---|
manage_work_item |
add_link, remove_link actions (work item linking) |
browse_files |
download_attachment action |
browse_releases |
assets action |
manage_release |
update, delete, delete_link actions |
browse_members |
list_group, get_group, list_all_project, list_all_group actions |
manage_member |
add_to_group, remove_from_group, remove_from_project, update_group actions |
Additionally, 14 tools have NO use-case page at all (only in overview table): browse_events, browse_users, manage_context, browse_search, browse_todos/manage_todos, browse_webhooks/manage_webhook, browse_snippets/manage_snippet, browse_integrations/manage_integration, browse_wiki/manage_wiki, browse_iterations.
4. Link to GitHub file will break
docs/tools/index.md:218 links to https://github.com/.../docs/TOOLS.md. After removing from git, this will 404.
Solution
Part A: Auto-syncing curated docs via marker injection
Concept: Curated docs keep custom prose/examples but action tables are auto-generated from schemas at build time.
Markers in curated .md files:
## browse_merge_requests
Find and inspect merge requests.
<!-- @autogen:tool browse_merge_requests -->
| Action | Description |
|--------|-------------|
| `list` | List merge requests with filtering |
...
<!-- @autogen:end -->
### Custom Examples
... (manual content preserved)Pre-build injection script (scripts/inject-tool-refs.ts):
/**
* Scans docs/tools/*.md for markers:
* <!-- @autogen:tool TOOL_NAME -->...<!-- @autogen:end -->
*
* Replaces content between markers with freshly generated
* action tables from the tool registry/schemas.
*
* Run: yarn inject-tool-refs
* Used in: docs.yml workflow before yarn docs:build
*/
import { RegistryManager } from '../src/registry-manager.js';
interface MarkerMatch {
file: string;
toolName: string;
startIdx: number;
endIdx: number;
}
// 1. Find all markers in docs/tools/*.md
// 2. For each marker, load tool schema from registry
// 3. Generate actions table (Action | Tier | Description)
// 4. Replace content between markers
// 5. Write updated files
function generateActionsTable(tool: ToolDefinition): string {
// Extract actions from discriminated union schema
// Format as markdown table: | Action | Tier | Description |
}
function generateParamsTable(tool: ToolDefinition): string {
// Extract per-action parameters
// Format as markdown tables grouped by action
}Package.json script:
"inject-tool-refs": "tsx scripts/inject-tool-refs.ts"CI integration (in docs.yml before docs:build):
- name: Generate dynamic documentation
run: |
yarn prisma generate
yarn build
yarn list-tools --export --toc > docs/TOOLS.md
yarn inject-tool-refsBenefits:
- Curated pages are ALWAYS in sync with code (actions, params, tiers)
- Custom prose, examples, tips remain manual (between markers)
- No VitePress plugins needed (pure pre-build step)
- Content visible in GitHub (last-generated state in markers)
- Deterministic output → easy to test
Tests (src/__tests__/inject-tool-refs.test.ts):
describe('inject-tool-refs', () => {
it('finds all @autogen:tool markers in docs', () => {
// Scan docs/tools/*.md, verify all tool names are valid
});
it('generates correct actions table for each tool', () => {
// For each registered tool, verify table has all actions
// Compare with registry schema
});
it('preserves content outside markers', () => {
// Given a .md with markers + manual content
// After injection, manual content is unchanged
});
it('is idempotent', () => {
// Running twice produces same output
});
it('fails on unknown tool name in marker', () => {
// <!-- @autogen:tool nonexistent_tool --> should error
});
it('validates all curated tools have markers', () => {
// Cross-check: every tool mentioned in docs/tools/*.md
// overview tables should have a @autogen marker
});
});Part B: Remove TOOLS.md from git
- Add to
.gitignore:# Generated documentation (built in CI) docs/TOOLS.md - Remove from git:
git rm --cached docs/TOOLS.md - Remove from
.releaserc.json→@semantic-release/git→assets(keep only["CHANGELOG.md", "package.json"]) - Remove
docs/TOOLS.mdgeneration from.releaserc.json→@semantic-release/exec→prepareCmd
Part C: Fix MCPB race condition
Replace release: [published] trigger with workflow_run:
on:
push:
branches: [main]
paths:
- 'docs/**'
- 'package.json'
- 'yarn.lock'
- '.github/workflows/docs.yml'
workflow_run:
workflows: ["CI/CD Pipeline"]
types: [completed]
branches: [main]
workflow_dispatch:With condition:
if: >
github.event_name != 'workflow_run' ||
github.event.workflow_run.conclusion == 'success'Part D: Fix links and navigation
-
Replace GitHub link in
docs/tools/index.md:218:[TOOLS.md](/TOOLS)
-
Add to VitePress sidebar:
"/tools/": [ { text: "Tool Reference", items: [ { text: "Overview", link: "/tools/" }, { text: "Full API Reference", link: "/TOOLS" }, ], }, // ... existing By Use-Case section ],
Part E: Add markers to curated docs
Update docs/tools/code-review.md, ci-cd.md, project-management.md, repository.md:
- Wrap action tables with
<!-- @autogen:tool TOOL_NAME -->...<!-- @autogen:end --> - Fix missing actions (the injection script will auto-populate from schemas)
- Keep all custom examples, tips, and workflow documentation
Part F: SEO Metadata
-
VitePress config (
docs/.vitepress/config.mts):titleTemplate: "%s | GitLab MCP"for SERP formattingtransformHead()hook auto-generates per-page OG/Twitter meta tags (og:title,og:description,og:url,twitter:card,twitter:title,twitter:description)
-
robots.txt (
docs/public/robots.txt):- Allow all crawlers + reference
sitemap.xml
- Allow all crawlers + reference
-
Frontmatter on all 72 documentation pages:
- Each page gets
title+description(max 160 chars) in YAML frontmatter - VitePress uses these for
<title>and<meta name="description"> transformHeadfeeds them to OG/Twitter tags
- Each page gets
-
sitemap.xml — VitePress sitemap generation with hostname config
Part G: inject-tool-refs Test Coverage
Unit tests (tests/unit/cli/inject-tool-refs.test.ts):
- 45 tests covering
extractActions,generateActionsTable,findMarkers,processFile,main - 98.91% line coverage, 97.43% branch coverage, 100% function coverage
- Tests oneOf discriminated union + flat enum schemas
- Tests marker detection, error cases, idempotency
- Export internal functions from
src/cli/inject-tool-refs.tsfor testability
Files to create
| File | Purpose |
|---|---|
src/cli/inject-tool-refs.ts |
Pre-build marker injection script |
tests/unit/cli/inject-tool-refs.test.ts |
45 unit tests (98.91% line coverage) |
docs/public/robots.txt |
SEO: allow crawlers + sitemap reference |
Files to modify
| File | Change |
|---|---|
.gitignore |
Add docs/TOOLS.md |
.releaserc.json |
Remove docs/TOOLS.md from exec and git plugin |
.github/workflows/docs.yml |
Add TOOLS.md + inject-tool-refs steps; replace release trigger with workflow_run |
docs/TOOLS.md |
git rm --cached |
docs/tools/index.md |
Replace GitHub link with local /TOOLS |
docs/.vitepress/config.mts |
Sidebar link + titleTemplate + transformHead + sitemap |
docs/tools/code-review.md |
Add @autogen:tool markers around action tables |
docs/tools/ci-cd.md |
Add @autogen:tool markers around action tables |
docs/tools/project-management.md |
Add @autogen:tool markers + fix missing actions |
docs/tools/repository.md |
Add @autogen:tool markers + fix missing actions |
package.json |
Add inject-tool-refs script |
docs/**/*.md (72 files) |
Add title + description YAML frontmatter |
Verification
After implementation:
yarn inject-tool-refsupdates curated docs with fresh action tablesyarn testpasses injection script tests (3878 tests, 125 suites)yarn docs:buildsucceeds with generated TOOLS.md + injected curated docs + sitemapyarn lint— 0 errors- inject-tool-refs coverage: 98.91% lines, 97.43% branches, 100% functions
- Push to main → ci-cd.yml → semantic-release + mcpb-bundle complete
- docs.yml triggers via
workflow_run→ generates TOOLS.md + injects tool refs + downloads .mcpb - https://gitlab-mcp.sw.foundation/downloads/gitlab-mcp-latest.mcpb returns 200
- https://gitlab-mcp.sw.foundation/TOOLS.html renders full reference
- Curated docs show current actions (auto-synced from schemas)
git logno longer shows TOOLS.md in release commits- All pages render with correct OG/Twitter meta tags for social sharing