Skip to content

Run Local Builds from the folder App Hosting's preparer picks - #11396

Open
falahat wants to merge 1 commit into
bapi_local_build_sharedfrom
bapi_local_build_monorepo
Open

falahat wants to merge 1 commit into
bapi_local_build_sharedfrom
bapi_local_build_monorepo

Conversation

@falahat

@falahat falahat commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Description

Stacked on #11403. Local Builds always built from the project root with GOOGLE_BUILDABLE=<rootDir>, which fails when the root has no package.json (e.g. an app in web/, or a Turborepo in a subfolder). They now build where #11282's buildDirectory() says: the Nx/Turborepo root, or else the app's folder. App Hosting's rollout sends rootDirectory relative to that folder.

Scenarios Tested

  • Unit tests.
  • Local Builds on Cloud Run and App Hosting: an app in a subfolder and a Turborepo in a subfolder go from ✗ to ✓. Turborepo, Nx, and root apps still deploy.

Sample Commands

# With "rootDir": "web" and "localBuild": true in firebase.json:
firebase deploy --only run:web
firebase deploy --only apphosting:web

@falahat
falahat added this pull request to stack #11267 October 30, 2026 15:36

@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 refactors local build preparation and deployment for App Hosting and Cloud Run by extracting and unifying the buildDirectory helper into a shared utility. This ensures that local builds in monorepos (such as Turborepo or Nx) run from the monorepo root, while other apps build from their own subfolders. The archiving and uploading processes are updated to use the correct build directory rather than the scratch directory root. Feedback on the changes suggests specifying a non-zero exit code ({ exit: 1 }) when throwing a FirebaseError for missing local build properties, in accordance with the repository style guide.

Comment thread src/deploy/apphosting/deploy.ts Outdated
Comment on lines 88 to 90
if (!outputFiles || !localBuildScratchDir || !buildDir) {
throw new FirebaseError(`No local build output files found for ${cfg.backendId}`);
}

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

According to the repository style guide, for expected errors due to a violation of a precondition (such as these required local build properties being undefined), we should specify a non-zero exit code ({ exit: 1 }).

Suggested change
if (!outputFiles || !localBuildScratchDir || !buildDir) {
throw new FirebaseError(`No local build output files found for ${cfg.backendId}`);
}
if (!outputFiles || !localBuildScratchDir || !buildDir) {
throw new FirebaseError("No local build output files found for " + cfg.backendId, { exit: 1 });
}
References
  1. Throw FirebaseError for expected, user-facing errors. If the error is due to a violation of a precondition (e.g. something that is null but should never be), specify a non-zero exit code ({ exit: 1 }). (link)

Local Builds, for both Cloud Run and App Hosting, copied the whole project and always built
from its root with GOOGLE_BUILDABLE set to rootDir. That fails when the project's root has no
package.json, like a self-contained app in a subfolder (firebase.json + functions/ + web/) or
a Turborepo in a subfolder: Universal Maker finds no buildpack group (b/576681181).

Local Builds now use buildDirectory(), the rule that #11282 added for Cloud Run source deploys:
- The scratch copy still has the whole project, so all of its .gitignore files still apply.
- The build runs in the Nx or Turborepo root, with GOOGLE_BUILDABLE set to the app's path, or
  else in the app's own folder. The built app is uploaded from that folder.
- App Hosting's rollout sends rootDirectory relative to that upload, as the API defines it.

buildDirectory() moves to deploy/apphosting/util.ts so that the shared local build code can use
it. Its outside-the-project check now uses the new isInDirectory(), which also handles paths on
another drive.
@falahat
falahat force-pushed the bapi_local_build_monorepo branch from 84ca862 to baeb216 Compare October 30, 2026 21:49
@falahat
falahat removed this pull request from stack #11267 October 30, 2026 22:04
@falahat
falahat changed the base branch from bapi_run_monorepo to bapi_local_build_shared October 30, 2026 22:04
@falahat
falahat added this pull request to stack #11404 October 30, 2026 22:06

This branch has not been deployed

No deployments
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.

1 participant