diff --git a/vite.config.ts b/vite.config.ts index 52b30ff..38b7bef 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,7 +1,9 @@ -import { defineConfig } from 'vite'; +import { defineConfig, Plugin } from 'vite'; import solidPlugin from 'vite-plugin-solid'; import { dirname, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; +import { exec } from 'node:child_process'; +import { promisify } from 'node:util'; const __dirname = dirname(fileURLToPath(import.meta.url)); @@ -22,5 +24,68 @@ export default defineConfig({ '/api': 'http://localhost:3001', }, }, - plugins: [solidPlugin()], + plugins: [solidPlugin(), versionPlugin()], }); + +function versionPlugin(): Plugin { + return { + name: 'generate-version', + apply: 'build', + async generateBundle() { + this.emitFile({ + type: 'asset', + fileName: 'version.txt', + source: await getVersionInfo(), + }); + }, + }; +} + +async function getVersionInfo(): Promise { + const info: Record = { + build: new Date().toISOString(), + }; + + const execAsync = promisify(exec); + + const fromJujutsu = async () => { + const template = [ + 'change_id.short()', + 'commit_id.short()', + 'committer.timestamp().format("%Y-%m-%d")', + 'description.first_line()', + ].join(' ++ "\\t" ++ '); + const { stdout } = await execAsync( + `jj log -r '::@ & ~description("")' -n1 --no-graph -T '${template}'` + ); + const [change, hash, date, msg] = stdout.trim().split('\t'); + info.change = change; + info.hash = hash; + info.commit = `${msg} (${date})`; + }; + + const fromGit = async () => { + const { stdout } = await execAsync( + 'git log --format="%h%x09%cs%x09%s" -n 1' + ); + const [hash, date, msg] = stdout.trim().split('\t'); + info.hash = hash; + info.commit = `${msg} (${date})`; + }; + + try { + await fromJujutsu(); + } catch { + try { + await fromGit(); + } catch { + // No VCS available + } + } + + return ( + Object.entries(info) + .map(([k, v]) => `${k}: ${v}`) + .join('\n') + '\n' + ); +}