Skip to content

fix(remoteconfig): validate condition expressions during --dry-run - #11126

Open
Ryu0118 wants to merge 3 commits into
firebase:mainfrom
Ryu0118:fix-remoteconfig-dry-run-validation
Open

Ryu0118 wants to merge 3 commits into
firebase:mainfrom
Ryu0118:fix-remoteconfig-dry-run-validation

Conversation

@Ryu0118

@Ryu0118 Ryu0118 commented Sep 20, 2026

Copy link
Copy Markdown

Description

Closes #11125

firebase deploy --only remoteconfig --dry-run currently performs no server-side validation, so an invalid percent() condition expression silently passes dry-run and only fails on a real deploy.

Root cause: the deploy pipeline's release phase (the only place the real template PUT happens) is skipped for every target when options.dryRun is true, and remoteconfig's client-side validateInputRemoteConfigTemplate() never inspects condition expression content.

Key changes:

  • prepare.ts now calls publishTemplate(..., { validateOnly: true }) unconditionally (matching database's unconditional rtdb.updateRules(..., { dryRun: true }) check), so expression errors surface before any target's release runs, not just when --dry-run is passed.
  • deployTemplate/publishTemplate gained a validateOnly option that sends ?validateOnly=true to the Remote Config template PUT endpoint (same param name/casing as dataconnect/client.ts's Data Connect Admin API client).

Scenarios Tested

  • npm run mocha -- 'src/deploy/remoteconfig/*.spec.ts' — all 5 passing, including two new cases covering the validateOnly query param and error propagation
  • npx tsc --project tsconfig.compile.json — clean
  • npm run lint:changed-files — 0 errors (pre-existing warnings only)
  • Manually tested against a real Firebase project (via npm link):
    • Valid template + --dry-run: prints remoteconfig: validating template... / remoteconfig: template is valid, then Dry run complete!
    • Template with an invalid condition expression + --dry-run: fails with 400 [VALIDATION_ERROR]: ... Was expecting one of: '(' '!' 'true' 'false' 'app' 'dateTime' 'device' 'percent' 'version'
    • Same broken template against unpatched firebase-tools@15.30.2: prints Dry run complete! with no error, confirming the reported bug

Sample Commands

No command or flag changes. Existing usage is unaffected:

firebase deploy --only remoteconfig --dry-run

now additionally prints, on success:

i  remoteconfig: validating template...
✔  remoteconfig: template is valid

and on an invalid condition expression, fails with a FirebaseError describing the syntax error instead of silently completing.

…ploy

remoteconfig's --dry-run previously performed no server-side validation
at all: the release phase (the only place the real template PUT happens)
is skipped for every target when options.dryRun is true, and the
client-side validateInputRemoteConfigTemplate() only checks etag/conditions
shape, never touching condition expression content. This meant an invalid
percent() condition expression would pass --dry-run silently and only
fail on a real deploy.

database's prepare phase already validates realtime database rules
unconditionally (rtdb.updateRules(..., { dryRun: true })), regardless of
whether the overall deploy is a dry run. This makes prepare.ts call
publishTemplate(..., { validateOnly: true }) the same way, always, so
condition expression errors are caught before any target's release runs
in a multi-target deploy, not just when --dry-run is passed.

deployTemplate/publishTemplate gained a validateOnly option that sends
?validateOnly=true to the Remote Config template PUT endpoint, matching
the parameter name and casing already used by the Data Connect Admin API
client (dataconnect/client.ts).
@google-cla

google-cla Bot commented Sep 20, 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 ensures that Remote Config templates are validated against the Remote Config API's validate_only mode during the prepare phase, preventing invalid condition expression syntax from being silently accepted during dry runs. Feedback suggests utilizing the existing logLabeledBullet and logLabeledSuccess logging utilities from src/utils.ts instead of manually constructing colored labels with colorette, which also allows for the removal of the unused colorette import.

Comment thread src/deploy/remoteconfig/prepare.ts Outdated
Comment on lines +26 to +28
utils.logBullet(clc.bold(clc.cyan("remoteconfig: ")) + "validating template...");
await publishTemplate(projectNumber, template, template.etag, { validateOnly: true });
utils.logSuccess(clc.bold(clc.green("remoteconfig: ")) + "template is valid");

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.

medium

Instead of manually constructing colored labels with colorette, use the existing logging utilities logLabeledBullet and logLabeledSuccess from src/utils.ts. This aligns with the repository's style guide to reuse existing utilities and keeps the logging format consistent across different deploy targets.\n\nYou can also remove the unused import * as clc from "colorette"; at the top of the file.

  utils.logLabeledBullet("remoteconfig", "validating template...");\n  await publishTemplate(projectNumber, template, template.etag, { validateOnly: true });\n  utils.logLabeledSuccess("remoteconfig", "template is valid");
References
  1. Look for existing utilities first: Before writing common helper functions (e.g., for logging, file system operations, promises, string manipulation), check src/utils.ts to see if a suitable function already exists. (link)

- Pass through options.force to the validate-only publishTemplate call in
  prepare.ts, so If-Match semantics stay consistent between the validate-only
  request and the real publish in release.ts.
- Have release.ts pass an explicit { force: options.force } instead of the
  raw Options object, so a stray validateOnly field from a scripted `require
  ("firebase-tools")` caller can't silently turn a real deploy into a
  validate-only no-op.
- Strengthen the validateOnly rejection test to assert on the propagated
  error message, so a regression that swallows the server's validation
  error text would be caught.
- Add nested @PARAM entries for options.force/options.validateOnly to clear
  the jsdoc/check-param-names warnings introduced by the previous commit.
- Tighten the prepare.ts comment (previous wording had a dangling clause)
  and fix the CHANGELOG entry, which said "during dry-run" and used the
  wrong (snake_case) parameter name; validation now runs on every prepare,
  dry-run or not.
Address Gemini Code Assist review feedback: reuse existing logging
helpers instead of manually composing colored labels with colorette,
matching the style used elsewhere in the deploy pipeline.
@Ryu0118
Ryu0118 force-pushed the fix-remoteconfig-dry-run-validation branch from b9c4c27 to eafac84 Compare September 20, 2026 09:17
@Ryu0118
Ryu0118 marked this pull request as ready for review September 20, 2026 09:20
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.

remoteconfig --dry-run does not validate condition expression syntax

2 participants