Skip to content

Commit 9009323

Browse files
committed
add a frontend version tag to Footer.tsx
1 parent 5cacbf6 commit 9009323

12 files changed

Lines changed: 518 additions & 23 deletions

File tree

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

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

6137
export default defineConfig({
138+
root: projectRoot,
139+
define: {
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(process.env.GITHUB_REF_NAME),
144+
'import.meta.env.VITE_GITHUB_REF_TYPE': JSON.stringify(process.env.GITHUB_REF_TYPE),
145+
'import.meta.env.VITE_SPA_DISPLAY_VERSION': JSON.stringify(spaDisplayVersion)
146+
},
7147
plugins: [
8148
react(),
9149
istanbul({
@@ -24,8 +164,8 @@ export default defineConfig({
24164
},
25165
resolve: {
26166
alias: {
27-
'@': path.resolve(__dirname, 'src'),
28-
'@tests': path.resolve(__dirname, 'tests')
167+
'@': path.resolve(projectRoot, 'src'),
168+
'@tests': path.resolve(projectRoot, 'tests')
29169
}
30170
}
31171
})

dev-env/vite.config.ts

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

6137
export default defineConfig({
138+
root: projectRoot,
7139
base: '/modern',
140+
define: {
141+
'import.meta.env.VITE_APP_VERSION': JSON.stringify(packageVersion),
142+
'import.meta.env.VITE_COMMIT_SHA_SHORT': JSON.stringify(shortCommitSha),
143+
'import.meta.env.VITE_GIT_EXACT_TAG': JSON.stringify(exactTag),
144+
'import.meta.env.VITE_GITHUB_REF_NAME': JSON.stringify(process.env.GITHUB_REF_NAME),
145+
'import.meta.env.VITE_GITHUB_REF_TYPE': JSON.stringify(process.env.GITHUB_REF_TYPE),
146+
'import.meta.env.VITE_SPA_DISPLAY_VERSION': JSON.stringify(spaDisplayVersion)
147+
},
8148
plugins: [
9149
react(),
10150
istanbul({
@@ -26,8 +166,8 @@ export default defineConfig({
26166
},
27167
resolve: {
28168
alias: {
29-
'@': path.resolve(__dirname, 'src'),
30-
'@tests': path.resolve(__dirname, 'tests')
169+
'@': path.resolve(projectRoot, 'src'),
170+
'@tests': path.resolve(projectRoot, 'tests')
31171
}
32172
}
33173
})

public/locales/en/footer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"copyright": "Copyright © {{year}}, {{copyrightHolder}}",
33
"privacyPolicy": "Privacy Policy",
4-
"poweredBy": "Powered by"
4+
"poweredBy": "Powered by",
5+
"spaVersion": "frontend version: {{version}}"
56
}

public/locales/es/footer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"copyright": "Copyright © {{year}}, {{copyrightHolder}}",
33
"privacyPolicy": "Política de privacidad",
4-
"poweredBy": "Desarrollado por"
4+
"poweredBy": "Desarrollado por",
5+
"spaVersion": "frontend version: {{version}}"
56
}

src/sections/layout/footer/Footer.module.scss

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,30 @@
2424
.powered-by-container {
2525
font-size: $dv-font-size-sm;
2626
text-align: right;
27+
display: flex;
28+
flex-direction: column;
29+
align-items: flex-end;
30+
gap: 0.25rem;
31+
}
32+
33+
.branding-row,
34+
.versions-row {
35+
display: flex;
36+
justify-content: flex-end;
37+
align-items: center;
38+
flex-wrap: wrap;
2739
}
2840

2941
.powered-by-text {
3042
margin-right: 0.6em;
3143
}
3244

3345
.version {
34-
margin-right: 0.3em;
3546
white-space: nowrap;
3647
text-align: right;
3748
vertical-align: bottom;
3849
}
50+
51+
.separator {
52+
margin: 0 0.3em;
53+
}

0 commit comments

Comments
 (0)