Skip to content

Commit e7b1c33

Browse files
committed
centralize the logic for determining the display version
1 parent 7608a93 commit e7b1c33

4 files changed

Lines changed: 187 additions & 370 deletions

File tree

build/spaVersionMetadata.mjs

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import { existsSync, readFileSync } from 'node:fs'
2+
import * as path from 'node:path'
3+
4+
export function getNodeEnv() {
5+
return globalThis.process?.env
6+
}
7+
8+
function normalizeTag(tag) {
9+
if (!tag) {
10+
return undefined
11+
}
12+
13+
return tag.replace(/^refs\/tags\//, '').replace(/^v/, '')
14+
}
15+
16+
function resolveSpaVersionDisplay({ packageVersion, commitSha, exactTag, refName, refType }) {
17+
const releaseTag = refType === 'tag' ? refName : exactTag
18+
19+
if (packageVersion && normalizeTag(releaseTag) === packageVersion) {
20+
return packageVersion
21+
}
22+
23+
if (commitSha) {
24+
return commitSha
25+
}
26+
27+
return packageVersion ?? 'unknown'
28+
}
29+
30+
function readTextFile(filePath) {
31+
try {
32+
return readFileSync(filePath, 'utf8').trim() || undefined
33+
} catch {
34+
return undefined
35+
}
36+
}
37+
38+
export function resolveProjectRoot(configDir) {
39+
const candidates = [configDir, path.resolve(configDir, '..'), path.resolve(configDir, '../..')]
40+
41+
const projectRoot = candidates.find((candidate) => {
42+
return (
43+
existsSync(path.join(candidate, 'package.json')) && existsSync(path.join(candidate, '.git'))
44+
)
45+
})
46+
47+
return projectRoot ?? configDir
48+
}
49+
50+
function readPackageVersion(projectRoot) {
51+
try {
52+
const packageJson = JSON.parse(readFileSync(path.join(projectRoot, 'package.json'), 'utf8'))
53+
54+
return packageJson.version
55+
} catch {
56+
return undefined
57+
}
58+
}
59+
60+
function resolveGitDir(projectRoot) {
61+
const dotGitPath = path.join(projectRoot, '.git')
62+
63+
if (!existsSync(dotGitPath)) {
64+
return undefined
65+
}
66+
67+
const dotGitContent = readTextFile(dotGitPath)
68+
69+
if (dotGitContent?.startsWith('gitdir: ')) {
70+
return path.resolve(projectRoot, dotGitContent.slice('gitdir: '.length))
71+
}
72+
73+
return dotGitPath
74+
}
75+
76+
function readPackedRef(gitDir, ref) {
77+
const packedRefs = readTextFile(path.join(gitDir, 'packed-refs'))
78+
79+
if (!packedRefs) {
80+
return undefined
81+
}
82+
83+
for (const line of packedRefs.split('\n')) {
84+
if (!line || line.startsWith('#') || line.startsWith('^')) {
85+
continue
86+
}
87+
88+
const [sha, packedRef] = line.split(' ')
89+
if (packedRef === ref) {
90+
return sha
91+
}
92+
}
93+
94+
return undefined
95+
}
96+
97+
function readGitHeadInfo(projectRoot) {
98+
const gitDir = resolveGitDir(projectRoot)
99+
100+
if (!gitDir) {
101+
return {}
102+
}
103+
104+
const head = readTextFile(path.join(gitDir, 'HEAD'))
105+
106+
if (!head) {
107+
return {}
108+
}
109+
110+
if (!head.startsWith('ref: ')) {
111+
return { commitSha: head.slice(0, 9) }
112+
}
113+
114+
const ref = head.slice('ref: '.length)
115+
const commitSha = readTextFile(path.join(gitDir, ref)) ?? readPackedRef(gitDir, ref)
116+
const exactTag = ref.startsWith('refs/tags/') ? ref.replace('refs/tags/', '') : undefined
117+
118+
return {
119+
commitSha: commitSha?.slice(0, 9),
120+
exactTag
121+
}
122+
}
123+
124+
export function createSpaVersionDefines(projectRoot, nodeEnv = getNodeEnv()) {
125+
const packageVersion = readPackageVersion(projectRoot)
126+
const gitHeadInfo = readGitHeadInfo(projectRoot)
127+
const shortCommitSha = nodeEnv?.GITHUB_SHA?.slice(0, 9) ?? gitHeadInfo.commitSha
128+
const exactTag =
129+
(nodeEnv?.GITHUB_REF_TYPE === 'tag' ? nodeEnv.GITHUB_REF_NAME : undefined) ??
130+
gitHeadInfo.exactTag
131+
const spaDisplayVersion = resolveSpaVersionDisplay({
132+
packageVersion,
133+
commitSha: shortCommitSha,
134+
exactTag,
135+
refName: nodeEnv?.GITHUB_REF_NAME,
136+
refType: nodeEnv?.GITHUB_REF_TYPE
137+
})
138+
139+
return {
140+
'import.meta.env.VITE_APP_VERSION': JSON.stringify(packageVersion),
141+
'import.meta.env.VITE_COMMIT_SHA_SHORT': JSON.stringify(shortCommitSha),
142+
'import.meta.env.VITE_GIT_EXACT_TAG': JSON.stringify(exactTag),
143+
'import.meta.env.VITE_GITHUB_REF_NAME': JSON.stringify(nodeEnv?.GITHUB_REF_NAME),
144+
'import.meta.env.VITE_GITHUB_REF_TYPE': JSON.stringify(nodeEnv?.GITHUB_REF_TYPE),
145+
'import.meta.env.VITE_SPA_DISPLAY_VERSION': JSON.stringify(spaDisplayVersion)
146+
}
147+
}

dev-env/shib-dev-env/vite.config.ts

Lines changed: 13 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -1,152 +1,30 @@
1-
import { readFileSync } from 'node:fs'
1+
import { existsSync } from 'node:fs'
2+
import { fileURLToPath } from 'node:url'
23
import { defineConfig } from 'vite'
34
import react from '@vitejs/plugin-react'
45
import istanbul from 'vite-plugin-istanbul'
56
import * as path from 'path'
67

7-
const nodeEnv = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process
8-
?.env
8+
const sharedBuildModuleUrl = [
9+
new URL('./build/spaVersionMetadata.mjs', import.meta.url),
10+
new URL('../build/spaVersionMetadata.mjs', import.meta.url),
11+
new URL('../../build/spaVersionMetadata.mjs', import.meta.url)
12+
].find((candidate) => existsSync(fileURLToPath(candidate)))
913

10-
function readTextFile(filePath: string): string | undefined {
11-
try {
12-
return readFileSync(filePath, 'utf8').trim() || undefined
13-
} catch {
14-
return undefined
15-
}
16-
}
17-
18-
function resolveSpaVersionDisplay({
19-
packageVersion,
20-
commitSha,
21-
exactTag,
22-
refName,
23-
refType
24-
}: {
25-
packageVersion?: string
26-
commitSha?: string
27-
exactTag?: string
28-
refName?: string
29-
refType?: string
30-
}): string {
31-
const releaseTag = refType === 'tag' ? refName : exactTag
32-
const normalizedReleaseTag = releaseTag?.replace(/^refs\/tags\//, '').replace(/^v/, '')
33-
34-
if (packageVersion && normalizedReleaseTag === packageVersion) {
35-
return packageVersion
36-
}
37-
38-
if (commitSha) {
39-
return commitSha
40-
}
41-
42-
return packageVersion ?? 'unknown'
43-
}
44-
45-
function resolveProjectRoot(configDir: string): string {
46-
const candidates = [configDir, path.resolve(configDir, '..'), path.resolve(configDir, '../..')]
47-
48-
const projectRoot = candidates.find((candidate) => {
49-
return Boolean(readTextFile(path.join(candidate, 'package.json'))) && Boolean(readTextFile(path.join(candidate, '.git')))
50-
})
51-
52-
return projectRoot ?? configDir
53-
}
54-
55-
function readPackageVersion(projectRoot: string): string | undefined {
56-
try {
57-
const packageJson = JSON.parse(readFileSync(path.join(projectRoot, 'package.json'), 'utf8')) as {
58-
version?: string
59-
}
60-
61-
return packageJson.version
62-
} catch {
63-
return undefined
64-
}
65-
}
66-
67-
function resolveGitDir(projectRoot: string): string | undefined {
68-
const dotGitPath = path.join(projectRoot, '.git')
69-
const dotGitContent = readTextFile(dotGitPath)
70-
71-
if (dotGitContent?.startsWith('gitdir: ')) {
72-
return path.resolve(projectRoot, dotGitContent.slice('gitdir: '.length))
73-
}
74-
75-
return dotGitContent ? undefined : dotGitPath
14+
if (!sharedBuildModuleUrl) {
15+
throw new Error('Could not locate build/spaVersionMetadata.mjs')
7616
}
7717

78-
function readPackedRef(gitDir: string, ref: string): string | undefined {
79-
const packedRefs = readTextFile(path.join(gitDir, 'packed-refs'))
80-
81-
if (!packedRefs) {
82-
return undefined
83-
}
84-
85-
for (const line of packedRefs.split('\n')) {
86-
if (!line || line.startsWith('#') || line.startsWith('^')) {
87-
continue
88-
}
89-
90-
const [sha, packedRef] = line.split(' ')
91-
if (packedRef === ref) {
92-
return sha
93-
}
94-
}
95-
96-
return undefined
97-
}
98-
99-
function readGitHeadInfo(projectRoot: string): { commitSha?: string; exactTag?: string } {
100-
const gitDir = resolveGitDir(projectRoot)
101-
102-
if (!gitDir) {
103-
return {}
104-
}
105-
106-
const head = readTextFile(path.join(gitDir, 'HEAD'))
107-
108-
if (!head) {
109-
return {}
110-
}
111-
112-
if (!head.startsWith('ref: ')) {
113-
return { commitSha: head.slice(0, 9) }
114-
}
115-
116-
const ref = head.slice('ref: '.length)
117-
const commitSha = readTextFile(path.join(gitDir, ref)) ?? readPackedRef(gitDir, ref)
118-
const exactTag = ref.startsWith('refs/tags/') ? ref.replace('refs/tags/', '') : undefined
119-
120-
return {
121-
commitSha: commitSha?.slice(0, 9),
122-
exactTag
123-
}
18+
const { createSpaVersionDefines, resolveProjectRoot } = (await import(sharedBuildModuleUrl.href)) as {
19+
createSpaVersionDefines: (projectRoot: string) => Record<string, string>
20+
resolveProjectRoot: (configDir: string) => string
12421
}
12522

12623
const projectRoot = resolveProjectRoot(__dirname)
127-
const packageVersion = readPackageVersion(projectRoot)
128-
const gitHeadInfo = readGitHeadInfo(projectRoot)
129-
const shortCommitSha = nodeEnv?.GITHUB_SHA?.slice(0, 9) ?? gitHeadInfo.commitSha
130-
const exactTag =
131-
(nodeEnv?.GITHUB_REF_TYPE === 'tag' ? nodeEnv.GITHUB_REF_NAME : undefined) ?? gitHeadInfo.exactTag
132-
const spaDisplayVersion = resolveSpaVersionDisplay({
133-
packageVersion,
134-
commitSha: shortCommitSha,
135-
exactTag,
136-
refName: nodeEnv?.GITHUB_REF_NAME,
137-
refType: nodeEnv?.GITHUB_REF_TYPE
138-
})
13924

14025
export default defineConfig({
14126
root: projectRoot,
142-
define: {
143-
'import.meta.env.VITE_APP_VERSION': JSON.stringify(packageVersion),
144-
'import.meta.env.VITE_COMMIT_SHA_SHORT': JSON.stringify(shortCommitSha),
145-
'import.meta.env.VITE_GIT_EXACT_TAG': JSON.stringify(exactTag),
146-
'import.meta.env.VITE_GITHUB_REF_NAME': JSON.stringify(nodeEnv?.GITHUB_REF_NAME),
147-
'import.meta.env.VITE_GITHUB_REF_TYPE': JSON.stringify(nodeEnv?.GITHUB_REF_TYPE),
148-
'import.meta.env.VITE_SPA_DISPLAY_VERSION': JSON.stringify(spaDisplayVersion)
149-
},
27+
define: createSpaVersionDefines(projectRoot),
15028
plugins: [
15129
react(),
15230
istanbul({

0 commit comments

Comments
 (0)