Skip to content

Commit

Permalink
fix: replace deprecated git version webpack plugin (#874)
Browse files Browse the repository at this point in the history
  • Loading branch information
xoxys authored Sep 1, 2024
1 parent 65a89a0 commit c05dfc7
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 68 deletions.
30 changes: 0 additions & 30 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
},
"devDependencies": {
"@babel/eslint-parser": "7.25.1",
"@eloquent/git-version-webpack-plugin": "5.0.1",
"autoprefixer": "10.4.20",
"copy-webpack-plugin": "12.0.2",
"css-loader": "7.1.2",
Expand Down
13 changes: 6 additions & 7 deletions webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import path from "path"
import { glob } from "glob"
import { fileURLToPath } from 'url';
import { fileURLToPath } from "url"

import { WebpackManifestPlugin } from "webpack-manifest-plugin"
import GitVersionPlugin from "@eloquent/git-version-webpack-plugin"
import FaviconsWebpackPlugin from "favicons-webpack-plugin"
import RemoveEmptyScriptsPlugin from "webpack-remove-empty-scripts"
import CopyPlugin from "copy-webpack-plugin"
import SRIPlugin from "./webpack.plugins.js"
import { SRIPlugin, GitVersionPlugin } from "./webpack.plugins.js"

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const nodeModulesPath = path.resolve(__dirname, "node_modules")

var config = {
Expand Down Expand Up @@ -108,7 +107,7 @@ var config = {
}),

new GitVersionPlugin({
path: "../VERSION"
outputFile: "../VERSION"
})
]
}
Expand All @@ -125,7 +124,7 @@ export default (argv) => {
type: "asset/resource",
generator: {
filename: "fonts/[name][ext]"
},
}
},
{
test: /\.(sa|sc|c)ss$/i,
Expand Down
152 changes: 122 additions & 30 deletions webpack.plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,53 +3,145 @@ import crypto from "crypto"
import path from "path"
import { validate } from "schema-utils"

export default class SRIPlugin {
import { access as accessCps } from "fs"
import { execFile as execFileCps } from "child_process"
import { promisify } from "util"

class SRIPlugin {
static defaultOptions = {
algorithm: "sha512",
sourceFile: "assets.json"
}

constructor(options = {}) {
const schema = {
type: "object",
properties: {
outputFile: {
type: "string"
},
algorithm: {
type: "string"
this.options = { ...SRIPlugin.defaultOptions, ...options }

validate(
{
type: "object",
properties: {
sourceFile: { type: "string" },
outputFile: { type: "string" },
algorithm: { type: "string" }
}
},
options,
{
name: "SRI Plugin",
baseDataPath: "options"
}
}
)
}

this.options = { ...SRIPlugin.defaultOptions, ...options }
apply(compiler) {
compiler.hooks.done.tap("SRIPlugin", () => {
const data = JSON.parse(fs.readFileSync(this.options.sourceFile, "utf8"))
const outputFile = this.options.outputFile || this.options.sourceFile
const { algorithm } = this.options

const calculateSRI = (file) => {
const fileContent = fs.readFileSync(path.join(".", "static", file))
const hash = crypto.createHash(algorithm).update(fileContent).digest("base64")
return `${algorithm}-${hash}`
}

validate(schema, options, {
name: "SRI Plugin",
baseDataPath: "options"
Object.keys(data).forEach((key) => {
data[key].integrity = calculateSRI(data[key].src)
})

fs.writeFileSync(outputFile, JSON.stringify(data, null, 2), { encoding: "utf8", flag: "w" })
})
}
}

class GitVersionPlugin {
static defaultOptions = {
outputFile: "VERSION"
}

constructor(options = {}) {
this.options = { ...GitVersionPlugin.defaultOptions, ...options }

validate(
{
type: "object",
properties: {
outputFile: { type: "string" }
}
},
options,
{
baseDataPath: "options",
name: "GitVersion Plugin"
}
)
}

apply(compiler) {
compiler.hooks.done.tap("SRIPlugin", (manifest) => {
let data = JSON.parse(fs.readFileSync(this.options.sourceFile, "utf8"))
let outputFile = this.options.outputFile ? this.options.outputFile : this.options.sourceFile
const { webpack, hooks, context } = compiler
const { Compilation } = webpack

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

Object.keys(data).forEach((key) => {
let element = data[key]
element.integrity = calculateSRI(element.src)
})
try {
await access(".git")
this.dependsOnGit = true
} catch {
this.dependsOnGit = false
}
})

fs.writeFileSync(outputFile, JSON.stringify(data, null, 2), {
encoding: "utf8",
flag: "w"
})
hooks.compilation.tap("GitVersionPlugin", (compilation) => {
if (this.dependsOnGit) {
compilation.fileDependencies.add(path.join(context, ".git/logs/HEAD"))
compilation.contextDependencies.add(path.join(context, ".git/refs/tags"))
}

compilation.hooks.processAssets.tapPromise(
{
name: "GitVersionPlugin",
stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL
},
async (assets) => {
try {
const v = await this.version()

assets[this.options.outputFile] = {
source: () => `${v}\n`,
size: () => v.length + 1
}
} catch {
assets[this.options.outputFile] = {
source: () => "",
size: () => 0
}
}
}
)
})
}

async version() {
const execFile = promisify(execFileCps)

try {
const { stdout: describe } = await execFile("git", ["describe", "--long", "--tags"])
const [, tag, offset] = describe.trim().match(/^(.*)-(\d+)-g[0-9a-f]+$/)
return parseInt(offset) === 0 ? tag : this.getBranchAndHash()
} catch {
return this.getBranchAndHash()
}
}

async getBranchAndHash() {
const execFile = promisify(execFileCps)
const [{ stdout: branch }, { stdout: hash }] = await Promise.all([
execFile("git", ["rev-parse", "--abbrev-ref", "HEAD"]),
execFile("git", ["rev-parse", "HEAD"])
])
return `${branch.trim()}@${hash.substring(0, 7)}`
}
}

export { SRIPlugin, GitVersionPlugin }

0 comments on commit c05dfc7

Please sign in to comment.