Skip to content

Commit 0d96437

Browse files
committed
chore: workaround npm/cli#3466 when bundling internal deps
Works around npm/cli#3466 when bundling internal dependencies using the bundleDependencies package.json property. This change works in tandem with the npm pack/publish process -- when we run `developer/src/kmc/build.sh publish` (or `pack`), we end up with `npm version` stomping on all our package.json files, so the repo is dirty after this. We need a copy of the top-level package.json before this stomping happens, in order to get a simple map of the location of each of our internal dependencies, from the `dependencies` property (it would be possible to figure this out with a lot more parsing of our package.json files, but this is simpler). This means, in future, we should avoid publishing our internal dependencies such as those under common/ to npm, as they serve no practical purpose there.
1 parent 508588e commit 0d96437

File tree

2 files changed

+72
-1
lines changed

2 files changed

+72
-1
lines changed

developer/src/kmc/build.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,10 @@ fi
133133
if builder_start_action publish; then
134134
. "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh"
135135

136+
# To ensure that we cache the top-level package.json, we must call this before
137+
# the global publish
138+
builder_publish_cleanup
139+
136140
# For now, kmc will have responsibility for publishing keyman-version and
137141
# common-types, as well as all the other dependent modules. In the future, we
138142
# should probably have a top-level npm publish script that publishes all
@@ -143,14 +147,20 @@ if builder_start_action publish; then
143147

144148
# Finally, publish kmc
145149
builder_publish_to_npm
150+
builder_publish_cleanup
146151
builder_finish_action success publish
147152
elif builder_start_action pack; then
148153
. "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh"
149154

155+
# To ensure that we cache the top-level package.json, we must call this before
156+
# the global pack
157+
builder_publish_cleanup
158+
150159
for package in "${PACKAGES[@]}"; do
151160
"$KEYMAN_ROOT/$package/build.sh" pack $DRY_RUN
152161
done
153162

154163
builder_publish_to_pack
164+
builder_publish_cleanup
155165
builder_finish_action success pack
156166
fi

resources/build/build-utils-ci.inc.sh

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,9 @@ function _builder_publish_npm_package() {
100100
dry_run=--dry-run
101101
fi
102102

103+
_builder_publish_cache_package_json
103104
_builder_write_npm_version
105+
_builder_prepublish
104106

105107
# Note: In either case, npm publish MUST be given --access public to publish a
106108
# package in the @keymanapp scope on the public npm package index.
@@ -141,9 +143,68 @@ function _builder_write_npm_version() {
141143
. +
142144
(try { dependencies: (.dependencies | to_entries | . + map(select(.key | match("@keymanapp/.*")) .value |= $VERSION_WITH_TAG) | from_entries) } catch {}) +
143145
(try { devDependencies: (.devDependencies | to_entries | . + map(select(.key | match("@keymanapp/.*")) .value |= $VERSION_WITH_TAG) | from_entries) } catch {}) +
144-
(try { bundleDependencies: (.bundleDependencies | to_entries | . + map(select(.key | match("@keymanapp/.*")) .value |= $VERSION_WITH_TAG) | from_entries) } catch {}) +
145146
(try { optionalDependencies: (.optionalDependencies | to_entries | . + map(select(.key | match("@keymanapp/.*")) .value |= $VERSION_WITH_TAG) | from_entries) } catch {})
146147
' > "${line}_"
147148
mv -f "${line}_" "$line"
148149
done
150+
}
151+
152+
#
153+
# Due to https://github.com/npm/cli/issues/3466, we manually create all
154+
# bundleDependencies (__NOT__ bundledDependencies, beware typos) from
155+
# the target's package.json in its node_modules folder. Must run from
156+
# the target's folder.
157+
#
158+
function _builder_prepublish() {
159+
mkdir -p node_modules/@keymanapp
160+
local packages=($(cat package.json | "$JQ" --raw-output '.bundleDependencies | join(" ")'))
161+
local package
162+
163+
# For each @keymanapp/ package, we'll do a local symlink, note that Windows
164+
# mklink is internal to cmd!
165+
for package in "${packages[@]}"; do
166+
if [[ $package =~ ^@keymanapp/ ]]; then
167+
# Creating local symlink under node_modules
168+
local link_source=node_modules/$package
169+
170+
# lookup the link_target from top-level package.json/dependencies
171+
local link_target="$(cat "$KEYMAN_ROOT/builder_package_publish.json" | jq -r .dependencies.\"$package\")"
172+
173+
if [[ $link_target =~ ^file: ]]; then
174+
link_target="$KEYMAN_ROOT"/${link_target#file:}
175+
176+
builder_echo "Manually linking $link_source -> $link_target (see https://github.com/npm/cli/issues/3466)"
177+
rm -rf $link_source
178+
if [[ $BUILDER_OS == win ]]; then
179+
link_source="$(cygpath -w "$link_source")"
180+
link_target="$(cygpath -w "$link_target")"
181+
cmd //c mklink //j "$link_source" "$link_target"
182+
else
183+
ln -sr "$link_target" "$link_source"
184+
fi
185+
fi
186+
fi
187+
done
188+
}
189+
190+
#
191+
# We need to cache /package.json before npm version gets its sticky fingers on
192+
# it, because afterwards, we lose the file: paths that help us to resolve
193+
# dependencies easily. Part of the https://github.com/npm/cli/issues/3466
194+
# workaround.
195+
#
196+
function _builder_publish_cache_package_json() {
197+
if [[ -f "$KEYMAN_ROOT/builder_package_publish.json" ]]; then
198+
return 0
199+
fi
200+
201+
if "$JQ" -e '.version' "$KEYMAN_ROOT/developer/src/kmc/package.json" > /dev/null; then
202+
builder_die "npm version has already been run. Revert the version changes to all package.json files before re-running"
203+
fi
204+
205+
cp "$KEYMAN_ROOT/package.json" "$KEYMAN_ROOT/builder_package_publish.json"
206+
}
207+
208+
function builder_publish_cleanup() {
209+
rm -f "$KEYMAN_ROOT/builder_package_publish.json"
149210
}

0 commit comments

Comments
 (0)