Skip to content

feat: show build version and git commit in UI and startup log - #1023

Open
Furox-Art wants to merge 1 commit into
HelpCode-ai:mainfrom
Furox-Art:feat/version-display
Open

Furox-Art wants to merge 1 commit into
HelpCode-ai:mainfrom
Furox-Art:feat/version-display

Conversation

@Furox-Art

Copy link
Copy Markdown

Closes #1000

What

Single source of truth for build version, commit and build date, surfaced in three places:

  1. packages/backend/src/common/app-version.ts — readAppVersion() moved here from mcp-endpoint.controller.ts (walk-up logic and comment preserved). Exports APP_VERSION, APP_COMMIT (APP_COMMIT || SENTRY_RELEASE || 'dev'), APP_BUILD_DATE (APP_BUILD_DATE || null).

  2. GET /api/version — new VersionController in packages/backend/src/health/, behind AuthGuard('jwt'). Returns { version, commit, buildDate, deploymentMode }. /health/server-info is untouched.

  3. Footer — signed-in users see v{version} in the footer, with full version + commit in the tooltip.

Also updated:

  • tracing.ts and instrument.ts: service.version / Sentry release fall back to APP_VERSION instead of the unset npm_package_version (which was producing 0.0.0 in containers).
  • main.ts: startup log line AnythingMCP v0.18.0 (commit 3bd9f8b, built 2026-10-04, mode self-hosted).
  • Dockerfile: APP_COMMIT and APP_BUILD_DATE build args → ENV, plus org.opencontainers.image.revision and .version OCI labels.
  • Unit tests in app-version.spec.ts covering env precedence and the dev fallback.
  • docs/deployment.md documents the build args; docs/operations/observability.md notes the service.version source change.

Acceptance criteria

  • docker build --build-arg APP_COMMIT=$(git rev-parse HEAD) . → footer and startup log show the short SHA; without the arg they show dev.
  • GET /api/version returns 401 without a JWT. /health/server-info is unchanged.
  • Unit test app-version.spec.ts covers env precedence and the dev fallback.
  • The MCP serverInfo.version still equals package.json version.
  • Docs updated.

Verification

$ cd packages/backend && npm test -- app-version.spec.ts
 PASS  src/common/app-version.spec.ts
  app-version
    ✓ APP_COMMIT falls back to dev when unset
    ✓ APP_COMMIT prefers APP_COMMIT over SENTRY_RELEASE
    ✓ APP_COMMIT uses SENTRY_RELEASE when APP_COMMIT is unset
    ✓ APP_BUILD_DATE defaults to null
    ✓ APP_BUILD_DATE reads from env
    ✓ APP_VERSION is a non-empty string

@github-actions

Copy link
Copy Markdown

👋 Welcome, @Furox-Art, and thanks for opening your first PR on AnythingMCP!

A few quick pointers:

  • Make sure CI is green before requesting review (Backend, Frontend, Playwright, CodeQL, Trivy).
  • If this is a new adapter, the parametrised catalog.spec.ts test will validate it automatically.
  • Sign off your commits if you can — it's not blocking, just nice to have.

Someone from the core team will look at this within ~48h. If you don't hear back, please ping us in Discussions / Q&A.

⭐ While you wait — if you find AnythingMCP useful, a star helps others discover it.

@github-actions

github-actions Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@Furox-Art

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

github-actions Bot added a commit that referenced this pull request Oct 10, 2026
@helpcodeai

Copy link
Copy Markdown
Contributor

@Furox-Art thanks for the PR. Heads-up: #1000 was assigned to someone else on 8 October, and the rules in #997 give them 7 days. I've asked them to tell us by Wednesday 15 October whether they're still on it. Meanwhile I'm reviewing this one, so it's ready either way. Next time, please comment on the issue first so we can assign it to you.

@helpcodeai helpcodeai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks @Furox-Art, the structure is good, and keeping the version behind auth and off /health/server-info is exactly right. A few things are needed before this can go in:

Blocker

  1. packages/backend/src/mcp-server/mcp-endpoint.controller.ts: the new import { APP_VERSION } ... ended up inside the @nestjs/common import block, so the backend doesn't compile (TS1003/TS1005, 5 test suites fail). Move it above import {, and drop the two blank lines left where readAppVersion was.

The footer never shows a version
2. versionApi.get() in lib/api.ts sends no token, so /api/version always answers 401 and the footer stays empty. Pass the token (get: (token: string) => request(..., { token, skipAutoLogout: true })), read it from useAuth() in the footer and only fetch when it's set.

Still missing from #1000
3. The "Copy version info" card in Settings → Administration (app/settings/admin/page.tsx).
4. .github/workflows/docker-publish.yml: add APP_COMMIT=${{ github.sha }} and a build date to build-args. Today buildDate is always null and the startup log says "built unknown". Two lines, nothing else in the workflow.
5. Footer format: v0.21.0 · 3bd9f8b with the short SHA, linked to https://github.com/HelpCode-ai/anythingmcp/commit/<sha> when it's a 40-character SHA, plain dev otherwise. Fetch once per session (a module-level cached promise), not on every AppShell mount.
6. Shorten the SHA for display in the startup log and footer (/^[0-9a-f]{40}$/.test(c) ? c.slice(0, 7) : c), and keep the full SHA in the API response for the link.

Small things
7. Dockerfile: org.opencontainers.image.version="${APP_VERSION}" has no matching ARG, so local builds get an empty label. Declare ARG APP_VERSION= or drop the label (CI overrides it anyway).
8. docs/deployment.md: the new section sits after the "Back to README" line; move it above. In docs/operations/observability.md, put the sentence in the service.version section instead of at the end of the file.
9. app-version.ts and app-version.spec.ts are executable (100755); please make them 100644.
10. version.controller.ts: one @nestjs/common import instead of two, and add @ApiBearerAuth().

About the assignment: as I wrote above, #1000 was given to someone else first, so the final call waits until Wednesday 15 October. Fixing these in the meantime means it's ready to merge if it's yours.

@Furox-Art
Furox-Art force-pushed the feat/version-display branch 2 times, most recently from 3805e41 to 5076aa5 Compare October 11, 2026 12:35
@Furox-Art

Copy link
Copy Markdown
Author

All ten points addressed, pushed as a new commit on the rebased branch:

Blocker

  1. Moved the APP_VERSION import above the @nestjs/common block, removed the leftover blank lines. app-version.ts/app-version.spec.ts are now 100644.

Footer
2. versionApi.get(token) now takes the token (skipAutoLogout: true); the footer reads it from useAuth() and only fetches when set.
5. Footer shows v0.21.0 · 3bd9f8b with the short SHA linked to the commit on GitHub when it's a 40-char SHA; version is fetched once per session via a module-level cached promise.
6. SHA shortened for display (/^[0-9a-f]{40}$/ ? slice(0,7) : c) in both footer and startup log; the full SHA stays in the API response for the link.

Still missing from #1000
3. "About this instance" card added to Settings → Administration with a Copy version info button.
4. docker-publish.yml now passes APP_COMMIT=${{ github.sha }} and APP_BUILD_DATE=${{ github.event.head_commit.timestamp }}.

Small things
7. ARG APP_VERSION= declared in the Dockerfile.
8. deployment.md section moved above "Back to README"; observability.md sentence moved into the OTEL_SERVICE_VERSION table row.
10. version.controller.ts now has a single @nestjs/common import and @ApiBearerAuth().

Closes HelpCode-ai#1000

- packages/backend/src/common/app-version.ts: single source of truth
  exporting APP_VERSION, APP_COMMIT (APP_COMMIT || SENTRY_RELEASE || dev)
  and APP_BUILD_DATE (APP_BUILD_DATE || null), moving readAppVersion()
  out of mcp-endpoint.controller.ts
- packages/backend/src/tracing.ts + instrument.ts: use APP_VERSION as the
  service.version / Sentry release fallback instead of npm_package_version
- packages/backend/src/main.ts: log version, commit, build date and mode
  at startup
- packages/backend/src/health/version.controller.ts: new GET /api/version
  behind AuthGuard('jwt') returning { version, commit, buildDate,
  deploymentMode }; registered in health.module.ts
- packages/frontend/src/components/footer.tsx: show v{version} for
  signed-in users, with full version+commit in the tooltip
- Dockerfile: APP_COMMIT and APP_BUILD_DATE build args to ENV, plus
  org.opencontainers.image.revision and .version OCI labels
- app-version.spec.ts: unit tests for env precedence and dev fallback
- docs: deployment.md documents the build args; observability.md notes
  the service.version source change
@Furox-Art
Furox-Art force-pushed the feat/version-display branch from 5076aa5 to 2caf3b3 Compare October 11, 2026 12:40

@helpcodeai helpcodeai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the quick turnaround @Furox-Art. The backend side is in good shape now: I checked out the branch and tsc, lint and the full Jest run pass (524 suites), /api/version sits behind the JWT guard and /health/server-info is untouched. A few things are still off, and the first one breaks the build:

  1. packages/frontend/src/app/settings/admin/page.tsx calls versionApi.get(token) but never imports it, so the frontend typecheck fails (TS2304: Cannot find name 'versionApi' at line 68). Add it to the existing import { adminSettings, type AlertWebhookInput } from '@/lib/api'.
  2. Same file: the Copy button calls navigator.clipboard.writeText directly. On a self-hosted instance served over plain HTTP navigator.clipboard is undefined, so it throws before your .catch runs and nothing happens. Use copyText from @/lib/clipboard (already imported in that page). It returns a boolean and has the fallback. While you're there, the card shows only its heading when the fetch fails; a short "Version info unavailable" line would be better than an empty card.
  3. .github/workflows/docker-publish.yml only runs on workflow_dispatch, and that event has no head_commit, so APP_BUILD_DATE ends up empty and published images still log "built unknown". The metadata step already computes a build timestamp, so this works without an extra step: APP_BUILD_DATE=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }}
  4. docs/operations/observability.md: the sentence landed in the middle of the "Service identity" table, so the table stops at OTEL_SERVICE_VERSION and the OTEL_DEPLOYMENT_ENVIRONMENT row renders as plain text. Change the default in the OTEL_SERVICE_VERSION row from npm_package_version to APP_VERSION (the backend's package.json version) and put the sentence under the table.
  5. docs/deployment.md: sorry, my "move it above" was unclear. It's now the very first section, ahead of the top navigation and Quick Start. Please make it a ### Build provenance subsection under "Production Deployment", right after "With Docker (Manual)". Also use git rev-parse HEAD instead of --short HEAD in the example: the footer only links 40-character SHAs, so with the short form you never get the link. And drop the extra blank lines added at the end of both docs files.
  6. Small one in footer.tsx: getVersionOnce caches the failed promise too, so a single 401 (a token that expires right at that moment, say) hides the version for the rest of the session. Set versionPromise = null when the request fails so the next mount retries.

Once these are in it looks ready to me. As before, the merge itself waits for the 15 October answer on #1000.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🎃 Show the build version and git commit in the UI and the backend startup log

2 participants