diff --git a/common/src/api/schema.ts b/common/src/api/schema.ts index b5711691..32266252 100644 --- a/common/src/api/schema.ts +++ b/common/src/api/schema.ts @@ -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', diff --git a/web/components/about-settings.tsx b/web/components/about-settings.tsx index c95bb69c..4d777d64 100644 --- a/web/components/about-settings.tsx +++ b/web/components/about-settings.tsx @@ -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(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 = () => ( @@ -21,75 +131,68 @@ const LoadedAboutSettings = (props: { }) => { const {} = props - return - {IS_VERCEL && } - {Capacitor.isNativePlatform() && } - - + 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 + + + + + } -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 + return

Web build (Vercel)

Commit SHA: {sha}

-

Commit message: {msg}

+

Commit message: {gitMessage}

Vercel deployment ID: {deploymentId}

Environment: {env}

} -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(null) - const [androidAppVersion, setAndroidAppVersion] = useState(null) - const [androidBuildNumber, setAndroidBuildNumber] = useState(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 +const AndroidInfo = (props: {info?: Android}) => { + const {info} = props + if (!info) return + return

Android (Capacitor / Capawesome)

-

App version (Android): {androidAppVersion}

-

Native build number (Android): {androidBuildNumber}

-

Live update build ID (Capawesome): {liveUpdateBundleId}

-

Live update commit - (Capawesome): {liveUpdateInfo.commitSha}, {liveUpdateInfo.commitMessage}, {liveUpdateInfo.gitRef}

-

Env: {JSON.stringify(Object.fromEntries(Object.entries(process.env).sort()), null, 2)}

+

App version (Android): {info.appVersion}

+

Native build number (Android): {info.buildNumber}

+

Live update build ID (Capawesome): {info.liveUpdate?.bundleId}

+

Live update commit (Capawesome): {JSON.stringify(info.liveUpdate)}

} -const BackendInfo = () => { - const [info, setInfo] = useState({}) - 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 + return

Backend

API version: {info.version}

{sha &&

API commit SHA: {sha}

} @@ -98,9 +201,12 @@ const BackendInfo = () => { } -const RuntimeInfo = () => { - return +const RuntimeInfo = (props: {info?: Runtime}) => { + const {info} = props + if (!info) return + return

Runtime

-

Platform: {IS_VERCEL ? 'Web' : Capacitor.isNativePlatform() ? 'Android' : HOSTING_ENV}

+

Platform: {info.platform}

+

Env: {JSON.stringify(Object.fromEntries(Object.entries(process.env).sort()), null, 2)}

}