-
Notifications
You must be signed in to change notification settings - Fork 3.2k
chore(ci): check build memory against vercel machine size #4657
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,129 @@ | ||
| # Measures how much memory a full production build needs and compares it | ||
| # against the capacity of the Vercel build machine the docs are running on. | ||
| # | ||
| # Run this before a release. Adding a documentation version is what moves the | ||
| # number, so this answers "do we need a bigger build machine before we ship?" | ||
| # while there is still time to change it. | ||
| # | ||
| # Preview deployments only build English, so they never exercise the Japanese | ||
| # locale and cannot catch this. This workflow builds both. | ||
|
|
||
| name: 'Docs Build Memory Check' | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| machine: | ||
| description: 'Which Vercel build machine type is ionic-docs on? (Project Settings > Build and Deployment > Build Machine)' | ||
| required: true | ||
| type: choice | ||
| default: Standard | ||
| options: | ||
| - Standard | ||
| - Enhanced | ||
| - Turbo | ||
| - Elastic | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| measure: | ||
| name: 📏 Measure Production Build Memory | ||
| # Must be Linux. `/usr/bin/time -v` is GNU specific, and Vercel builds on | ||
| # Linux, so the numbers are comparable. | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||
|
|
||
| - name: ⚙️ Use Node.js 20 | ||
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | ||
| with: | ||
| node-version: 20 | ||
|
|
||
| - name: 🕸️ Install Dependencies | ||
| run: npm ci --legacy-peer-deps | ||
|
|
||
| - name: 🏗️ Build All Locales | ||
| env: | ||
| # `npm run build` resolves to build:${VERCEL_ENV:-preview}, and | ||
| # build:preview is English only. Without this the job would measure | ||
| # the half that already fits and would never catch the problem. | ||
| VERCEL_ENV: production | ||
| # scripts/release-notes.mjs exits non-zero in CI without a token. | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| # prebuild runs `crowdin upload` when this is non-empty, which pushes | ||
| # source strings to Crowdin. This job only measures memory and must | ||
| # never publish, so it is pinned empty rather than relying on the | ||
| # secret not being exposed to this workflow. | ||
| CROWDIN_PERSONAL_TOKEN: '' | ||
| run: /usr/bin/time -v -o build-memory.log npm run build | ||
| shell: bash | ||
|
|
||
| - name: 📊 Report Against Machine Capacity | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This step has no That's worth keeping, because the log still has the number in it. GNU time writes its whole report before working out its own exit status, so an OOM-killed build leaves the peak RSS in the log with a |
||
| env: | ||
| MACHINE: ${{ inputs.machine }} | ||
| run: | | ||
| set -euo pipefail | ||
|
|
||
| PEAK_KB=$(awk '/Maximum resident set size/ { print $NF }' build-memory.log) | ||
| if [ -z "$PEAK_KB" ]; then | ||
| echo "::error::Could not read peak memory from build-memory.log" | ||
| exit 1 | ||
| fi | ||
| PEAK_GB=$(awk -v kb="$PEAK_KB" 'BEGIN { printf "%.2f", kb / 1048576 }') | ||
|
|
||
| # A build must stay well below a machine's advertised size, for two | ||
| # reasons. Vercel's own processes need part of that memory, so the | ||
| # nominal figure is not all available: the build that failed during | ||
| # the v9 release measured about 8.2 GB and was killed on a nominally | ||
| # 8 GB machine. And identical builds vary between runs, measured at | ||
| # 7.86 GB and 8.42 GB on the same input. | ||
| # | ||
| # This margin is a judgment call, not a number published by Vercel. | ||
| # It only becomes load bearing when the build comes within a couple | ||
| # of GB of a tier boundary. | ||
| THRESHOLD_PCT=75 | ||
|
|
||
| # Smallest fixed tier this build fits on under the threshold. Falls | ||
| # back to Turbo, the largest, when nothing fits. | ||
| RECOMMENDED=$(awk -v peak="$PEAK_GB" -v t="$THRESHOLD_PCT" 'BEGIN { | ||
| split("Standard:8 Enhanced:16 Turbo:60", tiers, " ") | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The PR description says there's no hardcoded capacity to keep up to date, but the dropdown only carries the tier name. The capacities are literals here and again in the The values are all correct against Vercel's current specs, so nothing's wrong today. It's the next change I'd worry about: patching the |
||
| for (i = 1; i <= 3; i++) { | ||
| split(tiers[i], tier, ":") | ||
| if (peak / tier[2] * 100 <= t) { print tier[1]; exit } | ||
| } | ||
| print "Turbo" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: when nothing fits under the threshold this prints |
||
| }') | ||
|
|
||
| # Elastic has no fixed capacity to check against. It sizes each build | ||
| # from recent successful builds, so when earlier builds were killed | ||
| # before recording what they needed it can assign a machine smaller | ||
| # than the build requires. Report the size, but make no pass or fail | ||
| # claim. | ||
| if [ "$MACHINE" = "Elastic" ]; then | ||
| echo "::warning title=Check the machine Elastic will assign::Elastic sizes each build from recent successful builds, so there is no fixed capacity to check against. Confirm what it will assign under Project Settings > Build and Deployment > Build Machine, where it names the machine your next deployment will use. Otherwise switch to ${RECOMMENDED}, which this ${PEAK_GB} GB build fits on." | ||
| exit 0 | ||
| fi | ||
|
|
||
| case "$MACHINE" in | ||
| Standard) CAPACITY=8 ;; | ||
| Enhanced) CAPACITY=16 ;; | ||
| Turbo) CAPACITY=60 ;; | ||
| *) | ||
| echo "::error::Unknown machine type: $MACHINE" | ||
| exit 1 | ||
| ;; | ||
| esac | ||
|
|
||
| if awk -v cap="$CAPACITY" -v peak="$PEAK_GB" -v t="$THRESHOLD_PCT" 'BEGIN { | ||
| exit (peak / cap * 100 > t) ? 1 : 0 | ||
| }'; then | ||
| echo "::notice title=Success! No action needed::Build peaks at ${PEAK_GB} GB, so it should have no issues on the ${MACHINE} machine." | ||
| exit 0 | ||
| fi | ||
|
|
||
| echo "::error title=Move to ${RECOMMENDED} before releasing::Build peaks at ${PEAK_GB} GB, too close to the ${CAPACITY} GB ceiling of the ${MACHINE} machine. Vercel needs part of that memory for its own processes, so the build cannot use all of it." | ||
| exit 1 | ||
| shell: bash | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think Vercel is building this on Node 24, not 20. Their docs say
engines.nodeoverrides whatever's picked in Project Settings, and their mapping table puts>=20.0.0in the 24.x row, resolving to the latest 24.x. This repo'spackage.jsondeclares exactly that.If that's right, the measurement is on a different major than production, and GC behavior moves between majors enough to undercut the comparison. The quick fix is
node-version: 24. A committed.nvmrcthat both this workflow and Vercel read would be the durable one, since there's no.nvmrcor Volta pin right now.