Skip to content

Commit

Permalink
feat(builtin): accept any stamp vars in pkg_npm
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Eagle committed Aug 30, 2020
1 parent 09ec233 commit c6ec8b0
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 33 deletions.
55 changes: 35 additions & 20 deletions internal/pkg_npm/packager.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,29 @@ function unquoteArgs(s) {
return s.replace(/^'(.*)'$/, '$1');
}

/**
* The status files are expected to look like
* BUILD_SCM_HASH 83c699db39cfd74526cdf9bebb75aa6f122908bb
* BUILD_SCM_LOCAL_CHANGES true
* STABLE_BUILD_SCM_VERSION 6.0.0-beta.6+12.sha-83c699d.with-local-changes
* BUILD_TIMESTAMP 1520021990506
*
* @param {string} p the path to the status file
* @returns a two-dimensional array of key/value pairs
*/
function parseStatusFile(p) {
if (!p) return [];
return fs.readFileSync(p, {encoding: 'utf-8'})
.split('\n')
.filter(t => !!t)
.map(t => t.split(' '));
}

function main(args) {
args = fs.readFileSync(args[0], {encoding: 'utf-8'}).split('\n').map(unquoteArgs);
const
[outDir, baseDir, srcsArg, binDir, genDir, depsArg, packagesArg, substitutionsArg,
replaceWithVersion, stampFile, vendorExternalArg] = args;
volatileFile, infoFile, vendorExternalArg] = args;

const substitutions = [
// Strip content between BEGIN-INTERNAL / END-INTERNAL comments
Expand All @@ -74,27 +92,24 @@ function main(args) {
for (const key of Object.keys(rawReplacements)) {
substitutions.push([new RegExp(key, 'g'), rawReplacements[key]])
}
// Replace version last so that earlier substitutions can add
// the version placeholder
if (replaceWithVersion) {
let version = '0.0.0';
if (stampFile) {
// The stamp file is expected to look like
// BUILD_SCM_HASH 83c699db39cfd74526cdf9bebb75aa6f122908bb
// BUILD_SCM_LOCAL_CHANGES true
// BUILD_SCM_VERSION 6.0.0-beta.6+12.sha-83c699d.with-local-changes
// BUILD_TIMESTAMP 1520021990506
//
// We want version to be the 6.0.0-beta... part
const versionTag = fs.readFileSync(stampFile, {encoding: 'utf-8'})
.split('\n')
.find(s => s.startsWith('BUILD_SCM_VERSION'));
// Don't assume BUILD_SCM_VERSION exists
if (versionTag) {
version = versionTag.split(' ')[1].replace(/^v/, '').trim();
// Replace statuses last so that earlier substitutions can add
// status-related placeholders
if (volatileFile || infoFile) {
const statusEntries = parseStatusFile(volatileFile)
statusEntries.push(...parseStatusFile(infoFile))
// Looks like {'BUILD_SCM_VERSION': 'v1.2.3'}
const statuses = new Map(statusEntries)
for (let idx = 0; idx < substitutions.length; idx++) {
const match = substitutions[idx][1].match(/\{(.*)\}/);
if (!match) continue;
const statusKey = match[1];
if (statuses.has(statusKey)) {
// FIXME: need to strip leading "v" like we did in
// https://github.com/bazelbuild/rules_nodejs/pull/1591
// (needs a test added)
substitutions[idx][1] = statuses.get(statusKey);
}
}
substitutions.push([new RegExp(replaceWithVersion, 'g'), version]);
}

// src like baseDir/my/path is just copied to outDir/my/path
Expand Down
48 changes: 35 additions & 13 deletions internal/pkg_npm/pkg_npm.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,26 @@ PKG_NPM_ATTRS = {
doc = """Optional package_name that this npm package may be imported as.""",
),
"replace_with_version": attr.string(
doc = """If set this value is replaced with the version stamp data.
See the section on stamping in the README.""",
doc = """DEPRECATED: use substitutions instead.
`replace_with_version = "my_version_placeholder"` is just syntax sugar for
`substitutions = {"my_version_placeholder": "{BUILD_SCM_VERSION}"}`.
Follow this deprecation at https://github.com/bazelbuild/rules_nodejs/issues/1694
""",
default = "0.0.0-PLACEHOLDER",
),
"srcs": attr.label_list(
doc = """Files inside this directory which are simply copied into the package.""",
allow_files = True,
),
"substitutions": attr.string_dict(
doc = """Key-value pairs which are replaced in all the files while building the package.""",
doc = """Key-value pairs which are replaced in all the files while building the package.
You can use values from the workspace status command using curly braces, for example
`{"0.0.0-PLACEHOLDER": "{STABLE_GIT_VERSION}"}`.
See the section on stamping in the README
""",
),
"vendor_external": attr.string_list(
doc = """External workspaces whose contents should be vendored into this workspace.
Expand Down Expand Up @@ -184,7 +194,15 @@ def create_package(ctx, deps_files, nested_packages):
# current package unless explicitely specified.
filtered_deps_sources = _filter_out_external_files(ctx, deps_files, package_path)

# Back-compat for the replace_with_version stamping
# see https://github.com/bazelbuild/rules_nodejs/issues/1694 for removal
substitutions = dict(**ctx.attr.substitutions)
if stamp and ctx.attr.replace_with_version:
substitutions[ctx.attr.replace_with_version] = "{BUILD_SCM_VERSION}"

args = ctx.actions.args()
inputs = ctx.files.srcs + deps_files + nested_packages

args.use_param_file("%s", use_always = True)
args.add(package_dir.path)
args.add(package_path)
Expand All @@ -193,19 +211,23 @@ def create_package(ctx, deps_files, nested_packages):
args.add(ctx.genfiles_dir.path)
args.add_joined(filtered_deps_sources, join_with = ",", omit_if_empty = False)
args.add_joined([p.path for p in nested_packages], join_with = ",", omit_if_empty = False)
args.add(ctx.attr.substitutions)
args.add(ctx.attr.replace_with_version)
args.add(ctx.version_file.path if stamp else "")
args.add_joined(ctx.attr.vendor_external, join_with = ",", omit_if_empty = False)
args.add(substitutions)

inputs = ctx.files.srcs + deps_files + nested_packages

# The version_file is an undocumented attribute of the ctx that lets us read the volatile-status.txt file
# produced by the --workspace_status_command. That command will be executed whenever
# this action runs, so we get the latest version info on each execution.
# See https://github.com/bazelbuild/bazel/issues/1054
if stamp:
# The version_file is an undocumented attribute of the ctx that lets us read the volatile-status.txt file
# produced by the --workspace_status_command.
# Similarly info_file reads the stable-status.txt file.
# That command will be executed whenever
# this action runs, so we get the latest version info on each execution.
# See https://github.com/bazelbuild/bazel/issues/1054
args.add(ctx.version_file.path)
inputs.append(ctx.version_file)
args.add(ctx.info_file.path)
inputs.append(ctx.info_file)
else:
args.add_all(["", ""])

args.add_joined(ctx.attr.vendor_external, join_with = ",", omit_if_empty = False)

ctx.actions.run(
progress_message = "Assembling npm package %s" % package_dir.short_path,
Expand Down

0 comments on commit c6ec8b0

Please sign in to comment.