Skip to content

Fix/apphosting port validation#9937

Open
jayeshpandey01 wants to merge 2 commits intofirebase:mainfrom
jayeshpandey01:fix/apphosting-port-validation
Open

Fix/apphosting port validation#9937
jayeshpandey01 wants to merge 2 commits intofirebase:mainfrom
jayeshpandey01:fix/apphosting-port-validation

Conversation

@jayeshpandey01
Copy link

Fix: Remove restrictive port validation in App Hosting custom start commands

Problem

The App Hosting emulator enforced overly restrictive validation that rejected any custom start command containing --port or -p flags. This validation threw a FirebaseError and prevented legitimate use cases where developers need explicit port control in their custom commands.

Previous behavior:

if (startCommand.includes("--port") || startCommand.includes(" -p ")) {
  throw new FirebaseError(
    "Specifying a port in the start command is not supported by the apphosting emulator",
  );
}

This blanket rejection was problematic for:

  • Framework-specific configurations requiring explicit port binding
  • Custom wrapper scripts that manage port allocation
  • Development workflows where port specification is part of the command chain

Solution

This PR refactors the port handling logic to be more permissive while maintaining intelligent defaults:

1. Removed Restrictive Validation

Eliminated the error-throwing validation that blocked port flags entirely.

2. Conditional Port Injection for Angular CLI

Angular CLI doesn't respect the PORT environment variable, so we conditionally append --port only when not already present:

if (
  startCommand.includes("ng serve") &&
  !startCommand.includes("--port") &&
  !startCommand.includes(" -p ")
) {
  startCommand += ` --port ${port}`;
}

3. Port Mismatch Detection & Warning

Added regex-based port extraction to detect user-specified ports and warn on mismatches:

const portMatch = startCommand.match(/--port[= ](\d+)|-p[= ](\d+)/);
if (portMatch) {
  const userPort = parseInt(portMatch[1] || portMatch[2]);
  if (userPort !== port) {
    logLabeledWarning(
      Emulators.APPHOSTING,
      `Custom start command specifies port ${userPort}, but emulator is using port ${port}. ` +
        `Make sure your command uses the PORT environment variable or matches the emulator port.`,
    );
  }
}

Technical Changes

Modified Files:

  • src/emulator/apphosting/serve.ts - Core port handling logic
  • src/emulator/apphosting/serve.spec.ts - Updated test suite

Key Improvements:

  • Replaced imperative validation with declarative conditional logic
  • Regex pattern matching for port extraction: /--port[= ](\d+)|-p[= ](\d+)/
  • Non-blocking warning system for port mismatches
  • Idempotent port injection for Angular CLI

Testing

Updated test suite to validate new behavior:

it("should allow custom command with port specified and show warning", async () => {
  const startCommand = "npm run dev -- --port 5004";
  await serve.start({ startCommand });
  expect(spawnWithCommandStringStub.getCall(0).args[0]).to.eq(startCommand);
});

it("should not add port to ng serve if already specified", async () => {
  const startCommand = "ng serve --port 5002";
  await serve.start({ startCommand });
  expect(spawnWithCommandStringStub.getCall(0).args[0]).to.eq(startCommand);
});

Test Coverage:

  • ✅ Custom commands with explicit ports are accepted without modification
  • ✅ Angular commands without ports receive automatic --port injection
  • ✅ Angular commands with ports are passed through unchanged
  • ✅ Port mismatch detection triggers appropriate warnings
  • ✅ No regression in existing emulator functionality

Breaking Changes

None. This change is backward compatible and makes the emulator more permissive.

Related Issues

Fixes issues where developers using custom start commands with port specifications were blocked by the emulator.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @jayeshpandey01, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the App Hosting emulator's flexibility by relaxing its port validation rules for custom start commands. Previously, the emulator would reject any command containing explicit port flags, hindering various development setups. The changes now allow users to specify ports in their commands while intelligently handling Angular CLI-specific port requirements and providing helpful warnings for potential port mismatches, ultimately improving the developer experience without introducing breaking changes.

Highlights

  • Removed Restrictive Port Validation: The emulator no longer rejects custom start commands that explicitly specify a port using --port or -p flags, allowing for more flexible development workflows.
  • Conditional Angular CLI Port Injection: For Angular CLI commands (ng serve), the emulator now conditionally injects the --port flag only if it's not already present in the user's command, ensuring Angular applications run on the correct port without overriding user preferences.
  • Port Mismatch Detection and Warning: A new mechanism detects if a user-specified port in a custom command differs from the emulator's assigned port and logs a warning, guiding users to ensure their commands align with the emulator's configuration.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/command.ts
    • Refactored option parsing logic for command definitions using array destructuring.
  • src/emulator/apphosting/serve.spec.ts
    • Removed test case for rejecting custom commands with specified ports.
    • Added test case to verify custom commands with explicit ports are allowed and trigger warnings.
    • Added test case to confirm Angular CLI commands with pre-specified ports are not modified.
  • src/emulator/apphosting/serve.ts
    • Removed the strict validation that previously rejected custom start commands containing port flags.
    • Updated Angular CLI port injection to only append --port if not already present in the command.
    • Implemented regex-based detection for user-specified ports in custom commands.
    • Added a warning mechanism for port mismatches between user commands and the emulator's assigned port.
Activity
  • No human activity has been recorded on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

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

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 effectively addresses the overly restrictive port validation in the App Hosting emulator by removing the error and implementing a more flexible warning system for port mismatches. The changes are logical and well-implemented. I've included a few suggestions to enhance the robustness of the port detection logic and to make the associated tests more comprehensive by asserting the new warning behavior.

@kmcnellis
Copy link
Member

Why is the existing emulator port configuration via firebase.json not sufficient in these cases? https://firebase.google.com/docs/emulator-suite/install_and_configure#port_configuration

@kmcnellis
Copy link
Member

@jayeshpandey01
Copy link
Author

Why is the existing emulator port configuration via firebase.json not sufficient in these cases? https://firebase.google.com/docs/emulator-suite/install_and_configure#port_configuration

The firebase.json port configuration controls the port that the App Hosting emulator listens on, but it does not guarantee that the underlying framework or custom start command will bind to that same port.

In many real-world setups, the start command invokes a framework dev server (e.g. ng serve, npm run dev, or custom Node scripts) that may:

  • Require explicit --port or -p flags
  • Ignore the PORT environment variable
  • Use wrapper scripts that internally hardcode or forward port arguments

For example, Angular CLI does not reliably respect the PORT environment variable and instead expects --port to be explicitly provided. Similarly, custom scripts may forward port flags as part of the command chain. In these cases, configuring the emulator port in firebase.json alone is insufficient to ensure port alignment.

The previous validation blocked legitimate use cases by rejecting any command containing --port or -p, even when explicitly required by the framework. This change makes the emulator more permissive while still:

  • Preserving the configured emulator port
  • Detecting mismatches via regex extraction
  • Emitting a warning when the user-specified port differs from the emulator port
  • Maintaining Angular-specific port injection only when necessary

This approach keeps the emulator configuration authoritative while allowing flexibility for framework-specific requirements and custom workflows.

@jayeshpandey01
Copy link
Author

And https://firebase.google.com/docs/emulator-suite/use_app_hosting#configure_the_start_command_for_angular_apps

Thanks for the question!

The firebase.json port configuration only tells the App Hosting emulator which port to listen on, it doesn’t guarantee that the framework dev server invoked by the custom start command will bind to that same port.

In many cases—especially for Angular apps—framework tools do not reliably respect the PORT environment variable that the emulator sets. The official App Hosting emulator docs explicitly mention configuring the start command for Angular apps to ensure the dev server runs correctly in the emulator environment. For Angular, this often means passing --port explicitly because Angular CLI doesn’t consistently pick up environment variables like PORT on its own. :contentReference[oaicite:0]{index=0}

So:

  • firebase.json configures the emulator’s listening port, but it cannot force every framework or custom script to bind there.
  • Many dev servers (e.g., Angular CLI, custom npm scripts) still require an explicit --port or -p flag or otherwise ignore PORT.
  • The previous restrictive validation prevented legitimate start commands that include port flags, even when those flags are necessary or intended by the developer.
  • Our change makes the emulator permissive, allows explicit ports, and adds warnings when there’s a mismatch between the user-specified port and the emulator port.

This approach aligns with the documented guidance for Angular and other frameworks where the start command may need explicit port configuration, and ensures both the emulator and the framework dev server are correctly aligned without restrictive errors. :contentReference[oaicite:1]{index=1}

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.

3 participants