Skip to content

Commit b8d268d

Browse files
authored
[ci] Download fnm directly from GitHub releases and validate checksum (#94579)
I determined that [`nvm` wasn't sufficient for our use-case since we need to support windows](#94175 (comment)), so this doubles down on `fnm`. This reduces risks of supply chain attacks with `fnm`. This also cleans up some old stuff that was left over from self-hosted runners and/or that was there for debugging, if it isn't useful anymore.
1 parent 3caee03 commit b8d268d

1 file changed

Lines changed: 58 additions & 59 deletions

File tree

.github/workflows/build_reusable.yml

Lines changed: 58 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -172,73 +172,65 @@ jobs:
172172
git config --global core.eol lf
173173
shell: bash
174174

175-
- name: Check if fnm is installed
176-
id: check-fnm
177-
run: |
178-
if [ -x "$(command -v fnm)" ]; then
179-
echo "fnm found."
180-
echo "found=true" >> $GITHUB_OUTPUT
181-
else
182-
echo "fnm not found."
183-
echo "found=false" >> $GITHUB_OUTPUT
184-
fi
175+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
176+
with:
177+
fetch-depth: 25
178+
persist-credentials: false
185179

186180
- name: Install fnm
187-
if: steps.check-fnm.outputs.found != 'true'
188181
run: |
189-
export FNM_DIR="${HOME}/.local/share/fnm"
190-
curl -fsSL https://fnm.vercel.app/install | bash
191-
export PATH="$FNM_DIR:$PATH"
192-
echo "$FNM_DIR" >> $GITHUB_PATH
193-
fnm env --json | jq -r 'to_entries|map("\(.key)=\(.value|tostring)")|.[]' | xargs -I {} echo "{}" >> $GITHUB_ENV
194-
195-
- name: Normalize input step names into path key
196-
uses: actions/github-script@d746ffe35508b1917358783b479e04febd2b8f71 # v9.0.0
197-
id: var
198-
with:
199-
script: |
200-
core.setOutput('input_step_key', '${{ inputs.stepName }}'.toLowerCase().replaceAll(/[/.]/g, '-').trim('-'));
201-
202-
- name: Use Node.js ${{ inputs.nodeVersion || env.NODE_LTS_VERSION }} for default shell
182+
FNM_VERSION=v1.39.0
183+
FNM_BIN_DIR="$HOME/.local/share/fnm/bin"
184+
185+
case "$RUNNER_OS" in
186+
Linux)
187+
# The asset names and sha256 are available on the GH releases page
188+
# https://github.com/Schniz/fnm/releases
189+
FNM_ASSET=fnm-linux.zip
190+
FNM_SHA256=7807664f39d39fc518da1c35ba0181e4b3267603c4b1dedeb4b5fc6ae440a224
191+
FNM_EXE=fnm
192+
;;
193+
Windows)
194+
FNM_ASSET=fnm-windows.zip
195+
FNM_SHA256=8183bed4348cb78fdfd8abb3d1247fbeab7b2082f941363929c61e747c001e10
196+
FNM_EXE=fnm.exe
197+
;;
198+
*)
199+
echo "::error::Unsupported RUNNER_OS: $RUNNER_OS"
200+
exit 1
201+
;;
202+
esac
203+
FNM_BIN="$FNM_BIN_DIR/$FNM_EXE"
204+
205+
mkdir -p "$FNM_BIN_DIR"
206+
curl -L --fail --retry 3 -o /tmp/fnm.zip \
207+
"https://github.com/Schniz/fnm/releases/download/$FNM_VERSION/$FNM_ASSET"
208+
echo "$FNM_SHA256 /tmp/fnm.zip" | sha256sum --check --status
209+
unzip /tmp/fnm.zip "$FNM_EXE" -d "$FNM_BIN_DIR"
210+
rm /tmp/fnm.zip
211+
chmod +x "$FNM_BIN"
212+
213+
echo "$FNM_BIN_DIR" >> $GITHUB_PATH
214+
"$FNM_BIN" env --corepack-enabled --json | \
215+
jq -r 'to_entries|map("\(.key)=\(.value|tostring|@sh)")|.[]' | \
216+
xargs -I {} echo "{}" >> $GITHUB_ENV
217+
218+
- name: Use Node.js ${{ inputs.nodeVersion || env.NODE_LTS_VERSION }}
203219
run: |
204-
node --version || true
205-
which node || true
206-
# TODO: May be sufficient to just set `$FNM_MULTISHELL_PATH/bin` from `fnm env --json` into GITHUB_PATH
207-
fnm_env=$(fnm env)
208-
# Debug what we're about to eval
209-
echo "$fnm_env"
210-
eval "$fnm_env"
211-
fnm use --install-if-missing ${{ inputs.nodeVersion || env.NODE_LTS_VERSION }}
212-
fnm default ${{ inputs.nodeVersion || env.NODE_LTS_VERSION }}
213-
node --version
214-
which node
215-
NODE_SHELL_PATH=$(dirname "$(which node)")
216-
echo "Adding '$NODE_SHELL_PATH' to GITHUB_PATH"
217-
echo "$NODE_SHELL_PATH" >> "$GITHUB_PATH"
218-
# Debug used Node.js version in a separate step to ensure
219-
# the Node.js version is set for the entire job
220+
fnm use --install-if-missing "$NODE_VERSION"
221+
fnm default "$NODE_VERSION"
222+
eval "$(fnm env)"
223+
echo "$(dirname "$(which node)")" >> "$GITHUB_PATH"
224+
env:
225+
NODE_VERSION: ${{ inputs.nodeVersion || env.NODE_LTS_VERSION }}
226+
227+
# Debug used Node.js version in a separate step to ensure the Node.js
228+
# version is set for the entire job
220229
- name: Verify Node.js version
221230
run: |
222231
which node
223232
node --version
224-
- name: Prepare corepack
225-
if: ${{ runner.os == 'Linux' }}
226-
run: |
227-
npm i -g corepack@0.31
228-
- run: corepack enable
229-
- run: pwd
230-
231-
- name: Kill stale sccache processes
232-
if: ${{ runner.os == 'Windows' }}
233-
shell: powershell
234-
run: Get-Process sccache -ErrorAction SilentlyContinue | Stop-Process -Force
235-
236-
- run: rm -rf .git
237-
238-
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
239-
with:
240-
fetch-depth: 25
241-
persist-credentials: false
233+
pnpm --version
242234
243235
# Cache pnpm store on GitHub-hosted runners (self-hosted runners have their own persistent storage)
244236
- name: Get pnpm store directory
@@ -378,6 +370,13 @@ jobs:
378370
if: ${{ inputs.testTimingsArtifact == '' }}
379371
run: pnpm dlx turbo@${TURBO_VERSION} run get-test-timings -- --build ${{ github.sha }}
380372

373+
- name: Normalize input step names into path key
374+
uses: actions/github-script@d746ffe35508b1917358783b479e04febd2b8f71 # v9.0.0
375+
id: var
376+
with:
377+
script: |
378+
core.setOutput('input_step_key', '${{ inputs.stepName }}'.toLowerCase().replaceAll(/[/.]/g, '-').trim('-'));
379+
381380
# Restore the list of tests that already passed in an earlier
382381
# attempt of this same workflow run.
383382
- name: Restore passed-tests cache

0 commit comments

Comments
 (0)