Skip to content

Commit c05dfc7

Browse files
authored
fix: replace deprecated git version webpack plugin (#874)
1 parent 65a89a0 commit c05dfc7

File tree

4 files changed

+128
-68
lines changed

4 files changed

+128
-68
lines changed

package-lock.json

-30
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
},
4646
"devDependencies": {
4747
"@babel/eslint-parser": "7.25.1",
48-
"@eloquent/git-version-webpack-plugin": "5.0.1",
4948
"autoprefixer": "10.4.20",
5049
"copy-webpack-plugin": "12.0.2",
5150
"css-loader": "7.1.2",

webpack.config.js

+6-7
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
import path from "path"
22
import { glob } from "glob"
3-
import { fileURLToPath } from 'url';
3+
import { fileURLToPath } from "url"
44

55
import { WebpackManifestPlugin } from "webpack-manifest-plugin"
6-
import GitVersionPlugin from "@eloquent/git-version-webpack-plugin"
76
import FaviconsWebpackPlugin from "favicons-webpack-plugin"
87
import RemoveEmptyScriptsPlugin from "webpack-remove-empty-scripts"
98
import CopyPlugin from "copy-webpack-plugin"
10-
import SRIPlugin from "./webpack.plugins.js"
9+
import { SRIPlugin, GitVersionPlugin } from "./webpack.plugins.js"
1110

12-
const __filename = fileURLToPath(import.meta.url);
13-
const __dirname = path.dirname(__filename);
11+
const __filename = fileURLToPath(import.meta.url)
12+
const __dirname = path.dirname(__filename)
1413
const nodeModulesPath = path.resolve(__dirname, "node_modules")
1514

1615
var config = {
@@ -108,7 +107,7 @@ var config = {
108107
}),
109108

110109
new GitVersionPlugin({
111-
path: "../VERSION"
110+
outputFile: "../VERSION"
112111
})
113112
]
114113
}
@@ -125,7 +124,7 @@ export default (argv) => {
125124
type: "asset/resource",
126125
generator: {
127126
filename: "fonts/[name][ext]"
128-
},
127+
}
129128
},
130129
{
131130
test: /\.(sa|sc|c)ss$/i,

webpack.plugins.js

+122-30
Original file line numberDiff line numberDiff line change
@@ -3,53 +3,145 @@ import crypto from "crypto"
33
import path from "path"
44
import { validate } from "schema-utils"
55

6-
export default class SRIPlugin {
6+
import { access as accessCps } from "fs"
7+
import { execFile as execFileCps } from "child_process"
8+
import { promisify } from "util"
9+
10+
class SRIPlugin {
711
static defaultOptions = {
812
algorithm: "sha512",
913
sourceFile: "assets.json"
1014
}
1115

1216
constructor(options = {}) {
13-
const schema = {
14-
type: "object",
15-
properties: {
16-
outputFile: {
17-
type: "string"
18-
},
19-
algorithm: {
20-
type: "string"
17+
this.options = { ...SRIPlugin.defaultOptions, ...options }
18+
19+
validate(
20+
{
21+
type: "object",
22+
properties: {
23+
sourceFile: { type: "string" },
24+
outputFile: { type: "string" },
25+
algorithm: { type: "string" }
2126
}
27+
},
28+
options,
29+
{
30+
name: "SRI Plugin",
31+
baseDataPath: "options"
2232
}
23-
}
33+
)
34+
}
2435

25-
this.options = { ...SRIPlugin.defaultOptions, ...options }
36+
apply(compiler) {
37+
compiler.hooks.done.tap("SRIPlugin", () => {
38+
const data = JSON.parse(fs.readFileSync(this.options.sourceFile, "utf8"))
39+
const outputFile = this.options.outputFile || this.options.sourceFile
40+
const { algorithm } = this.options
41+
42+
const calculateSRI = (file) => {
43+
const fileContent = fs.readFileSync(path.join(".", "static", file))
44+
const hash = crypto.createHash(algorithm).update(fileContent).digest("base64")
45+
return `${algorithm}-${hash}`
46+
}
2647

27-
validate(schema, options, {
28-
name: "SRI Plugin",
29-
baseDataPath: "options"
48+
Object.keys(data).forEach((key) => {
49+
data[key].integrity = calculateSRI(data[key].src)
50+
})
51+
52+
fs.writeFileSync(outputFile, JSON.stringify(data, null, 2), { encoding: "utf8", flag: "w" })
3053
})
3154
}
55+
}
56+
57+
class GitVersionPlugin {
58+
static defaultOptions = {
59+
outputFile: "VERSION"
60+
}
61+
62+
constructor(options = {}) {
63+
this.options = { ...GitVersionPlugin.defaultOptions, ...options }
64+
65+
validate(
66+
{
67+
type: "object",
68+
properties: {
69+
outputFile: { type: "string" }
70+
}
71+
},
72+
options,
73+
{
74+
baseDataPath: "options",
75+
name: "GitVersion Plugin"
76+
}
77+
)
78+
}
3279

3380
apply(compiler) {
34-
compiler.hooks.done.tap("SRIPlugin", (manifest) => {
35-
let data = JSON.parse(fs.readFileSync(this.options.sourceFile, "utf8"))
36-
let outputFile = this.options.outputFile ? this.options.outputFile : this.options.sourceFile
81+
const { webpack, hooks, context } = compiler
82+
const { Compilation } = webpack
3783

38-
const checksum = (str, algorithm = this.options.algorithm, encoding = "base64") =>
39-
crypto.createHash(algorithm).update(str, "utf8").digest(encoding)
40-
const fileSum = (file, algorithm) => checksum(fs.readFileSync(file), algorithm)
41-
const calculateSRI = (file, algorithm = this.options.algorithm) =>
42-
`${algorithm}-${fileSum(path.join(".", "static", file), algorithm)}`
84+
hooks.beforeCompile.tapPromise("GitVersionPlugin", async () => {
85+
const access = promisify(accessCps)
4386

44-
Object.keys(data).forEach((key) => {
45-
let element = data[key]
46-
element.integrity = calculateSRI(element.src)
47-
})
87+
try {
88+
await access(".git")
89+
this.dependsOnGit = true
90+
} catch {
91+
this.dependsOnGit = false
92+
}
93+
})
4894

49-
fs.writeFileSync(outputFile, JSON.stringify(data, null, 2), {
50-
encoding: "utf8",
51-
flag: "w"
52-
})
95+
hooks.compilation.tap("GitVersionPlugin", (compilation) => {
96+
if (this.dependsOnGit) {
97+
compilation.fileDependencies.add(path.join(context, ".git/logs/HEAD"))
98+
compilation.contextDependencies.add(path.join(context, ".git/refs/tags"))
99+
}
100+
101+
compilation.hooks.processAssets.tapPromise(
102+
{
103+
name: "GitVersionPlugin",
104+
stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL
105+
},
106+
async (assets) => {
107+
try {
108+
const v = await this.version()
109+
110+
assets[this.options.outputFile] = {
111+
source: () => `${v}\n`,
112+
size: () => v.length + 1
113+
}
114+
} catch {
115+
assets[this.options.outputFile] = {
116+
source: () => "",
117+
size: () => 0
118+
}
119+
}
120+
}
121+
)
53122
})
54123
}
124+
125+
async version() {
126+
const execFile = promisify(execFileCps)
127+
128+
try {
129+
const { stdout: describe } = await execFile("git", ["describe", "--long", "--tags"])
130+
const [, tag, offset] = describe.trim().match(/^(.*)-(\d+)-g[0-9a-f]+$/)
131+
return parseInt(offset) === 0 ? tag : this.getBranchAndHash()
132+
} catch {
133+
return this.getBranchAndHash()
134+
}
135+
}
136+
137+
async getBranchAndHash() {
138+
const execFile = promisify(execFileCps)
139+
const [{ stdout: branch }, { stdout: hash }] = await Promise.all([
140+
execFile("git", ["rev-parse", "--abbrev-ref", "HEAD"]),
141+
execFile("git", ["rev-parse", "HEAD"])
142+
])
143+
return `${branch.trim()}@${hash.substring(0, 7)}`
144+
}
55145
}
146+
147+
export { SRIPlugin, GitVersionPlugin }

0 commit comments

Comments
 (0)