Skip to content

fix(docs): deploy bug report API as CF Worker + improve widget & layout#154

Merged
polaz merged 14 commits intomainfrom
feat/#145-featdocs-add-report-a-bug-feedback-widget-to-docum
Jan 23, 2026
Merged

fix(docs): deploy bug report API as CF Worker + improve widget & layout#154
polaz merged 14 commits intomainfrom
feat/#145-featdocs-add-report-a-bug-feedback-widget-to-docum

Conversation

@polaz
Copy link
Copy Markdown
Member

@polaz polaz commented Jan 23, 2026

Summary

  • Fix 405 Method Not Allowed — deploy bug report handler as standalone Cloudflare Worker (GitHub Pages is static-only, can't handle POST)
  • Improve widget visibility — floating bottom-right button with pulse animation instead of hidden vertical tab
  • Add project logo — navbar icon + hero image on landing page
  • Widen content layout@media queries for screens >1440px and >1600px

Technical Details

  • docs/worker/ — standalone CF Worker with route docs.gitlab-mcp.sw.foundation/api/*
  • Worker intercepts POST /api/report-bug before it reaches GitHub Pages origin
  • CI job deploy-worker uses cloudflare/wrangler-action@v3
  • KV namespace 67e3b42cfafe492bbc8bbb17fe5c6b8b for IP-based rate limiting
  • CORS updated: https://docs.gitlab-mcp.sw.foundation as primary origin
  • GitHub App sw-release-bot (ID: 2686935) with issues:write permission

Post-merge steps

After CI deploys the Worker:

cd docs/worker
npx wrangler secret put GITHUB_APP_ID            # 2686935
npx wrangler secret put GITHUB_APP_INSTALLATION_ID  # 104999149
npx wrangler secret put GITHUB_APP_PEM           # base64-encoded private key

Test plan

  • yarn lint — 0 errors
  • yarn test — 3746 passed
  • yarn docs:build — builds successfully
  • After deploy: POST to /api/report-bug returns 201
  • Widget visible on desktop without scrolling
  • Content wider on >1440px screens

Closes #145, closes #153

polaz added 13 commits January 23, 2026 18:36
- Add BugReportWidget.vue: persistent side-tab with expandable form,
  success/error states, responsive design (side panel on desktop,
  bottom sheet on mobile), dark mode support, and prefers-reduced-motion
- Add Cloudflare Pages Function (docs/functions/api/report-bug.ts):
  creates GitHub issues via GitHub App installation token with
  honeypot anti-spam, IP-based rate limiting via KV, input validation,
  and CORS restricted to docs domain
- Add VitePress custom theme extending default with layout-bottom slot
- Add .github/ISSUE_TEMPLATE/bug.yml as fallback for direct GitHub reports
- Add @cloudflare/workers-types and docs/functions/tsconfig.json
- Exclude docs/ from main tsconfig to avoid type conflicts

Closes #145
- Fix PKCS#1 vs PKCS#8 PEM detection: use "BEGIN RSA" presence to
  correctly identify PKCS#1 format (GitHub App PEMs) vs PKCS#8
- Add aria-modal="true" and focus trap to dialog panel for
  screen reader and keyboard-only accessibility
- Return focus to trigger button when dialog closes
- Extract pure utility functions to utils.ts for testability
- Add 27 unit tests covering validation, CORS, base64url encoding,
  ASN.1 length encoding, and buffer concatenation
Import CATEGORIES and MIN_DESCRIPTION_LENGTH from shared utils into the
Vue widget instead of duplicating values. Add explicit local variable
narrowing in validateReport for stricter TypeScript compatibility.
The trigger button uses v-if and is recreated on state change. Focus
must wait for DOM patch before the new element ref is available.
GitHub Pages returns 405 for POST requests because it's static-only hosting.
The CF Pages Function in docs/functions/ was never deployed.

Solution: standalone Cloudflare Worker at docs/worker/ with route rule
docs.gitlab-mcp.sw.foundation/api/* intercepting requests before GitHub Pages.

- Add docs/worker/ with wrangler.toml and Worker-format handler
- Add deploy-worker job to docs.yml CI workflow
- Add https://docs.gitlab-mcp.sw.foundation to ALLOWED_ORIGINS
- Update test expectation for new primary origin

Closes #153
- Widget: move from vertical side tab to floating bottom-right button
  with pulse animation and "Report Bug" label (more discoverable)
- Logo: add project logo to navbar and hero section on landing page
- Layout: add custom CSS with @media queries for wider content on
  screens >1440px and >1600px (reduces wasted horizontal space)
Copilot AI review requested due to automatic review settings January 23, 2026 20:51
…d-report-a-bug-feedback-widget-to-docum

# Conflicts:
#	docs/.vitepress/theme/components/BugReportWidget.vue
#	docs/.vitepress/theme/index.ts
#	docs/functions/api/utils.ts
#	tests/unit/docs/report-bug-handler.test.ts
@polaz polaz enabled auto-merge (squash) January 23, 2026 20:52
@polaz polaz merged commit e8284bc into main Jan 23, 2026
14 checks passed
@polaz polaz deleted the feat/#145-featdocs-add-report-a-bug-feedback-widget-to-docum branch January 23, 2026 20:55
@codecov
Copy link
Copy Markdown

codecov bot commented Jan 23, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Deploys a bug-report backend that works with the static GitHub Pages docs site, while improving docs UI (bug widget, branding, and layout).

Changes:

  • Add a standalone Cloudflare Worker for POST /api/report-bug (GitHub App auth + KV rate limiting) and a CI job to deploy it.
  • Update the VitePress theme to include a more visible “Report Bug” floating widget and widen the layout on large screens.
  • Add docs branding assets (logo in navbar + hero image) and a GitHub bug issue template.

Reviewed changes

Copilot reviewed 12 out of 14 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
yarn.lock Adds Cloudflare Workers type dependency to the lockfile.
tsconfig.json Excludes docs/ from root TS compilation.
package.json Adds @cloudflare/workers-types to devDependencies.
tests/unit/docs/report-bug-utils.test.ts Unit tests for validation/CORS/encoding utilities used by the bug report API.
tests/unit/docs/report-bug-handler.test.ts Unit tests for the Pages Function implementation of the bug report handler.
tests/unit/docs/cloudflare-types.d.ts Minimal CF type stubs for the Jest environment.
docs/worker/wrangler.toml Worker config with route and KV binding for rate limiting.
docs/worker/tsconfig.json Worker-specific TS config using Workers types.
docs/worker/src/index.ts Cloudflare Worker implementation of the bug report API endpoint.
docs/worker/package.json Separate worker package metadata/dependencies.
docs/public/logo.png Adds the navbar logo asset.
docs/index.md Adds hero image configuration to the landing page.
docs/functions/tsconfig.json Adds TS config for the (legacy/tested) functions code.
docs/functions/api/utils.ts Extracts shared pure utilities for testability (validation/CORS/encoding helpers).
docs/functions/api/report-bug.ts Pages Function implementation (JWT auth, KV rate limiting, create GitHub issue).
docs/.vitepress/theme/style.css Adds layout widening and hero image sizing CSS overrides.
docs/.vitepress/theme/index.ts Extends the default theme to mount the bug report widget.
docs/.vitepress/theme/components/BugReportWidget.vue New floating bug report widget UI and client-side submit logic.
docs/.vitepress/config.mts Adds themeConfig.logo for the navbar.
.github/workflows/docs.yml Adds a deploy-worker job using cloudflare/wrangler-action@v3.
.github/ISSUE_TEMPLATE/bug.yml Adds a structured GitHub bug report issue template.
Comments suppressed due to low confidence (2)

docs/.vitepress/theme/components/BugReportWidget.vue:68

  • submit() always updates state after the awaited fetch(). If the user closes the widget (via the close button or Escape) while the request is in-flight, the resolved promise can set state back to success/error and unexpectedly reopen the panel. Consider preventing closing while state === "submitting", or track a request id/AbortController and ignore late responses when the widget has been collapsed/unmounted.
    if (response.ok) {
      state.value = "success";
      resetForm();
      setTimeout(() => {
        state.value = "collapsed";
      }, 3000);

.github/workflows/docs.yml:82

  • deploy-worker can run even if the docs build job fails (no needs: dependency). This can deploy an updated API while the site build/deploy did not succeed, leaving the system in an inconsistent state. Add needs: build (or similar gating) so the Worker only deploys after a successful build.
  deploy-worker:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy Cloudflare Worker
        uses: cloudflare/wrangler-action@v3
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
          workingDirectory: docs/worker

Comment on lines +1 to +10
{
"name": "gitlab-mcp-docs-api",
"private": true,
"type": "module",
"devDependencies": {
"@cloudflare/workers-types": "^4.20241218.0",
"typescript": "^5.7.0",
"wrangler": "^3.99.0"
}
}
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docs/worker is set up as a separate package (with its own package.json) but there’s no lockfile in that directory. Combined with caret (^) ranges, Worker deployments via CI can become non-deterministic as transitive deps change. Consider either making docs/worker a Yarn workspace managed by the root lockfile, or pin exact versions and add a lockfile for the worker directory.

Copilot uses AI. Check for mistakes.
Comment on lines +51 to +69
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);

if (url.pathname !== "/api/report-bug") {
return new Response("Not Found", { status: 404 });
}

if (request.method === "OPTIONS") {
return handleOptions(request);
}

if (request.method === "POST") {
return handlePost(request, env);
}

return new Response("Method Not Allowed", { status: 405 });
},
};
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Worker implementation is the production handler for /api/report-bug, but the new unit tests target docs/functions/api/report-bug.ts instead. That means the deployed code path is currently untested and can drift from the tested implementation. Consider refactoring to share a single tested handler between docs/worker/src/index.ts and the Pages Function (or add dedicated unit tests that import/call the Worker handler).

Copilot generated this review using guidance from repository custom instructions.
@sw-release-bot
Copy link
Copy Markdown

🎉 This PR is included in version 6.33.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

2 participants