Pin the Baseline date in .browserslistrc
What does this MR do and why?
Makes the compiled frontend assets a function of the source again, instead of the day they are compiled:
- Pins
.browserslistrctobaseline widely available on 2026-10-01. - Adds
.browserslistrcto the assets cache key inscripts/lib/assets_sha.rb. - Adds
Keeps::UpdateBrowserslistBaselineDate, a monthly housekeeper keep that moves the date to the first day of the current month through a reviewed MR.
The problem
.browserslistrc contains the bare query baseline widely available. For that form, browserslist calls getCompatibleVersions() without a date (index.js#L821-L866 at 4.28.5), and baseline-browser-mapping uses new Date() minus 30 months as the cutoff. The resolved browsers drive Babel preset-env with useBuiltIns: 'usage' (so the core-js polyfill set, babel.config.js), the SWC env.targets in config/rspack/loader_rules.js, and autoprefixer (postcss.config.js).
Resolved with the lockfile versions (browserslist 4.28.5, baseline-browser-mapping 2.10.42, caniuse-lite 1.0.30001803, core-js-compat 3.38.0, corejs.version 3.45.1), the same source targets these browsers depending on the build day (UTC):
| Build day | Chrome / Edge | Firefox | Safari / iOS Safari | core-js polyfills |
|---|---|---|---|---|
| 2026-07-25 to 2026-08-19 | 121 | 122 | 17.2 | 188 |
| 2026-08-20 to 2026-09-04 | 121 | 123 | 17.2 | 188 |
| 2026-09-05 to 2026-09-18 | 121 | 123 | 17.4 | 184 |
| 2026-09-19 to 2026-09-21 | 121 | 124 | 17.4 | 184 |
| 2026-09-22 to 2026-10-15 | 123 | 124 | 17.4 | 183 |
| 2026-10-16 to 2026-10-17 | 123 | 125 | 17.4 | 183 |
| 2026-10-18 to 2026-11-12 | 124 | 125 | 17.4 | 183 |
The CI asset cache hides this most of the time, but every recompilation picks up the current day. A patch release compiled weeks after the first release of a version can drop polyfills that the version shipped with. baseline-browser-mapping itself recommends pinning the date per build (README, "Keeping baseline-browser-mapping up to date"), and browserslist documents the dated form (README).
Why 2026-10-01
It resolves to the same 115 browsers and the same 183 core-js polyfills as the undated query on 2026-10-12, so merging changes nothing in the compiled output. Every date from 2026-09-22 to 2026-10-15 resolves to that set. If this merges after 2026-10-15, the pin is still deterministic, but it holds the browser set at the 2026-10-01 level, while an undated build would already have moved on, until the keep's November MR.
Babel preset-env 7.23.7 and autoprefixer 10.4.14 produce byte-identical output for the old and the new .browserslistrc on a sample that uses polyfillable APIs (Array#at, Promise.withResolvers, ArrayBuffer#transfer, Set#union, and others) and prefixable CSS. The same sample with on 2026-08-01 produces 29 instead of 27 core-js imports, so the comparison does detect a change.
Why the cache key changes
.assets-compilation-patterns in .gitlab/ci/rules.gitlab-ci.yml already lists .browserslistrc, and scripts/lib/assets_sha.rb says that its list should match, but AssetsSha did not hash the file. The .assets-cache key and the assets image tag both come from that hash, and scripts/compile_assets skips compilation on a cache hit. Without this change, a commit that only moves the date would reuse assets compiled for the previous browser set.
Keeping the date current
The keep follows the existing pattern for scheduled keeps in .gitlab/ci/housekeeping.gitlab-ci.yml, like the monthly frontend keep Keeps::CleanupGlIntroduced. It sets the first day of the current month, so every run in a month produces the same change and a rerun updates the open MR. It does nothing when the pinned date is already that day or later, or when the query has no date. Every month reuses the same branch, so the keep overrides recreate_when_closed? (like Keeps::RubocopFixer): closing one month's MR does not stop the following months. It asks a maintainer::frontend reviewer, because moving the date changes the shipped browser support.
Alternatives considered:
- A Renovate custom manager: the Renovate configuration for this project lives outside it, in
gitlab-org/frontend/renovate-gitlab-bot(doc/development/dependencies.md), and the date is not a version of any package. - A spec that fails when the date is older than N months: it would break master on a day unrelated to any change.
- Deriving the date from the commit date during the build: GitLab compiles assets in several places (CI, Omnibus, CNG,
gitlab:assets:compileon source installations), and not all of them have Git metadata. A date in the file works everywhere.
Consumers of the query
| Consumer | How it reads .browserslistrc |
Result with the dated query |
|---|---|---|
config/rspack/loader_rules.js (SWC env.targets) |
browserslist(browserslist.loadConfig({ path: ROOT_PATH })) |
Same 115 browsers |
babel.config.js (@babel/preset-env) |
@babel/helper-compilation-targets 7.27.2, browserslist config |
Identical output |
postcss.config.js (autoprefixer) |
browserslist config | Identical output |
config/helpers/supported_browsers.js |
SHA-256 of the file content | One-time miss of the webpack babel-loader and Rspack persistent caches, as intended |
config/rspack.config.mjs |
target: 'web', so Rspack does not resolve browserslist itself |
Not affected |
vite.config.js |
lightningcss with errorRecovery only; PostCSS as above |
Not affected |
doc/install/requirements.md |
Describes the Widely available set, does not quote the query | Still accurate, no change |
browserslist added both the bare and the dated Baseline forms in 4.26.0, and yarn.lock resolves every browserslist range to 4.28.5, so no consumer can understand one form but not the other.
Known limitation
baseline-browser-mapping parses the date as UTC midnight but subtracts the 30 months in local time. Comparing every day from 2025-01-01 to 2027-12-31 in six time zones against UTC, 54 of 1095 dates resolve to a slightly different set in at least one of them. 2026-10-01 and the monthly dates from 2026-11-01 to 2027-08-01 are not affected. CI compiles in UTC. This could be reported upstream to web-platform-dx/baseline-browser-mapping.
References
- browserslist 4.28.5, Baseline query handling
- baseline-browser-mapping 2.10.42 README, "Keeping
baseline-browser-mappingup to date" - gitlab-housekeeper README
Screenshots or screen recordings
Not applicable: build configuration only, no UI change.
How to set up and validate locally
-
On
masterand on this branch, compare the resolved browsers. Until 2026-10-15 both print the same list:yarn browserslist -
See how the set depends on the date:
yarn browserslist "baseline widely available on 2026-08-01" yarn browserslist "baseline widely available on 2026-10-01" -
Dry-run the keep. In October 2026 it makes no change, because the date is already 2026-10-01. To see a change, first set an older date in
.browserslistrcand commit it, then run:bundle exec gitlab-housekeeper -d -k Keeps::UpdateBrowserslistBaselineDateThe dry run commits the change to a local branch and prints the MR it would open. It does not push.
Post-merge
Create a pipeline schedule on the default branch with SCHEDULE_TYPE=housekeeping and HOUSEKEEPING_KEEP=update_browserslist_baseline_date, and a monthly cron early in the month (for example 0 6 2 * *), as described at the top of .gitlab/ci/housekeeping.gitlab-ci.yml. HOUSEKEEPER_GITLAB_API_TOKEN is already required by the other housekeeping jobs.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.