Skip to content

chore: migrate BigQuery npm publishing workflow to OSS Exit Gate - #3305

Open
zarturod wants to merge 49 commits into
firebase:masterfrom
zarturod:chore/oss-exit-gate-migration
Open

zarturod wants to merge 49 commits into
firebase:masterfrom
zarturod:chore/oss-exit-gate-migration

Conversation

@zarturod

Copy link
Copy Markdown

Summary

Migrates the existing .github/workflows/npm_publish_bq_scripts.yml and .github/workflows/scripts/npm_publish.sh publishing workflow for the @firebaseextensions/* packages (@firebaseextensions/firestore-bigquery-change-tracker, @firebaseextensions/fs-bq-import-collection, @firebaseextensions/fs-bq-schema-views) to publish through OSS Exit Gate (firebase-extensions/npm).

Changes

  • Authenticates to Google Cloud Workload Identity Federation (projects/305452601764/locations/global/workloadIdentityPools/builders/providers/github).
  • Stages the package tarball to Artifact Registry (https://us-npm.pkg.dev/oss-exit-gate-prod/firebase-extensions--npm/).
  • Uploads the release manifest.json to gs://oss-exit-gate-prod-projects-bucket/firebase-extensions/npm/manifests/ to trigger OSS Exit Gate publishing.

dependabot Bot and others added 30 commits July 20, 2026 20:50
…y with 12 updates

Bumps the version-minor-and-patch group with 12 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [ts-jest](https://github.com/kulshekhar/ts-jest) | `29.4.9` | `29.4.11` |
| [@genkit-ai/google-genai](https://github.com/genkit-ai/genkit/tree/HEAD/js/plugins/google-genai) | `1.37.0` | `1.39.0` |
| [@types/express-serve-static-core](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/express-serve-static-core) | `4.19.8` | `4.19.9` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `20.19.39` | `20.19.43` |
| [genkit](https://github.com/genkit-ai/genkit/tree/HEAD/js/genkit) | `1.33.0` | `1.39.0` |
| [js-yaml](https://github.com/nodeca/js-yaml) | `3.14.2` | `3.15.0` |
| [nodemailer](https://github.com/nodemailer/nodemailer) | `9.0.1` | `9.0.3` |
| [smtp-server](https://github.com/nodemailer/smtp-server) | `3.19.1` | `3.19.2` |
| [@types/node-fetch](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node-fetch) | `2.6.4` | `2.6.13` |
| [@genkit-ai/vertexai](https://github.com/genkit-ai/genkit/tree/HEAD/js/plugins/vertexai) | `1.37.0` | `1.39.0` |
| [sharp](https://github.com/lovell/sharp) | `0.34.5` | `0.35.3` |
| [nanoid](https://github.com/ai/nanoid) | `5.1.9` | `5.1.16` |



Updates `ts-jest` from 29.4.9 to 29.4.11
- [Release notes](https://github.com/kulshekhar/ts-jest/releases)
- [Changelog](https://github.com/kulshekhar/ts-jest/blob/main/CHANGELOG.md)
- [Commits](kulshekhar/ts-jest@v29.4.9...v29.4.11)

Updates `@genkit-ai/google-genai` from 1.37.0 to 1.39.0
- [Release notes](https://github.com/genkit-ai/genkit/releases)
- [Commits](https://github.com/genkit-ai/genkit/commits/@genkit-ai/google-genai@1.39.0/js/plugins/google-genai)

Updates `@types/express-serve-static-core` from 4.19.8 to 4.19.9
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/express-serve-static-core)

Updates `@types/node` from 20.19.39 to 20.19.43
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `genkit` from 1.33.0 to 1.39.0
- [Release notes](https://github.com/genkit-ai/genkit/releases)
- [Commits](https://github.com/genkit-ai/genkit/commits/genkit@1.39.0/js/genkit)

Updates `js-yaml` from 3.14.2 to 3.15.0
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](nodeca/js-yaml@3.14.2...3.15.0)

Updates `nodemailer` from 9.0.1 to 9.0.3
- [Release notes](https://github.com/nodemailer/nodemailer/releases)
- [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md)
- [Commits](nodemailer/nodemailer@v9.0.1...v9.0.3)

Updates `smtp-server` from 3.19.1 to 3.19.2
- [Release notes](https://github.com/nodemailer/smtp-server/releases)
- [Changelog](https://github.com/nodemailer/smtp-server/blob/master/CHANGELOG.md)
- [Commits](nodemailer/smtp-server@v3.19.1...v3.19.2)

Updates `@types/node-fetch` from 2.6.4 to 2.6.13
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node-fetch)

Updates `@genkit-ai/vertexai` from 1.37.0 to 1.39.0
- [Release notes](https://github.com/genkit-ai/genkit/releases)
- [Commits](https://github.com/genkit-ai/genkit/commits/@genkit-ai/vertexai@1.39.0/js/plugins/vertexai)

Updates `sharp` from 0.34.5 to 0.35.3
- [Release notes](https://github.com/lovell/sharp/releases)
- [Commits](lovell/sharp@v0.34.5...v0.35.3)

Updates `nanoid` from 5.1.9 to 5.1.16
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](ai/nanoid@5.1.9...5.1.16)

---
updated-dependencies:
- dependency-name: ts-jest
  dependency-version: 29.4.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: version-minor-and-patch
- dependency-name: "@genkit-ai/google-genai"
  dependency-version: 1.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: version-minor-and-patch
- dependency-name: "@types/express-serve-static-core"
  dependency-version: 4.19.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: version-minor-and-patch
- dependency-name: "@types/node"
  dependency-version: 20.19.43
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: version-minor-and-patch
- dependency-name: genkit
  dependency-version: 1.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: version-minor-and-patch
- dependency-name: js-yaml
  dependency-version: 3.15.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: version-minor-and-patch
- dependency-name: nodemailer
  dependency-version: 9.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: version-minor-and-patch
- dependency-name: smtp-server
  dependency-version: 3.19.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: version-minor-and-patch
- dependency-name: "@types/node-fetch"
  dependency-version: 2.6.13
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: version-minor-and-patch
- dependency-name: "@genkit-ai/vertexai"
  dependency-version: 1.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: version-minor-and-patch
- dependency-name: sharp
  dependency-version: 0.35.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: version-minor-and-patch
- dependency-name: nanoid
  dependency-version: 5.1.16
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: version-minor-and-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
…n/version-minor-and-patch-5f24554eda

chore(deps): bump the version-minor-and-patch group across 1 directory with 12 updates
…e#2928)

* chore: backfill Apache license headers in ts/js files

Claude-Session: https://claude.ai/code/session_013dz9GhC3metut6HFswPavu

* ci: enforce Apache license headers with addlicense

Adds a license job to the Validate workflow that runs google/addlicense
in check mode over tracked ts/js files. Run npm run license:fix locally
to add missing headers.

Claude-Session: https://claude.ai/code/session_013dz9GhC3metut6HFswPavu

* ci: pin validate workflow actions to commit SHAs

Required by zizmor unpinned-uses mandatory policy.

Claude-Session: https://claude.ai/code/session_013dz9GhC3metut6HFswPavu

* ci: restrict validate workflow to read-only permissions

Resolves zizmor excessive-permissions finding.

Claude-Session: https://claude.ai/code/session_013dz9GhC3metut6HFswPavu

* chore: harden addlicense script

NUL-separated file list for filenames with special characters, and
reject unknown modes instead of defaulting to fix.

Claude-Session: https://claude.ai/code/session_013dz9GhC3metut6HFswPavu
…s-branch

Kits should be published from the kits branch
This helps debug action failures when several releases are happening at once and they fail early
Print inputs as the first step of release-kits
## Summary

`npm publish --provenance` requires `repository.url` to resolve to the
GitHub repo that built the package. Two BigQuery script packages
declared a bare `github.com/firebase/extensions.git` — no scheme, so npm
can't normalise it and provenance fails.

Prefixed both with `git+https://`, matching
`firestore-bigquery-change-tracker`, which already publishes fine:

- `@firebaseextensions/fs-bq-schema-views`
- `@firebaseextensions/fs-bq-import-collection`

Broken since `--provenance` was added in March 2026. No other
`package.json` on `next` is affected.
Syncs release-kit.yaml byte-for-byte with the version that landed on
kits in firebase#2990. This copy never executes (Release Kit is always
dispatched from kits; next has no kits/ directories); it only lists the
workflow in the Actions UI, and it had drifted to show the old broken
versioning logic. No behavior change. Will need re-syncing if firebase#2991
lands on kits.
…ase#2994)

Syncs release-kit.yaml byte-for-byte with the firebase#2993 version on kits
(trusted publishing, checkout/push/release pinned to kits). The firebase#2992
copy on next authenticated via the removed NPM_TOKEN and checked out the
dispatched ref, so dispatching from next failed at the test job. The
firebase#2993 file is dispatch-ref-agnostic, making the two copies safely
identical. No behavior change beyond fixing dispatch-from-next.
inlined and others added 18 commits August 31, 2026 14:49
…elease-kit

chore(ci): print inputs at start of release-kit workflow
…ebase#2937)

## The bug

The retry guard was an `async` function called without `await`, so it
was always truthy and every insert failure retried with
`ignoreUnknownValues: true`. Unknown fields were dropped and the write
reported success. Since 2020 (`2de70201`), untested.

## The fix

The retry now removes only the columns BigQuery named, and only the ones
we add to existing tables (`document_id`, `old_data`, and `path_params`
with `wildcardIds`). Anything else fails the insert and backs up the
full row.

Two adjacent bugs go with it: `settings()` was called on every failure
though it may only be called once, so every backup after the first
threw; and `error_details` was always empty.

## Testing

52 new offline tests, `tsc --noEmit` clean, plus verified against a live
BigQuery instance.

## To decide

Allowlisting `document_id` costs a duplicate row in the legacy `_latest`
view, taken because those tables already duplicate every pre-upgrade
row. Needs a CHANGELOG note and a tracker version bump.

---------

Co-authored-by: Jacob Cable <jacobcable94@gmail.com>
…d clustering sync (firebase#2817)

Fixes firebase#2194. (firebase#2801, the `db.settings()` guard, was originally part of
this branch but landed on next with firebase#2937; this PR no longer touches
that file.)

firebase#2194: `tableRequiresUpdate` always returned true, via two accidental
triggers: `JSON.stringify(config.clustering)` gives `"null"` vs the
table's `"[]"`, and `fields.find(...)` fed `undefined` into a boolean
comparison. Fixed with `config.clustering || []` and `fields.some(...)`.
The `find` -> `some` change is behavioral, not cosmetic: clustering sync
on existing tables depended on the always-true trigger, because
`updateClustering` mutated the shared metadata before
`tableRequiresUpdate` compared it (desired vs desired). A third commit
moves `updateClustering` after the check, inside `shouldUpdate`. The
`some` fix has no behavioral regression guard (offline tests pass
booleans directly, and the live suites assert final table state, which
the spurious update also produced), so `fields` is now typed
`TableField[]` and a revert to `find` fails compilation.

Rebased onto next after firebase#2937 merged. The behavior change disclosed
earlier is now narrower: `tableRequiresUpdate` gained a trigger that
fires when the configured custom partition column is missing from the
table's schema, so the column is added by a real metadata update on the
next initialize instead of by the old spurious path, and the trigger
stops firing once the column lands. What remains: an insert racing the
column's schema propagation fails terminally with its rows backed up
intact, since the column is deliberately not stripped for a lag retry (a
null there misfiles the row into the wrong partition permanently).

Verified against live BigQuery: clustering, insertRetry, backupSettings,
and checkUpdates suites all pass; clustering, checkUpdates, and
partitioning (with `RUN_BIGQUERY_INTEGRATION_TESTS=true`) re-run after
the review follow-up.
…rc-to-next

feat(release-kit): add use firebase-functions RC checkbox and validation
…ase-admin 14 (firebase#3133)

The change tracker pins `firebase-admin` to `^13.2.0`. A consumer on
firebase-admin 14 therefore installs a second copy of the SDK nested
under the tracker, and that copy has its own app registry: the
consumer's `initializeApp()` never reaches it. Every call the tracker
makes through its own copy, which today is the backup write in
`handleFailedTransactions`, fails with "The default Firebase app does
not exist", the failure is logged as `failedBackupWrite`, and the rows
meant for `backupTableId` are lost. Verified by loading both copies in
one process against the published 2.1.0.

The range was already widened to `^13.2.0 || ^14.0.0` on the `kits`
branch (cc86630) but that landed at 2.0.4 and was never published;
2.1.0 was cut from `next` without it. This cherry-picks that commit onto
`next` and releases it as 2.1.1 with a changelog entry. No source
changes: the tracker only uses `getFirestore`, `firebase-admin/app` and
`Timestamp`, all unchanged between 13 and 14, and the firebase-functions
6 it depends on already accepts admin 14.

`npm ci` and `npm run build` pass. The jest suite needs live BigQuery
and was not run.

Unblocks the kit bump in firebase#3127.

---------

Co-authored-by: Izaak Gough <izaak.gough@invertase.io>
…ase-admin 14 (firebase#3134)

Follow-up to firebase#3133. 2.1.1 widened the firebase-admin range to `^13.2.0
|| ^14.0.0` but two things stopped it working on 14.

First, firebase-admin 14 removes the namespaced API. The package still
read `admin.apps` at import in `handleFailedTransactions` and
`admin.firestore.Timestamp` in the partition converter, so wherever it
resolved against admin 14 it threw `Cannot read properties of undefined
(reading 'length')` at import. Every namespaced use, in shipped code,
the test fixture and the tests, is now the modular API from
`firebase-admin/app` and `firebase-admin/firestore`, which is identical
on 13 and 14.

Second, the package depends on firebase-functions `^6.3.2`, whose peer
range for firebase-admin stops at `^13.0.0`. On a consumer running admin
14 npm therefore kept a nested admin 13 under the tracker regardless of
the tracker's own range, and that nested copy has no default app. Under
npm that nesting is also why 2.1.1 did not crash: `admin.apps` resolved
on the nested 13. The range now accepts firebase-functions 7 as well;
the package only uses its `logger`.

Verified: build and the test tsconfig compile against admin 14.3.0 and
functions 7.3.2; `converter.test.ts` passes (48) on that tree; the
packed tarball installed into the firestore-bigquery-export kit on admin
14, followed by `npm dedupe`, collapses to a single admin copy, the
tracker resolves the kit's app, and all 62 kit tests pass. An existing
consumer shrinkwrap does not dedupe on its own, since the nested 13
still satisfies the new ranges, so the kit bump must dedupe explicitly.
The kit pins firebase-functions `^7.3.3-rc.0`, which no stable range
matches, so a nested firebase-functions 7.3.2 remains under the tracker
until the kit moves to a stable 7.x; that only affects trace correlation
on tracker log lines, not the admin app.

The lockfile stays on admin 13 and functions 6 because under admin 14
the jest config cannot load the ESM-only `jose` that firebase-functions
v2 pulls in via admin auth; that is a jest `transformIgnorePatterns` gap
for a separate change. The live BigQuery suites were not run.

Unblocks the kit bump in firebase#3127.
…view updates, release 2.2.1 (firebase#3137)

Cherry-pick of da21982 from firebase#3121 (Corie's fix, approved by Izaak) onto
`next`, plus the 2.2.1 version bump and changelog entry. firebase#3121 targets
`kits`, but the tracker is published from `next`, so the fix never
reached npm from there.

The bug: `initializeLatestView` builds the snapshot query for an
existing `_raw_latest` view without `bqProjectId`, so
`buildLatestSnapshotViewQuery` falls back to `process.env.PROJECT_ID`.
That variable is only set for extensions. On a kit the view query became
`undefined.<dataset>.<table>` and the `initBigQuerySync` task failed in
`afterFirstDeploy`. The create path already passed the project. The fix
passes `bq.projectId` on the update path too, matching the create path.

Tests: the materializedViews suites pass locally (20 tests), including
the new one that sets `process.env.PROJECT_ID` to a decoy and asserts
the query uses the BigQuery project. Not verified against a live
redeploy.

After merge, dispatch `npm_publish_bq_scripts.yml` for 2.2.1, then
regenerate the kit shrinkwrap in the stack so the rc pins it.

Fixes firebase#3120

---------

Co-authored-by: Corie Watson <watson.corie@gmail.com>
…e#3187)

Add a `use_peer_dependencies_only` boolean input to the `release-kit`
workflow to allow publishing kits with `firebase-functions` and
`firebase-admin` as peer dependencies.

When enabled:
- Inspects `package.json` for `firebase-functions` and `firebase-admin`
in
  `dependencies` using `npm pkg get`.
- Runs `npm install --save-peer <pkg@spec>` followed by
  `npm install --save-dev <pkg@spec>` using the extracted version spec.
- Moves the packages out of `dependencies` into `peerDependencies` while
  retaining them in `devDependencies` so tests and builds succeed.
- Executes after the optional `firebase-functions@next` install step in
both
  the `test` and `release` jobs so that RC version specs are preserved.
- Reports the option status in the Dry Run Summary.
…ly" checkbox (firebase#3190)

1. Our existing nested dependency problems seem better solved by adding
`"skipLibCheck": true` to wrapper tsconfig.json
2. This workflow actually wrote peer dependencies to git which is not a
good workflow. If we want to go this route we should design a better
system that allows testing with regular dependencies and releases with
peer dependencies.
Byte-for-byte copy of `.github/workflows/release-kit.yaml` from the
companion `kits` PR (fix/release-kit-dist-tag). The `next` copy exists
only so the workflow appears in the Actions UI, but GitHub runs the
steps from the dispatched ref, so drift here changes what gets
published.

This copy had drifted: it lacked the shrinkwrap prune step from firebase#3085.
firestore-bigquery-export@0.1.0 was dispatched from `next` today and
shipped 101 dev lock entries including the `@esbuild/*` platform
binaries, so consumer `npm ci` under npm 10 fails with `EBADPLATFORM`.
It also still ran `npm dist-tag add` after a stable publish, which the
trusted-publishing token cannot do (E401).

Merge the `kits` PR first, then this one, and check the two files are
identical afterwards. Not verified live.
…nt marker (firebase#3218)

Add the deprecation notice and machine-readable
FIREBASE_EXTENSION_REPLACEMENT marker to README.md and PREINSTALL.md,
pointing to @firebase-function-kits/firestore-bigquery-export.
…cation

docs: explain the Extensions deprecation and function kits in the README
@zarturod
zarturod requested a review from a team as a code owner October 27, 2026 14:53
@google-cla

google-cla Bot commented Oct 27, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds copyright headers across the repository, introduces a script to automate license header checks, and updates several dependencies. It also adds deprecation notices to the extensions' documentation recommending migration to function kits, and implements robust error handling, retries, and backup mechanisms for failed BigQuery inserts in the firestore-bigquery-change-tracker library. Feedback was provided on the license script to prevent unexpected failures when no matching files are found.

Comment thread scripts/addlicense.sh Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants