Skip to content
This repository was archived by the owner on Jan 25, 2023. It is now read-only.

Commit a21ba04

Browse files
JGAntunesehmicky
andauthored
feat: better cache support for JS workspaces (#526)
* feat: initial work to add support for js workspaces * fix(ws-cache): addressing some typos and moving the caching call before the regular node_modules cache * fix(ws-cache): using a tmp dir for workspace locations file & better handling of node_modules cache move out * fix(ws-cache): correctly handle dirs with spaces * fix(ws-cache): use a variable instead of tmp dir to keep ws locations * fix(ws-cache): no need for intermediate variables for ws locations * chore(ws-cache): move cache_dir to the upper scope * chore(ws-cache): don't call yarn workspaces twice * fix(ws-cache): ended up messing the jq command 🤦 * chore: typo in comment run-build-functions.sh Co-authored-by: ehmicky <ehmicky@users.noreply.github.com> Co-authored-by: ehmicky <ehmicky@users.noreply.github.com>
1 parent d84c794 commit a21ba04

File tree

1 file changed

+99
-6
lines changed

1 file changed

+99
-6
lines changed

run-build-functions.sh

Lines changed: 99 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ mkdir -p $NETLIFY_CACHE_DIR/ruby_version
3939
mkdir -p $NETLIFY_CACHE_DIR/swift_version
4040

4141
# pwd caches
42+
NETLIFY_JS_WORKSPACES_CACHE_DIR="$NETLIFY_CACHE_DIR/js-workspaces"
43+
44+
mkdir -p $NETLIFY_JS_WORKSPACES_CACHE_DIR
4245
mkdir -p $NETLIFY_CACHE_DIR/node_modules
4346
mkdir -p $NETLIFY_CACHE_DIR/.bundle
4447
mkdir -p $NETLIFY_CACHE_DIR/bower_components
@@ -102,6 +105,38 @@ run_yarn() {
102105
fi
103106

104107

108+
if [ "$NETLIFY_YARN_WORKSPACES" = "true" ]
109+
then
110+
echo "NETLIFY_YARN_WORKSPACES feature flag set"
111+
local workspace_output
112+
local workspace_exit_code
113+
# YARN_IGNORE_PATH will ignore the presence of a local yarn executable (i.e. yarn 2) and default
114+
# to using the global one (which, for now, is always yarn 1.x). See https://yarnpkg.com/configuration/yarnrc#ignorePath
115+
workspace_output="$(YARN_IGNORE_PATH=1 yarn workspaces --json info )"
116+
workspace_exit_code=$?
117+
if [ $workspace_exit_code -eq 0 ]
118+
then
119+
local package_locations
120+
# Extract all the packages and respective locations. .data will be a JSON object like
121+
# {
122+
# "my-package-1": {
123+
# "location": "packages/blog-1",
124+
# "workspaceDependencies": [],
125+
# "mismatchedWorkspaceDependencies": []
126+
# },
127+
# (...)
128+
# }
129+
# We need to cache all the node_module dirs, or we'll always be installing them on each run
130+
mapfile -t package_locations <<< "$(echo "$workspace_output" | jq -r '.data | fromjson | to_entries | .[].value.location')"
131+
restore_js_workspaces_cache "${package_locations[@]}"
132+
else
133+
echo "No workspace detected"
134+
restore_cwd_cache node_modules "node modules"
135+
fi
136+
else
137+
restore_cwd_cache node_modules "node modules"
138+
fi
139+
105140
echo "Installing NPM modules using Yarn version $(yarn --version)"
106141
run_npm_set_temp
107142

@@ -130,6 +165,8 @@ run_npm_set_temp() {
130165
}
131166

132167
run_npm() {
168+
restore_cwd_cache node_modules "node modules"
169+
133170
if [ -n "$NPM_VERSION" ]
134171
then
135172
if [ "$(npm --version)" != "$NPM_VERSION" ]
@@ -475,7 +512,6 @@ install_dependencies() {
475512

476513
if [ -f package.json ]
477514
then
478-
restore_cwd_cache node_modules "node modules"
479515
if [ "$NETLIFY_USE_YARN" = "true" ] || ([ "$NETLIFY_USE_YARN" != "false" ] && [ -f yarn.lock ])
480516
then
481517
run_yarn $YARN_VERSION
@@ -669,9 +705,17 @@ install_dependencies() {
669705
#
670706
cache_artifacts() {
671707
echo "Caching artifacts"
708+
672709
cache_cwd_directory ".bundle" "ruby gems"
673710
cache_cwd_directory "bower_components" "bower components"
674-
cache_cwd_directory "node_modules" "node modules"
711+
712+
if [ "$NETLIFY_YARN_WORKSPACES" == "true" ]
713+
then
714+
cache_node_modules
715+
else
716+
cache_cwd_directory "node_modules" "node modules"
717+
fi
718+
675719
cache_cwd_directory ".venv" "python virtualenv"
676720
cache_cwd_directory ".build" "swift build"
677721
cache_cwd_directory ".netlify/plugins" "build plugins"
@@ -690,7 +734,7 @@ cache_artifacts() {
690734
cache_home_directory ".composer" "composer dependencies"
691735
cache_home_directory ".homebrew-cache", "homebrew cache"
692736
cache_home_directory ".rustup" "rust rustup cache"
693-
737+
694738
if [ -f Cargo.toml ] || [ -f Cargo.lock ]
695739
then
696740
cache_home_directory ".cargo/registry" "rust cargo registry cache"
@@ -747,11 +791,11 @@ cache_artifacts() {
747791
move_cache() {
748792
local src=$1
749793
local dst=$2
750-
if [ -d $src ]
794+
if [ -d "$src" ]
751795
then
752796
echo "Started $3"
753-
rm -rf $dst
754-
mv $src $dst
797+
rm -rf "$dst"
798+
mv "$src" "$dst"
755799
echo "Finished $3"
756800
fi
757801
}
@@ -779,6 +823,55 @@ restore_cwd_cache() {
779823
move_cache "$NETLIFY_CACHE_DIR/$1" "$PWD/$1" "restoring cached $2"
780824
}
781825

826+
#
827+
# Restores node_modules dirs cached for js workspaces
828+
# See https://github.com/netlify/pod-workflow/issues/139/ for more context
829+
#
830+
# Expects:
831+
# $@ each argument should be a package location relative to the repo's root
832+
restore_js_workspaces_cache() {
833+
# Keep a record of the workspaces in the project in order to cache them later
834+
NETLIFY_JS_WORKSPACE_LOCATIONS=("$@")
835+
836+
# Retrieve each workspace node_modules
837+
for location in "${NETLIFY_JS_WORKSPACE_LOCATIONS[@]}"; do
838+
move_cache "$NETLIFY_JS_WORKSPACES_CACHE_DIR/$location/node_modules" \
839+
"$NETLIFY_REPO_DIR/$location/node_modules" \
840+
"restoring workspace $location node modules"
841+
done
842+
# Retrieve hoisted node_modules
843+
move_cache "$NETLIFY_JS_WORKSPACES_CACHE_DIR/node_modules" "$NETLIFY_REPO_DIR/node_modules" "restoring workspace root node modules"
844+
}
845+
846+
#
847+
# Caches node_modules dirs for a js project. Either detects the presence of js workspaces
848+
# via the `NETLIFY_JS_WORKSPACE_LOCATIONS` variable, or looks at the node_modules in the cwd.
849+
#
850+
cache_node_modules() {
851+
# Check the number of workspace locations detected
852+
if [ "${#NETLIFY_JS_WORKSPACE_LOCATIONS[@]}" -eq 0 ]
853+
then
854+
cache_cwd_directory "node_modules" "node modules"
855+
else
856+
cache_js_workspaces
857+
fi
858+
}
859+
860+
#
861+
# Caches node_modules dirs from js workspaces. It acts based on the presence of a
862+
# `NETLIFY_JS_WORKSPACE_LOCATIONS` variable previously set in `restore_js_workspaces_cache()`
863+
#
864+
cache_js_workspaces() {
865+
for location in "${NETLIFY_JS_WORKSPACE_LOCATIONS[@]}"; do
866+
mkdir -p "$NETLIFY_JS_WORKSPACES_CACHE_DIR/$location"
867+
move_cache "$NETLIFY_REPO_DIR/$location/node_modules" \
868+
"$NETLIFY_JS_WORKSPACES_CACHE_DIR/$location/node_modules" \
869+
"saving workspace $location node modules"
870+
done
871+
# Retrieve hoisted node_modules
872+
move_cache "$NETLIFY_REPO_DIR/node_modules" "$NETLIFY_JS_WORKSPACES_CACHE_DIR/node_modules" "saving workspace root node modules"
873+
}
874+
782875
cache_cwd_directory() {
783876
move_cache "$PWD/$1" "$NETLIFY_CACHE_DIR/$1" "saving $2"
784877
}

0 commit comments

Comments
 (0)