This commit is contained in:
MartinBraquet
2025-12-15 14:44:40 +02:00
parent ed094bbeca
commit 009d4bf91f
2 changed files with 174 additions and 68 deletions

View File

@@ -49,7 +49,7 @@ export const API = (_apiTypeCheck = {
message: 'Server is working.'
uid?: string
version?: string
git?: { revision?: string; commitDate?: string; author?: string }
git?: { revision?: string; commitDate?: string; author?: string, message?: string }
},
summary: 'Check whether the API server is running',
tag: 'General',

View File

@@ -1,14 +1,124 @@
import {WithPrivateUser} from "web/components/user/with-user";
import {PrivateUser} from "common/user";
import {Col} from "web/components/layout/col";
import {HOSTING_ENV, IS_VERCEL} from "common/hosting/constants";
import {Capacitor} from "@capacitor/core";
import {LiveUpdate} from "@capawesome/capacitor-live-update";
import {useEffect, useState} from "react";
import {App} from "@capacitor/app";
import {api} from "web/lib/api";
import {githubRepo} from "common/constants";
import {CustomLink} from "web/components/links";
import {WithPrivateUser} from "web/components/user/with-user"
import {PrivateUser} from "common/user"
import {Col} from "web/components/layout/col"
import {HOSTING_ENV, IS_VERCEL} from "common/hosting/constants"
import {Capacitor} from "@capacitor/core"
import {LiveUpdate} from "@capawesome/capacitor-live-update"
import {useEffect, useState} from "react"
import {App} from "@capacitor/app"
import {api} from "web/lib/api"
import {githubRepo} from "common/constants"
import {CustomLink} from "web/components/links"
import {Button} from "web/components/buttons/button"
export type WebBuild = {
gitSha?: string
gitMessage?: string
deploymentId?: string
environment?: string
}
export type LiveUpdateInfo = {
bundleId?: string | null
commitSha?: string
commitMessage?: string
}
export type Android = {
appVersion?: string
buildNumber?: string
liveUpdate?: LiveUpdateInfo
}
export type Backend = {
version?: string
gitSha?: string
gitMessage?: string
commitDate?: string
}
export type Runtime = {
platform: string
}
export type Diagnostics = {
web?: WebBuild,
android?: Android
backend?: Backend
runtime: Runtime
}
function useDiagnostics() {
const [data, setData] = useState<Diagnostics | null>(null)
useEffect(() => {
const load = async () => {
const diagnostics: Diagnostics = {
runtime: {
platform: IS_VERCEL
? 'web'
: Capacitor.isNativePlatform()
? 'android'
: HOSTING_ENV
}
}
if (IS_VERCEL) {
diagnostics.web = {
environment: process.env.NEXT_PUBLIC_VERCEL_ENV,
gitSha: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA,
gitMessage: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_MESSAGE,
deploymentId: process.env.NEXT_PUBLIC_VERCEL_DEPLOYMENT_ID,
}
}
if (Capacitor.isNativePlatform()) {
const appInfo = await App.getInfo()
const bundle = await LiveUpdate.getCurrentBundle().catch(() => {return {bundleId: null}})
diagnostics.android = {
appVersion: appInfo.version,
buildNumber: appInfo.build,
liveUpdate: {
bundleId: bundle.bundleId,
commitSha: process.env.CAPAWESOME_BUILD_GIT_COMMIT_SHA || 'N/A',
commitMessage: process.env.CAPAWESOME_BUILD_GIT_COMMIT_MESSAGE || 'N/A',
}
}
}
const backend = await api('health').catch(() => null)
if (backend) {
diagnostics.backend = {
version: backend.version,
gitSha: backend.git?.revision,
gitMessage: backend.git?.message,
commitDate: backend.git?.commitDate
}
}
setData(diagnostics)
}
load()
}, [])
return data
}
function diagnosticsToText(d: Diagnostics): string {
const replacer = (key: string, value: any) => {
if (value === null) return 'null'
if (value === undefined) return 'undefined'
return value
}
return JSON.stringify(d, replacer, 2)
.replace(/["{}\[\]]/g, '')
.replace(/^[ \t]*\n/gm, '')
.replace(/,\n/g, '\n')
.trim()
}
export const AboutSettings = () => (
<WithPrivateUser>
@@ -21,75 +131,68 @@ const LoadedAboutSettings = (props: {
}) => {
const {} = props
return <Col className={'custom-link'}>
{IS_VERCEL && <WebBuildInfo/>}
{Capacitor.isNativePlatform() && <AndroidInfo/>}
<BackendInfo/>
<RuntimeInfo/>
const [copyFeedback, setCopyFeedback] = useState('')
const diagnostics = useDiagnostics()
if (!diagnostics) return null
const handleCopy = async () => {
if (!diagnostics) return
await navigator.clipboard.writeText(diagnosticsToText(diagnostics))
setCopyFeedback('Copied!')
}
return <Col className={''}>
<WebBuildInfo info={diagnostics.web}/>
<AndroidInfo info={diagnostics.android}/>
<BackendInfo info={diagnostics.backend}/>
<RuntimeInfo info={diagnostics.runtime}/>
<Button
onClick={handleCopy}
className="w-fit mt-4"
>
{copyFeedback || 'Copy Info'}
</Button>
</Col>
}
const WebBuildInfo = () => {
const env = process.env.NEXT_PUBLIC_VERCEL_ENV
const msg = process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_MESSAGE
const sha = process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA
const deploymentId = process.env.NEXT_PUBLIC_VERCEL_DEPLOYMENT_ID
const WebBuildInfo = (props: {info?: WebBuild}) => {
const {info} = props
if (!info) return
const env = info.environment
const gitMessage = info.gitMessage
const sha = info.gitSha
const deploymentId = info.deploymentId
const url = `${githubRepo}/commit/${sha}`
return <Col>
return <Col className={'custom-link'}>
<h3>Web build (Vercel)</h3>
<p>Commit SHA: <CustomLink href={url}>{sha}</CustomLink></p>
<p>Commit message: {msg}</p>
<p>Commit message: {gitMessage}</p>
<p>Vercel deployment ID: {deploymentId}</p>
<p>Environment: {env}</p>
</Col>
}
const AndroidInfo = () => {
const liveUpdateInfo = {
commitSha: process.env.CAPAWESOME_BUILD_GIT_COMMIT_SHA || 'N/A',
commitMessage: process.env.CAPAWESOME_BUILD_GIT_COMMIT_MESSAGE || 'N/A',
gitRef: process.env.CAPAWESOME_BUILD_GIT_REF || 'N/A',
};
console.log(`Current Commit SHA: ${liveUpdateInfo.commitSha}`);
const [liveUpdateBundleId, setLiveUpdateBundleId] = useState<string | null>(null)
const [androidAppVersion, setAndroidAppVersion] = useState<string | null>(null)
const [androidBuildNumber, setAndroidBuildNumber] = useState<string | null>(null)
useEffect(() => {
const load = async () => {
const liveUpdateBundle = await LiveUpdate.getCurrentBundle()
console.log('liveUpdateBundle', liveUpdateBundle)
setLiveUpdateBundleId(liveUpdateBundle.bundleId)
alert(liveUpdateBundle)
const info = await App.getInfo()
setAndroidAppVersion(info.version)
setAndroidBuildNumber(info.build)
}
load()
}, [])
return <Col>
const AndroidInfo = (props: {info?: Android}) => {
const {info} = props
if (!info) return
return <Col className={'custom-link'}>
<h3>Android (Capacitor / Capawesome)</h3>
<p>App version (Android): {androidAppVersion}</p>
<p>Native build number (Android): {androidBuildNumber}</p>
<p>Live update build ID (Capawesome): {liveUpdateBundleId}</p>
<p>Live update commit
(Capawesome): {liveUpdateInfo.commitSha}, {liveUpdateInfo.commitMessage}, {liveUpdateInfo.gitRef}</p>
<p>Env: {JSON.stringify(Object.fromEntries(Object.entries(process.env).sort()), null, 2)}</p>
<p>App version (Android): {info.appVersion}</p>
<p>Native build number (Android): {info.buildNumber}</p>
<p>Live update build ID (Capawesome): {info.liveUpdate?.bundleId}</p>
<p>Live update commit (Capawesome): {JSON.stringify(info.liveUpdate)}</p>
</Col>
}
const BackendInfo = () => {
const [info, setInfo] = useState<any>({})
useEffect(() => {
api('health').then(setInfo)
}, [])
console.log('Backend info', info)
const gitInfo = info.git || {}
const sha = gitInfo.revision
const commitDate = gitInfo.commitDate
const commitMessage = gitInfo.message
const BackendInfo = (props: {info?: Backend}) => {
const {info} = props
if (!info) return
const sha = info.gitSha
const commitDate = info.commitDate
const commitMessage = info.gitMessage
const url = `${githubRepo}/commit/${sha}`
return <Col>
return <Col className={'custom-link'}>
<h3>Backend</h3>
<p>API version: {info.version}</p>
{sha && <p>API commit SHA: <CustomLink href={url}>{sha}</CustomLink></p>}
@@ -98,9 +201,12 @@ const BackendInfo = () => {
</Col>
}
const RuntimeInfo = () => {
return <Col>
const RuntimeInfo = (props: {info?: Runtime}) => {
const {info} = props
if (!info) return
return <Col className={'custom-link'}>
<h3>Runtime</h3>
<p>Platform: {IS_VERCEL ? 'Web' : Capacitor.isNativePlatform() ? 'Android' : HOSTING_ENV}</p>
<p>Platform: {info.platform}</p>
<p>Env: {JSON.stringify(Object.fromEntries(Object.entries(process.env).sort()), null, 2)}</p>
</Col>
}