@mparticle/web-sdk 3.29.1 → 3.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -162,13 +162,181 @@ only at its Step 3. Once a V3 release has run on
162
162
  `staging-step-1.yml`. V2 runs the copies on `staging` and `master`, which this
163
163
  split does not change.
164
164
 
165
+ The last V3 release cut by semantic-release, whose Step 3 brings `main` level
166
+ with `v3-development`, ends that path. Every later V3 release is cut from
167
+ `main` by Release Please, as the next section describes, and `v3-development`
168
+ is retired.
169
+
170
+ ### V3 releases from `main` with Release Please
171
+
172
+ V3 pull requests merge to `main`. Release Please reads their Conventional
173
+ Commit titles and cuts each V3 release from `main`:
174
+
175
+ 1. **V3 Release Please** (`v3-release-please.yml`) keeps one release pull
176
+ request open on `main`. It carries the next version, the changelog entry and
177
+ the version of every kit.
178
+ 2. On each push to that pull request, **V3 Release Please - Commit Release
179
+ Bundles** builds core and every kit at that version and commits `dist/` and
180
+ `kits/**/dist` as the release machine user. The check **V3 release bundles
181
+ match version** passes once the committed bundles match that build. No other
182
+ pull request to `main` may change `dist/` or `kits/**/dist` (the check **V3
183
+ bundles change only in release PRs**).
184
+ 3. Before merging the release pull request, check that it does not show "This
185
+ branch is out-of-date with the base branch". If it does, wait for Release
186
+ Please to rewrite it and for **V3 release bundles match version** to go
187
+ green again. Hold other merges to `main` for a couple of minutes while you
188
+ merge. Release Please publishes the GitHub release and creates the `v3.X.Y`
189
+ tag on the merge commit.
190
+ 4. Run **V3 Release - Step 1** from that tag: in **Use workflow from**, choose
191
+ the tag, not a branch. Run it with `dryRun=true`, then `dryRun=false`. It
192
+ checks that the tag is on `main`, rebuilds core and every kit and compares
193
+ them with the tag's bundles, publishes core and every kit to npm `next`, and
194
+ then moves `v3-staging` forward to the tag commit. If a run stops part-way,
195
+ run Step 1 from the same tag again: it skips every package npm already holds
196
+ with the same bytes. A Step 1 run from a tag runs only while the
197
+ repository variable `V3_RELEASE_PLEASE_ENABLED` is `true`, and a run from
198
+ `v3-staging` fails once it is.
199
+ 5. Run Steps 2 and 3 from `main` as described below. Step 3 pushes only the
200
+ three release-order branches, because `main` already holds the release.
201
+ Don't change `V3_RELEASE_PLEASE_ENABLED` while a Step 3 run or its S3
202
+ promote is in progress. If a promote skipped because the variable changed,
203
+ run `promote-ga` by hand.
204
+
205
+ `main` moves to the new version when the release pull request merges, and
206
+ `ga` serves it only after `promote-ga`. In that window `main` is ahead of
207
+ `ga` on every release. This is expected, and the gap closes at `promote-ga`.
208
+ Roll a release back with **v3-shadow-promote**: `rollback` for one channel, or
209
+ `rollback-all` for every channel in the selected pods. Rokt's internal V3 web
210
+ SDK delivery runbook holds the serving checks for each release.
211
+
212
+ Set the repository variable `V3_DIST_GUARD_ENABLED` to `true` once the first
213
+ Release Please release pull request's bundle commit shows as **Verified** on
214
+ GitHub. Until then, **V3 bundles change only in release PRs** passes with a
215
+ note. Then add it and **V3 release bundles match version** to the required
216
+ checks on `main`. When `V3_DIST_GUARD_ENABLED` is first set, or set again,
217
+ re-run **V3 bundles change only in release PRs** on every open pull request to
218
+ `main`. Each of them passed with a note while the variable was unset, and that
219
+ result stands until the check runs again.
220
+
221
+ #### Switch to Release Please
222
+
223
+ 1. Run the last V3 release cut by semantic-release with the three steps below,
224
+ Step 1 from `v3-staging`. Its Step 3 brings `main` level with
225
+ `v3-development`, and with it **V3 Release Please**, which does nothing
226
+ while `V3_RELEASE_PLEASE_ENABLED` is set to `false`.
227
+ 2. Lock `v3-development` with its ruleset, and retarget its open pull requests
228
+ to `main`. From here on, V3 pull requests merge to `main`.
229
+ 3. Before `V3_RELEASE_PLEASE_ENABLED` is set, merge one small pull request to
230
+ `main` that sets `.release-please-manifest.json` and `CHANGELOG.md` to that
231
+ release's version. The manifest reads that version. The changelog gains a
232
+ `# Changelog` title, and each semantic-release `# [3.X.0]` heading becomes
233
+ `## [3.X.0]`. Release Please adds each entry before the first `##` or `###`
234
+ version heading, so without this its first entry would land below that
235
+ release's.
236
+ 4. Set `V3_RELEASE_PLEASE_ENABLED` to `true`.
237
+ 5. Set `V3_DIST_GUARD_ENABLED` once the first release pull request's bundle
238
+ commit shows as **Verified**, as described above.
239
+
240
+ #### When a release does not go as planned
241
+
242
+ - **The release pull request merged, but no release or tag appeared.** Re-run
243
+ the failed **V3 Release Please** run. If it fails again, publish the release
244
+ from your own machine with the same files, then run Step 1 from the new tag.
245
+ The command pins release-please 17.6.0, the version that the workflow's
246
+ pinned `googleapis/release-please-action` v5.0.0 locks. Change both pins
247
+ together. For `GITHUB_TOKEN`, create a fine-grained personal access token
248
+ for this repository only, with a one-day expiry. Give it write access to
249
+ Contents, Pull requests and Issues, and nothing else (GitHub adds read-only
250
+ Metadata). Release Please labels the release pull request through the Issues
251
+ API. Delete the token once the release is published.
252
+
253
+ ```sh
254
+ npx release-please@17.6.0 github-release --token "$GITHUB_TOKEN" \
255
+ --repo-url mParticle/mparticle-web-sdk --target-branch main \
256
+ --config-file release-please-config.json \
257
+ --manifest-file .release-please-manifest.json
258
+ ```
259
+
260
+ - **Abandon a release.** Before the merge, close the release pull request.
261
+ Release Please opens a new one on the next push to `main`, with every
262
+ unreleased change. To pause Release Please, set `V3_RELEASE_PLEASE_ENABLED`
263
+ to `false` first, then close the open release pull request. That pauses V3
264
+ releases. It does not bring back the semantic-release path (see **Fall back
265
+ to the semantic-release path**). Don't use the `autorelease: snooze` label.
266
+ With `always-update`, Release Please keeps force-updating a snoozed PR.
267
+ After the merge, if a release must not ship, do not run Step 1 for its tag.
268
+ Leave the tag and the GitHub release in place, never reuse the version, and
269
+ merge the fix to `main`. Release Please then cuts the next version, and Step
270
+ 1 from that tag moves `v3-staging` past the abandoned one. This roll-forward
271
+ is how to replace a bad release.
272
+ - **Release a chosen version.** Add the footer `Release-As: 3.X.Y` to the
273
+ commit message of a pull request merged to `main`, for example by editing
274
+ the squash commit message. The next release pull request then proposes
275
+ 3.X.Y instead of the version the commit types give.
276
+
277
+ #### Fall back to the semantic-release path
278
+
279
+ Fall back only when Release Please itself cannot cut releases. To replace one
280
+ bad release, roll forward as **Abandon a release** describes.
281
+
282
+ Setting `V3_RELEASE_PLEASE_ENABLED` to `false` does not bring back the old
283
+ path on its own. Step 1 from `v3-staging` builds whatever `v3-development`
284
+ holds, and `v3-development` stops moving at the switch.
285
+
286
+ It is safe to fall back only when no release is part-way. Every tag Release
287
+ Please cut has finished Step 3 or was abandoned, and no Step 1, 2 or 3 run is
288
+ in progress. Then:
289
+
290
+ 1. Set `V3_RELEASE_PLEASE_ENABLED` to `false` first, then close the open
291
+ release pull request without merging it.
292
+ 2. Unset `V3_DIST_GUARD_ENABLED`. Remove **V3 bundles change only in release
293
+ PRs** and **V3 release bundles match version** from the required checks on
294
+ `main`. The old Step 3 pushes each release to `main` directly, not through
295
+ a pull request.
296
+ 3. Lift the ruleset that locks `v3-development`. Then bring `v3-development`
297
+ and `v3-staging` up to `main`. If either ancestor check fails, stop: that
298
+ branch holds a commit `main` lacks. Merge it into `main` with a pull
299
+ request, then repeat this step. The push is not forced, so it only
300
+ fast-forwards.
301
+
302
+ ```sh
303
+ git fetch origin main v3-development v3-staging
304
+ git merge-base --is-ancestor origin/v3-development origin/main
305
+ git merge-base --is-ancestor origin/v3-staging origin/main
306
+ git push --atomic origin origin/main:refs/heads/v3-development \
307
+ origin/main:refs/heads/v3-staging
308
+ ```
309
+
310
+ 4. Point both Dependabot updates in `.github/dependabot.yml` back at
311
+ `v3-development`, and merge V3 pull requests there again. From here on,
312
+ only Step 3 moves `main`.
313
+ 5. Release with the three steps below, Step 1 from `v3-staging`. Step 1 and
314
+ semantic-release take the newest `v3.X.Y` tag reachable from `v3-staging`,
315
+ a Release Please tag included, so the next version follows it.
316
+
317
+ Step 3 cannot push an older `v3-development` over a newer `main`. Without
318
+ Release Please it pushes all five branches, `main` included. Before the push
319
+ it checks that each one can fast-forward to the tag. If one cannot, it stops
320
+ with `origin/main cannot fast-forward to v3.X.Y` and pushes nothing. That
321
+ means a commit reached `main` outside Step 3. Merge `main` into
322
+ `v3-development` with a pull request, then run Step 1 again.
323
+
324
+ To return to Release Please, finish the last release's Step 3, so `main` and
325
+ `v3-development` are the same commit. Then merge one pull request to `main`
326
+ that sets `.release-please-manifest.json` and `CHANGELOG.md` to that release's
327
+ version, as step 3 of **Switch to Release Please** describes, and points
328
+ Dependabot back at `main`. Set `V3_RELEASE_PLEASE_ENABLED` to `true`, and merge
329
+ V3 pull requests to `main` again. Set `V3_DIST_GUARD_ENABLED` again as
330
+ described above.
331
+
165
332
  In GitHub Actions, choose the version's branch from the **Use workflow
166
333
  from** dropdown and run its workflows in order:
167
334
 
168
335
  1. **Step 1: Prepare CDN Pre-Release, Publish NPM**: run
169
336
  **Staging Release - Step 1** (`staging-step-1.yml`) from `staging` with
170
- `track=v2`, or **V3 Release - Step 1** (`v3-release-step-1.yml`) from
171
- `v3-staging`. This workflow builds and tests the version, creates and
337
+ `track=v2`, or **V3 Release - Step 1** (`v3-release-step-1.yml`) from the
338
+ V3 release tag (see the section above; before Release Please, from
339
+ `v3-staging`). From `staging` or `v3-staging`, this workflow builds and tests the version, creates and
172
340
  merges a generated release branch, runs semantic-release, and publishes the npm
173
341
  release. Before a new v3 release can advance, every existing kit `next` tag
174
342
  must match the core SDK's current `next` version. The one-time `3.0.0`
@@ -209,25 +377,90 @@ from** dropdown and run its workflows in order:
209
377
  the same rule as Step 2. For `releaseTag`, enter the same exact Git
210
378
  tag created by the successful Step 1 run. The workflow verifies that the tag
211
379
  matches `package.json`, resolves to the version's current staging head, and can
212
- fast-forward every destination. It then uses one atomic push to synchronize
213
- the version's development branch, trunk (`master` or `main`), and all three
214
- release-order branches; either every ref updates or none does. `dryRun=true`
215
- performs all validation without pushing. `dryRun=false` performs the atomic
216
- synchronization and releases the candidate to those destinations.
380
+ fast-forward every destination. It then uses one atomic push, so either every
381
+ ref updates or none does. For v2, and for v3 before Release Please, that push
382
+ synchronizes the version's development branch, trunk (`master` or `main`),
383
+ and all three release-order branches. Once `V3_RELEASE_PLEASE_ENABLED` is
384
+ `true`, V3 Step 3 first checks that the tag is on `main`, then pushes only the
385
+ three release-order branches, because `main` already holds the release and
386
+ `v3-development` is retired. `dryRun=true` performs all validation without
387
+ pushing. `dryRun=false` performs the atomic push and releases the candidate
388
+ to those destinations.
217
389
 
218
390
  Safe sequence: run Step 1 with `dryRun=true`, then Step 1 with `dryRun=false`;
219
391
  copy its release tag; optionally preview and run Step 2 for each needed
220
392
  release-order branch; finally run Step 3 with `dryRun=true`, then
221
393
  `dryRun=false`.
222
394
 
223
- Shadow v3 candidate packaging: when the `V3_PACKAGE_CANDIDATE` repository
224
- variable is `true`, a real V3 Step 1 run also runs **Package V3 candidate
225
- (shadow)** after the release. It packages the release tag's committed
226
- bundles into a `v3-candidate-<run id>-<run attempt>` artifact, kept for 7 days.
227
- It never runs for v2 or dry runs, has read-only access, and its failure does
228
- not fail the Step 1 run. It does keep the Step 1 run open until it finishes,
229
- so wait for the whole run to finish before starting Step 2 or Step 3. To turn
230
- it off, delete the variable or set it to anything other than `true`.
395
+ V3 candidate packaging, upload, and staging: a real **V3 Release - Step 1**
396
+ (`v3-release-step-1.yml`, `dryRun=false`) runs **Package V3 candidate
397
+ (shadow)** after the release to package the release tag's committed bundles
398
+ into a `v3-candidate-<run id>-<run attempt>` artifact (kept for 7 days). Once
399
+ **Publish V3 kits** and **Audit V3 kits on npm** have also succeeded, it runs
400
+ **Upload and stage V3 candidate**, which dispatches **V3 shadow
401
+ release: upload candidate** (`v3-shadow-candidate.yml`) on `main` with
402
+ `release_gate=true` and waits up to 120 minutes (the child jobs' 110-minute
403
+ ceiling plus 10 minutes of queue time, inside a 130-minute job timeout) for it
404
+ to succeed. A failed read of the child run's status (a 5xx or rate-limit reply)
405
+ is retried until that deadline. If the job fails, times out or is cancelled
406
+ before the child run completes, it cancels the child run. A refused cancel (a
407
+ 5xx or rate-limit reply) is retried with a doubling backoff (6 tries, 5 seconds
408
+ apart at first) until GitHub accepts it or the child run reads completed, first
409
+ by the wait step and then by the cleanup step. Release-gate dispatches for one
410
+ Step 1 run share one concurrency group (`v3-shadow-candidate-gate-STEP1_RUN_ID`),
411
+ so a re-run's child queues behind a leftover child instead of staging the same
412
+ build in parallel with it. A newer gate dispatch for the same Step 1 run takes
413
+ the group's single pending slot from an older pending one, which then fails its
414
+ own Step 1 wait. A manual dispatch with `release_gate=false` or a transition
415
+ `workflow_run` runs in another group, so it cannot displace a pending gate run.
416
+
417
+ If the dispatch request succeeds but its reply is lost or carries no
418
+ `workflow_run_id`, the job fails with no child run ID, so nothing cancels that
419
+ child. Before re-running Step 1, open the **V3 shadow release: upload
420
+ candidate** runs, find any run dispatched after the failed Step 1 run started,
421
+ and cancel it if it is still running. If it is missed, the shared concurrency
422
+ group still makes the re-run's child wait for it to finish.
423
+
424
+ Release-gate mode accepts both an in-progress `v3-release-step-1.yml`
425
+ parent run and one that has already
426
+ completed without being cancelled (so a maintainer can also dispatch
427
+ `v3-shadow-candidate.yml` manually with `release_gate=true` for repair after
428
+ Step 1 finishes), provided **Perform Release** and **Package V3 candidate
429
+ (shadow)** succeeded and one unexpired candidate artifact exists. Release-gate
430
+ mode also requires npm parity to pass: every package must be on npm with the
431
+ candidate's integrity. **Audit V3 kits on npm** only warns about a kit npm does
432
+ not show yet, and npm can take minutes to show a version it has accepted. So
433
+ while npm parity reads pending (a version npm does not show yet) or unavailable
434
+ (an `npm view` error or an unexpected reply), the candidate workflow reads npm
435
+ again with a doubling backoff (15 seconds at first, at most 2 minutes apart)
436
+ for up to 10 minutes, with a last read when the 10 minutes run out. A fail
437
+ reading (a published package with another integrity) fails the gate at once,
438
+ and a read stops at the first package that differs. A package still pending
439
+ or unavailable after the last read fails the gate instead of uploading. Each
440
+ `npm view` gets at most 30 seconds, and each read of every package at most 2
441
+ minutes. A package the read has no time left for reads unavailable. If `sleep`
442
+ fails between reads, the check fails instead of reading npm again at once. A
443
+ transition `workflow_run`, or a manual dispatch with `release_gate=false`,
444
+ reads npm once. The **Check the candidate against the release** job's
445
+ 25-minute timeout covers the 10 minutes, a last read of at most 2 minutes and
446
+ its other checks.
447
+ A failure in packaging, candidate verification, S3
448
+ upload, or `v3-staging` pointer staging fails the Step 1 release. In
449
+ release-gate mode, `V3_SHADOW_PODS` must include all five production pods
450
+ (`us1`, `us2`, `st1`, `eu1`, `au1`); `qa` is optional (if `qa` is listed in
451
+ `V3_SHADOW_PODS`, it runs in the same matrix and blocks the release on failure;
452
+ if `qa` is omitted from `V3_SHADOW_PODS`, only the five
453
+ production pods block the release and `qa` can run separately). Stage moves each
454
+ pod's `v3-staging` pointer independently in parallel, so if one pod fails, the
455
+ other pods have already moved to the new candidate; re-running failed jobs on
456
+ Step 1 (within the 7-day artifact window) re-runs **Upload and stage V3
457
+ candidate**, dispatches the candidate workflow again, and repairs the remaining
458
+ pods so every pod converges (`resumeKitReleaseTag` skips packaging and upload
459
+ as before). During the transition before a V3 release's Step 3 brings these
460
+ workflow updates to `main`, the shared **Staging Release - Step 1**
461
+ (`staging-step-1.yml`, `track=v3`) still uses the `V3_PACKAGE_CANDIDATE`
462
+ repository variable and the `workflow_run` trigger on `main`, so
463
+ `V3_PACKAGE_CANDIDATE` stays `true` until that transition release finishes.
231
464
 
232
465
  ### Recover an incomplete v3 kit publication
233
466
 
@@ -238,14 +471,22 @@ A real v3 Step 1 run can publish core and create the GitHub Release before all
238
471
  2. Copy the exact release tag from the failed Step 1 run.
239
472
  3. Use the failed job and its npm kit publish summary to identify any
240
473
  missing or rejected kits. Correct their npm or trusted-publisher configuration.
241
- 4. Dispatch **V3 Release - Step 1** from `v3-staging` with `dryRun=false`
474
+ 4. For a release Release Please cut, dispatch **V3 Release - Step 1** again
475
+ from the same tag with `dryRun=false`, and skip the rest of this step.
476
+ Otherwise, dispatch **V3 Release - Step 1** from `v3-staging` with `dryRun=false`
242
477
  and `resumeKitReleaseTag` set to the failed run's exact tag. If `main` has
243
478
  no `v3-release-step-1.yml` yet (the first V3 release after the split),
244
479
  dispatch **Staging Release - Step 1** from `v3-staging` with `track=v3`
245
480
  and the same two inputs instead.
246
481
  5. Wait for recovery to verify core and all 33 kits at that version on `next`.
247
482
  Existing byte-identical packages are skipped and only missing kits publish.
248
- 6. Continue to Step 2 or Step 3 only after the recovery run is green.
483
+ 6. If the failed run was **V3 Release - Step 1**, it did not upload or stage
484
+ its candidate, because that job waits for the kits. Dispatch **V3 shadow
485
+ release: upload candidate** (`v3-shadow-candidate.yml`) on `main` with
486
+ `step1_run_id` set to the failed run's ID and `release_gate=true`, within
487
+ the candidate's 7 days.
488
+ 7. Continue to Step 2 or Step 3 only after the recovery run and the candidate
489
+ upload are green.
249
490
 
250
491
  If recovery reports that the tagged core version is missing from npm, stop the
251
492
  kit recovery. Semantic-release may have pushed the generated staging commit and
@@ -274,7 +515,10 @@ from the branch selected in the **Use workflow from** dropdown, so every
274
515
  staging branch is identical to its trunk's copy: `staging-step-1.yml` on
275
516
  `staging` to `master`'s, and `v3-release-step-1.yml` on `v3-staging` to
276
517
  `main`'s. During the switch to the V3 files, a `track=v3` run of
277
- `staging-step-1.yml` from `v3-staging` must match `main`'s copy instead.
518
+ `staging-step-1.yml` from `v3-staging` must match `main`'s copy instead. A V3
519
+ Step 1 run from a release tag requires the tag's commit to be on `main`
520
+ instead, so a later edit to the workflow on `main` does not block an earlier
521
+ tag.
278
522
 
279
523
  npm trusted publishing names the workflow file that publishes each package:
280
524
  `staging-step-1.yml` publishes v2 of `@mparticle/web-sdk`, and