From 645a1b62208d5fc80d29b0f03031d3a87503088f Mon Sep 17 00:00:00 2001 From: Tom Butcher Date: Sun, 21 Jun 2026 13:19:15 +0100 Subject: [PATCH] Implemented about page. --- .gitignore | 5 ++++- Jenkinsfile | 10 ++++++++++ src/index.js | 2 ++ src/routes/index.js | 2 ++ src/routes/misc/server.js | 9 +++++++++ src/services/misc/appupdate.js | 4 +++- src/services/misc/server.js | 28 ++++++++++++++++++++++++++++ 7 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 src/routes/misc/server.js create mode 100644 src/services/misc/server.js diff --git a/.gitignore b/.gitignore index c2ddb7d..37879ec 100644 --- a/.gitignore +++ b/.gitignore @@ -141,4 +141,7 @@ gcodefile gcodefiles/* gcodefiles -test-results.xml \ No newline at end of file +test-results.xml + +# Jenkins generated build metadata +src/buildInfo.json diff --git a/Jenkinsfile b/Jenkinsfile index ab42189..d0675c3 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -23,6 +23,16 @@ pipeline { } } + stage('Write Build Metadata') { + steps { + nodejs(nodeJSInstallationName: 'Node23') { + sh ''' + node -e "const fs = require('fs'); fs.writeFileSync('src/buildInfo.json', JSON.stringify({ buildNumber: process.env.BUILD_NUMBER || 'dev' }, null, 2) + '\\n');" + ''' + } + } + } + stage('Install Dependencies') { steps { nodejs(nodeJSInstallationName: 'Node23') { diff --git a/src/index.js b/src/index.js index 79b634b..0f89a23 100644 --- a/src/index.js +++ b/src/index.js @@ -60,6 +60,7 @@ import { csvRoutes, appLaunchRoutes, appUpdateRoutes, + serverRoutes, } from './routes/index.js'; import path from 'path'; import * as fs from 'fs'; @@ -187,6 +188,7 @@ app.use('/excel', excelRoutes); app.use('/csv', csvRoutes); app.use('/applaunch', appLaunchRoutes); app.use('/appupdate', appUpdateRoutes); +app.use('/server', serverRoutes); // Start the application if (process.env.NODE_ENV !== 'test') { diff --git a/src/routes/index.js b/src/routes/index.js index de0d626..27abad8 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -53,6 +53,7 @@ import excelRoutes from './misc/excel.js'; import csvRoutes from './misc/csv.js'; import appLaunchRoutes from './misc/applaunch.js'; import appUpdateRoutes from './misc/appupdate.js'; +import serverRoutes from './misc/server.js'; export { userRoutes, @@ -110,4 +111,5 @@ export { csvRoutes, appLaunchRoutes, appUpdateRoutes, + serverRoutes, }; diff --git a/src/routes/misc/server.js b/src/routes/misc/server.js new file mode 100644 index 0000000..ce988c1 --- /dev/null +++ b/src/routes/misc/server.js @@ -0,0 +1,9 @@ +import express from 'express'; +import { isAuthenticated } from '../../keycloak.js'; +import { serverVersionRouteHandler } from '../../services/misc/server.js'; + +const router = express.Router(); + +router.get('/version', isAuthenticated, serverVersionRouteHandler); + +export default router; diff --git a/src/services/misc/appupdate.js b/src/services/misc/appupdate.js index 0fef98d..2a8addb 100644 --- a/src/services/misc/appupdate.js +++ b/src/services/misc/appupdate.js @@ -19,7 +19,7 @@ const buildApiUrl = (baseUrl, query = '') => { }; const getBranchBuildApiUrl = (branchUrl, buildType = 'lastSuccessfulBuild') => - `${normalizeProjectUrl(branchUrl)}/${buildType}/api/json?tree=number,url,result,timestamp,artifacts[fileName,relativePath]`; + `${normalizeProjectUrl(branchUrl)}/${buildType}/api/json?tree=number,url,result,displayName,timestamp,artifacts[fileName,relativePath]`; const mapArtifacts = (build, requestedBranch) => { const buildUrl = normalizeProjectUrl(build?.url); @@ -107,8 +107,10 @@ export const appUpdateCurrentRouteHandler = async (req, res) => { return res.send({ branch: requestedBranch, buildNumber: build.number, + buildUrl: build.url, buildResult: build.result, + buildName: build.displayName, buildTimestamp: build.timestamp, buildSource: source, artifacts: mapArtifacts(build, requestedBranch), diff --git a/src/services/misc/server.js b/src/services/misc/server.js new file mode 100644 index 0000000..f4c570c --- /dev/null +++ b/src/services/misc/server.js @@ -0,0 +1,28 @@ +import { readFileSync } from 'node:fs'; + +const readJsonFile = (fileUrl) => { + try { + return JSON.parse(readFileSync(fileUrl, 'utf8')); + } catch { + return {}; + } +}; + +const packageJsonUrl = new URL('../../../package.json', import.meta.url); +const buildInfoUrl = new URL('../../buildInfo.json', import.meta.url); + +const getServerVersionInfo = () => { + const packageJson = readJsonFile(packageJsonUrl); + const buildInfo = readJsonFile(buildInfoUrl); + + return { + version: packageJson.version ?? 'dev', + buildNumber: buildInfo.buildNumber ?? 'dev', + }; +}; + +export const serverVersionRouteHandler = (req, res) => { + res.json({ + ...getServerVersionInfo(), + }); +};