Skip to content

Conversation

@panteLx
Copy link
Owner

@panteLx panteLx commented Jan 4, 2026

Adds build-time metadata (build date, commit SHA/ref) and persists it as a structured build-info file.

Updates CI/Docker to pass and embed BUILD_DATE/COMMIT_SHA/COMMIT_REF, replaces simple .version handling with a .build-info.json reader and cached BuildInfo API, and exposes getBuildInfo/getCurrentVersion.

Updates version endpoint and client hook to return buildDate, short commit, github URL, isDev flag and improved latest-release/update detection and caching.

Removes reliance on branch env var and improves GitHub URL resolution for dev builds, enabling accurate build provenance and more reliable update checks.

Summary by CodeRabbit

  • New Features

    • Capture and embed build metadata (build date, commit SHA, commit ref) into releases and API responses.
    • Admin dashboard gains a System Information card showing version, build date, commit, GitHub/release links, and update status.
    • Version API and client hooks now expose buildDate and richer version info.
  • Chores

    • Removed unused environment example entry.

✏️ Tip: You can customize this high-level summary in your review settings.

Adds build-time metadata (build date, commit SHA/ref) and persists it as a structured build-info file.

Updates CI/Docker to pass and embed BUILD_DATE/COMMIT_SHA/COMMIT_REF, replaces simple .version handling with a .build-info.json reader and cached BuildInfo API, and exposes getBuildInfo/getCurrentVersion.

Updates version endpoint and client hook to return buildDate, short commit, github URL, isDev flag and improved latest-release/update detection and caching.

Removes reliance on branch env var and improves GitHub URL resolution for dev builds, enabling accurate build provenance and more reliable update checks.
Copilot AI review requested due to automatic review settings January 4, 2026 20:24
@coderabbitai
Copy link

coderabbitai bot commented Jan 4, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

This PR moves version and build metadata to be injected at build time: CI captures a BUILD_DATE timestamp and passes BUILD_DATE, COMMIT_SHA, and COMMIT_REF as Docker build-args. The Dockerfile writes a structured .build-info.json. App utilities, API route, hook, admin UI, and i18n read and surface that build-info instead of performing runtime GitHub fetches.

Changes

Cohort / File(s) Summary
CI Workflows
​.github/workflows/docker-dev.yml, ​.github/workflows/release.yml
Add a step that captures BUILD_DATE (ISO UTC) to GITHUB_OUTPUT and pass BUILD_DATE, COMMIT_SHA (github.sha), and COMMIT_REF (github.ref_name) as Docker build-args to the build-and-push step.
Dockerfile / Build metadata
Dockerfile
Add ARG BUILD_DATE, ARG COMMIT_SHA, ARG COMMIT_REF (runner stage) and write a JSON .build-info.json containing version, buildDate, commitSha, commitRef instead of a plain .version file.
Version utilities
lib/version.ts
Introduce exported BuildInfo interface and caching for it; add getBuildInfo() API; load .build-info.json (fallbacks to package.json/dev); update buildGitHubUrl() to accept optional commitSha.
Version API route
app/api/version/route.ts
Replace runtime GitHub commit fetch with getBuildInfo() usage; add VersionResponse shape including buildDate and commitHash; update caching and version/compare logic to use build-time info and short commit SHA.
Frontend admin UI
app/admin/page.tsx
Fetch /api/version on client, add system info card showing version, buildDate, commitHash, githubUrl, latestVersion/update badge; add loading states for version fetch.
Version hook
hooks/useVersionUpdate.ts
Extend VersionInfo to include buildDate: string (public interface change).
i18n
messages/en.json, messages/de.json, messages/it.json
Add admin.stats.systemInfo translation keys (title, description, version, buildDate, commitHash, latestVersion, updateAvailable, upToDate, viewOnGitHub, viewRelease, development, unknown).
Env example
.env.example
Remove GITHUB_BRANCH=main entry.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant CI as CI / GitHub Actions
    participant Docker as Docker build (Dockerfile)
    participant Container as App Runtime (container)
    participant Utils as lib/version.ts
    participant API as /api/version route
    Note over CI,Docker: Build-time
    CI->>CI: Capture BUILD_DATE (ISO UTC) -> GITHUB_OUTPUT
    CI->>Docker: Build & push (args: BUILD_DATE, COMMIT_SHA, COMMIT_REF, VERSION)
    Docker->>Docker: Create /app/.build-info.json (version, buildDate, commitSha, commitRef)
    Docker->>Container: Image includes .build-info.json
    Note over Container,API: Runtime
    API->>Utils: getBuildInfo()
    Utils->>Container: Read /app/.build-info.json (or fallback)
    Utils-->>API: Return BuildInfo
    API->>Utils: buildGitHubUrl(buildInfo.version, buildInfo.commitSha)
    Utils-->>API: Return github URL
    API->>API: Build VersionResponse (version, buildDate, commitHash, githubUrl, isDev, latest/version checks)
    API-->>Client: Return VersionResponse (cached)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

enhancement

Poem

🐰 Hop, I baked the time and sha,

Build-info tucked where files may lay.
No more runtime fetch at night,
Docker keeps our metadata tight.
Tiny rabbit cheers the build—hip, hooray!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main change: adding build metadata capture and a new build-info API, which aligns with the core modifications across Docker, CI workflows, version handling, and API endpoint.
✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

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

This PR modernizes the build metadata system by replacing the simple .version file with a structured .build-info.json file that captures comprehensive build information including version, build date, commit SHA, and commit reference. The changes improve build provenance tracking and enable more accurate update detection by eliminating the need for runtime GitHub API calls to fetch commit information.

Key changes:

  • Replaces .version file with .build-info.json containing structured metadata (version, buildDate, commitSha, commitRef)
  • Updates version API endpoint to return build metadata directly instead of fetching commit hash at runtime
  • Removes dependency on GITHUB_BRANCH environment variable for cleaner configuration

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
lib/version.ts Refactored to read structured build info from JSON file; added BuildInfo interface and getBuildInfo() function while maintaining backward compatibility
hooks/useVersionUpdate.ts Added buildDate field to VersionInfo interface for client-side consumption
app/api/version/route.ts Simplified to use pre-built metadata instead of runtime GitHub API calls; removed fetchCommitHash() and buildGitHubUrl() functions (moved to lib/version.ts)
Dockerfile Updated to write structured JSON metadata file instead of plain text version; accepts BUILD_DATE, COMMIT_SHA, and COMMIT_REF build args
.github/workflows/release.yml Added BUILD_DATE, COMMIT_SHA, and COMMIT_REF build arguments to Docker build step
.github/workflows/docker-dev.yml Added BUILD_DATE, COMMIT_SHA, and COMMIT_REF build arguments to Docker build step
.env.example Removed GITHUB_BRANCH environment variable as it's no longer needed
Comments suppressed due to low confidence (1)

app/api/version/route.ts:103

  • The version comparison logic only compares the first 3 segments (major.minor.patch) but doesn't handle pre-release versions (e.g., 1.0.0-alpha, 1.0.0-beta) or build metadata. If a version string contains these, they will be ignored in the comparison. Consider documenting this limitation or handling pre-release versions according to SemVer specification.
function compareVersions(current: string, latest: string): boolean {
  // Returns true if latest is newer than current
  // Remove 'v' prefix if present
  const cleanCurrent = current.replace(/^v/, "");
  const cleanLatest = latest.replace(/^v/, "");

  const parseCurrent = cleanCurrent.split(".").map(Number);
  const parseLatest = cleanLatest.split(".").map(Number);

  for (let i = 0; i < 3; i++) {
    const curr = parseCurrent[i] || 0;
    const lat = parseLatest[i] || 0;

    if (lat > curr) return true;
    if (lat < curr) return false;
  }

  return false;

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (3)
app/api/version/route.ts (1)

106-109: Consider a more precise dev version check.

The current implementation uses .includes("dev"), which might match unintended version strings (e.g., "1.2.3-devops", "1.2.3-development").

🔎 Suggested refinement for more precise matching
 function isDevVersion(version: string): boolean {
-  // Check if version is 'dev' or contains 'dev'
-  return version === "dev" || version.includes("dev");
+  // Check if version is exactly 'dev' or starts with 'dev-'
+  return version === "dev" || version.startsWith("dev-");
 }

This approach prevents false positives while still matching common dev version patterns like "dev", "dev-123", "dev-feature-branch".

lib/version.ts (2)

17-38: Consider simplifying file reading and validating buildDate format.

Two improvements to consider:

  1. The access() check at line 22 is unnecessary since readFile() will fail anyway if the file doesn't exist. This creates a minor TOCTOU (time-of-check-time-of-use) pattern.

  2. Per coding guidelines, dates should be in YYYY-MM-DD format. Consider validating the buildDate field format to catch misconfiguration early.

🔎 Proposed improvements
 async function getDockerBuildInfo(): Promise<BuildInfo | null> {
   try {
     const buildInfoPath = join(process.cwd(), ".build-info.json");
-
-    // Check if file exists
-    await access(buildInfoPath);
 
     // Read and parse build info
     const content = await readFile(buildInfoPath, "utf-8");
     const info = JSON.parse(content);
+
+    // Validate buildDate format (YYYY-MM-DD)
+    const datePattern = /^\d{4}-\d{2}-\d{2}$/;
+    if (info.buildDate && !datePattern.test(info.buildDate) && info.buildDate !== "unknown") {
+      console.warn(`Invalid buildDate format: ${info.buildDate}, expected YYYY-MM-DD`);
+    }
 
     return {
       version: info.version || "unknown",
       buildDate: info.buildDate || "unknown",
       commitSha: info.commitSha || "unknown",
       commitRef: info.commitRef || "unknown",
     };
   } catch {
     // File doesn't exist or can't be read
     return null;
   }
 }

Based on coding guidelines requiring YYYY-MM-DD date format.


130-149: LGTM! Enhanced GitHub URL generation.

The addition of commit SHA support for dev builds is a valuable improvement. The function correctly handles semver versions, dev builds with commit info, and fallback scenarios.

Optional note: The semver pattern /^v?\d+\.\d+\.\d+$/ only matches basic versions (e.g., "1.2.3") and doesn't handle pre-release versions (e.g., "1.2.3-beta.1") or build metadata. This is likely intentional for the current use case, but if you need to support pre-release versions in the future, the pattern would need adjustment.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6128de6 and fc1cd5b.

📒 Files selected for processing (7)
  • .env.example
  • .github/workflows/docker-dev.yml
  • .github/workflows/release.yml
  • Dockerfile
  • app/api/version/route.ts
  • hooks/useVersionUpdate.ts
  • lib/version.ts
💤 Files with no reviewable changes (1)
  • .env.example
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Store and display dates as YYYY-MM-DD strings (local dates without timezone conversion). Use formatDateToLocal() from lib/date-utils.ts before saving to database and date-fns with locale from getDateLocale() for display.
Use Drizzle-inferred types from schema directly (no any types). TypeScript must remain in strict mode with proper type safety throughout the application.
All React files must be in strict mode with TypeScript 5. No any types allowed. Import inferred types from Drizzle schema.
Use formatDateToLocal(date) utility from lib/date-utils.ts to convert dates to YYYY-MM-DD format before saving to database.

Files:

  • hooks/useVersionUpdate.ts
  • app/api/version/route.ts
  • lib/version.ts
hooks/use*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Implement data fetching hooks following the pattern: useShifts, usePresets, useNotes, useCalendars with accompanying action hooks like useShiftActions, useNoteActions for CRUD operations with optimistic updates.

Files:

  • hooks/useVersionUpdate.ts
app/**/*.{tsx,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

All components under app/ are Server Components by default unless marked with "use client". Use "use client" directive only for interactive UI components.

Files:

  • app/api/version/route.ts
app/api/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

app/api/**/*.ts: All API routes must include GET/POST/PUT/PATCH/DELETE exports in app/api/** directory and follow the pattern: check permissions → perform database operation → emit SSE event.
Use getSessionUser(request.headers) from lib/auth/sessions.ts to get current user in API routes. Use Better Auth's authClient methods on the client side for session management.
After any database mutation (create/update/delete), emit an SSE event using eventEmitter.emit('calendar-change', {...}) with appropriate type and action to keep clients in sync.
For calendar permission hierarchy in SQL queries and permission checks, follow: owner (highest) > admin > write > read (lowest). Use getUserAccessibleCalendars(userId) to get all accessible calendars.
Use getUserCalendarPermission(userId, calendarId) from lib/auth/permissions.ts to retrieve the exact permission level, which returns permission string or null if user has no access.

Files:

  • app/api/version/route.ts
🧬 Code graph analysis (1)
app/api/version/route.ts (1)
lib/version.ts (2)
  • getBuildInfo (91-107)
  • buildGitHubUrl (130-149)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Agent
  • GitHub Check: build-dev
🔇 Additional comments (11)
hooks/useVersionUpdate.ts (1)

6-6: LGTM!

The addition of the buildDate field aligns with the new BuildInfo-based versioning model and matches the response from the updated /api/version endpoint.

app/api/version/route.ts (4)

12-21: LGTM!

The new VersionResponse interface provides a clear, type-safe structure for the API response, including all necessary fields for version tracking, update detection, and build provenance.


86-104: LGTM!

The updated compareVersions function now correctly handles version strings with or without the 'v' prefix, improving robustness when comparing versions from different sources.


111-164: Excellent refactoring to build-time metadata approach.

The new implementation eliminates runtime GitHub API calls for commit information, instead relying on build-time injected metadata. This improves reliability, reduces external dependencies, and provides faster response times. The caching strategy is well-documented and consistent across the codebase.


140-151: No action required. The commitSha.substring(0, 7) operation is type-safe and properly guarded. The getBuildInfo() function guarantees commitSha is always a string through both the TypeScript interface definition and implementation-level fallbacks ("unknown" for missing values, "dev" for development mode).

Likely an incorrect or invalid review comment.

lib/version.ts (6)

4-9: LGTM! Clean interface design.

The BuildInfo interface is well-structured with appropriate string types for all fields.


59-73: LGTM! Proper fallback handling.

The fallback chain (Docker build-info → package.json → dev defaults) is well-implemented and ensures the function always returns valid BuildInfo.


79-85: LGTM! Correct initialization logic.

The initialization properly caches BuildInfo and handles the promise lifecycle correctly.


91-107: LGTM! Well-implemented caching pattern.

The function correctly handles concurrent calls and prevents redundant file reads with proper promise-based synchronization.


113-116: LGTM! Proper delegation.

The function correctly delegates to getBuildInfo() and extracts the version field, maintaining the expected API surface.


154-165: LGTM! Properly integrated with BuildInfo.

The function correctly uses the new getBuildInfo() API and passes the commit SHA for accurate GitHub URL generation.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
Dockerfile (1)

77-78: Node.js approach properly addresses JSON escaping concerns.

The current implementation using node -e with JSON.stringify correctly handles special characters and escaping, addressing the concerns raised in previous reviews. The fallback pattern ||'' ensures that missing build args result in empty strings rather than undefined values in the JSON.

lib/version.ts (1)

17-45: LGTM! Proper error handling for JSON parsing added.

The nested try-catch properly separates JSON parsing errors from file access errors, with appropriate logging for both cases. This addresses the concern raised in previous reviews.

🧹 Nitpick comments (3)
app/admin/page.tsx (3)

61-63: Missing dependency in useEffect or define function inside.

The useEffect references fetchVersionInfo but it's not in the dependency array. While this works because fetchVersionInfo is stable (no dependencies on state/props), ESLint's react-hooks/exhaustive-deps rule will flag this. Either move fetchVersionInfo inside the effect or wrap it with useCallback.

🔎 Proposed fix
-  // Fetch version info
-  useEffect(() => {
-    fetchVersionInfo();
-  }, []);
-
-  const fetchVersionInfo = async () => {
+  useEffect(() => {
+    const fetchVersionInfo = async () => {
+      try {
+        const response = await fetch("/api/version");
+        if (!response.ok) return;
+        const data = await response.json();
+        setVersionInfo(data);
+      } catch (error) {
+        console.error("Failed to fetch version info:", error);
+      } finally {
+        setIsLoadingVersion(false);
+      }
+    };
+
+    fetchVersionInfo();
+  }, []);
-    try {
-      const response = await fetch("/api/version");
-      if (!response.ok) return;
-      const data = await response.json();
-      setVersionInfo(data);
-    } catch (error) {
-      console.error("Failed to fetch version info:", error);
-    } finally {
-      setIsLoadingVersion(false);
-    }
-  };

167-173: Consider defensive date parsing.

If buildDate is neither "dev"/"unknown" nor a valid ISO date string, new Date() returns an Invalid Date, and format() may throw or display unexpected output. Consider adding a validity check.

🔎 Proposed fix
-                  {versionInfo.buildDate !== "dev" &&
-                  versionInfo.buildDate !== "unknown"
-                    ? format(new Date(versionInfo.buildDate), "PPp", {
-                        locale: dateLocale,
-                      })
-                    : t("admin.systemInfo.unknown")}
+                  {(() => {
+                    if (versionInfo.buildDate === "dev" || versionInfo.buildDate === "unknown") {
+                      return t("admin.systemInfo.unknown");
+                    }
+                    const date = new Date(versionInfo.buildDate);
+                    return isNaN(date.getTime())
+                      ? t("admin.systemInfo.unknown")
+                      : format(date, "PPp", { locale: dateLocale });
+                  })()}

33-42: Consider importing the shared type from a central location.

The VersionInfo interface is defined locally here and also as VersionResponse in app/api/version/route.ts. To avoid drift, consider exporting the type from a shared location (e.g., lib/version.ts or a types/ file) and importing it in both places.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc1cd5b and 13438bb.

📒 Files selected for processing (9)
  • .github/workflows/docker-dev.yml
  • .github/workflows/release.yml
  • Dockerfile
  • app/admin/page.tsx
  • app/api/version/route.ts
  • lib/version.ts
  • messages/de.json
  • messages/en.json
  • messages/it.json
🚧 Files skipped from review as they are similar to previous changes (2)
  • .github/workflows/release.yml
  • .github/workflows/docker-dev.yml
🧰 Additional context used
📓 Path-based instructions (3)
app/**/*.{tsx,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

All components under app/ are Server Components by default unless marked with "use client". Use "use client" directive only for interactive UI components.

Files:

  • app/api/version/route.ts
  • app/admin/page.tsx
app/api/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

app/api/**/*.ts: All API routes must include GET/POST/PUT/PATCH/DELETE exports in app/api/** directory and follow the pattern: check permissions → perform database operation → emit SSE event.
Use getSessionUser(request.headers) from lib/auth/sessions.ts to get current user in API routes. Use Better Auth's authClient methods on the client side for session management.
After any database mutation (create/update/delete), emit an SSE event using eventEmitter.emit('calendar-change', {...}) with appropriate type and action to keep clients in sync.
For calendar permission hierarchy in SQL queries and permission checks, follow: owner (highest) > admin > write > read (lowest). Use getUserAccessibleCalendars(userId) to get all accessible calendars.
Use getUserCalendarPermission(userId, calendarId) from lib/auth/permissions.ts to retrieve the exact permission level, which returns permission string or null if user has no access.

Files:

  • app/api/version/route.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Store and display dates as YYYY-MM-DD strings (local dates without timezone conversion). Use formatDateToLocal() from lib/date-utils.ts before saving to database and date-fns with locale from getDateLocale() for display.
Use Drizzle-inferred types from schema directly (no any types). TypeScript must remain in strict mode with proper type safety throughout the application.
All React files must be in strict mode with TypeScript 5. No any types allowed. Import inferred types from Drizzle schema.
Use formatDateToLocal(date) utility from lib/date-utils.ts to convert dates to YYYY-MM-DD format before saving to database.

Files:

  • app/api/version/route.ts
  • lib/version.ts
  • app/admin/page.tsx
🧠 Learnings (1)
📚 Learning: 2026-01-03T02:03:48.622Z
Learnt from: CR
Repo: panteLx/BetterShift PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-01-03T02:03:48.622Z
Learning: All user-facing strings must use the `t()` function from `next-intl` for translations. Never use hardcoded English strings in components or API responses.

Applied to files:

  • app/admin/page.tsx
🧬 Code graph analysis (2)
app/api/version/route.ts (1)
lib/version.ts (2)
  • getBuildInfo (98-114)
  • buildGitHubUrl (137-156)
app/admin/page.tsx (3)
components/ui/button.tsx (1)
  • Button (60-60)
components/ui/card.tsx (5)
  • Card (85-85)
  • CardHeader (86-86)
  • CardTitle (88-88)
  • CardDescription (90-90)
  • CardContent (91-91)
components/ui/badge.tsx (1)
  • Badge (36-36)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-dev
🔇 Additional comments (15)
messages/en.json (1)

648-661: LGTM! Translation keys align with BuildInfo structure.

The new systemInfo translation keys are well-structured and consistent with the admin UI pattern. They properly support the new build metadata display functionality.

messages/it.json (1)

648-661: LGTM! Italian translations are consistent.

The Italian translations for the systemInfo section are well-structured and align with the English version.

messages/de.json (1)

648-661: LGTM! German translations are consistent.

The German translations for the systemInfo section are well-structured and align with the other locales.

lib/version.ts (6)

4-9: LGTM! BuildInfo interface is well-defined.

The interface clearly defines the structure for build metadata, matching the data generated by the Dockerfile.


11-12: LGTM! Caching pattern prevents redundant file reads.

The dual caching approach (cached result + in-flight promise) properly handles both the loaded state and concurrent access scenarios.


66-80: LGTM! Fallback chain ensures robustness.

The function gracefully degrades from production build info to development defaults, ensuring a valid BuildInfo is always returned.


98-114: LGTM! Async caching pattern is correctly implemented.

The function properly handles caching, in-flight promises, and loading, ensuring efficient and race-condition-free access to build info.


120-123: LGTM! Clean wrapper maintains backward compatibility.

The function provides a convenient way to get just the version string while leveraging the full BuildInfo infrastructure.


137-156: LGTM! GitHub URL generation enhanced with commit support.

The function now properly generates commit URLs for development builds while maintaining backward compatibility with release tag URLs for semantic versions.

app/admin/page.tsx (1)

106-242: LGTM!

The System Information Card is well-implemented:

  • Proper loading and error states
  • External links use rel="noopener noreferrer" for security
  • Translation keys are used consistently via t() (as per learnings)
  • Conditional rendering for update badges and dev mode is clean
app/api/version/route.ts (5)

2-2: LGTM!

Clean import of build utilities and well-defined response interface. The VersionResponse structure properly captures all the version metadata fields needed by the frontend.

Also applies to: 12-21


86-104: LGTM!

The version comparison correctly handles the 'v' prefix and performs proper semver comparison for standard major.minor.patch versions.


142-145: Previous feedback addressed.

The commit hash handling now explicitly checks length before truncating, which addresses the concern from the past review about short strings like "unknown" or "dev".


111-167: LGTM!

The GET handler is well-structured:

  • Efficient caching with early return when cache is valid
  • Proper use of getBuildInfo and buildGitHubUrl from the shared library
  • Smart optimization: only fetches latest release for non-dev versions
  • Consistent Cache-Control headers on both cached and fresh responses

44-84: Well-implemented with graceful degradation.

The getLatestRelease function handles errors gracefully by returning null and properly manages both in-memory and Next.js fetch caching layers. The optional GITHUB_TOKEN handling is clean.

@panteLx panteLx merged commit 5c3dde9 into main Jan 4, 2026
3 checks passed
@panteLx panteLx deleted the feat/version-info branch January 4, 2026 21:18
@panteLx panteLx changed the title feat: Adds build metadata and build-info API feat: Adds build metadata, build-info API and admin panel build infos Jan 4, 2026
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.

3 participants