Skip to content

handle powershell stripping commas#10288

Open
aalej wants to merge 4 commits intomainfrom
aalej_handle-powershell-commas
Open

handle powershell stripping commas#10288
aalej wants to merge 4 commits intomainfrom
aalej_handle-powershell-commas

Conversation

@aalej
Copy link
Copy Markdown
Contributor

@aalej aalej commented Apr 8, 2026

Description

Fixes #7506

a somewhat more elegant fix compared to #9878 which does replace all

Scenarios Tested

  • Test on an actual windows machine using PowerShell
terminal logs
> firebase emulators:start --only hosting,auth,firestore
i  emulators: Starting emulators: auth, firestore, hosting
i  firestore: Firestore Emulator logging to firestore-debug.log
+  firestore: Firestore Emulator UI websocket is running on 9150.
i  hosting[test-project-721bf]: Serving hosting files from: public
+  hosting[test-project-721bf]: Local server: http://127.0.0.1:5000

┌─────────────────────────────────────────────────────────────┐
│ ✔  All emulators ready! It is now safe to connect your app. │
│ i  View Emulator UI at http://127.0.0.1:4000/               │
└─────────────────────────────────────────────────────────────┘

┌────────────────┬────────────────┬─────────────────────────────────┐
│ Emulator       │ Host:Port      │ View in Emulator UI             │
├────────────────┼────────────────┼─────────────────────────────────┤
│ Authentication │ 127.0.0.1:9099 │ http://127.0.0.1:4000/auth      │
├────────────────┼────────────────┼─────────────────────────────────┤
│ Firestore      │ 127.0.0.1:8080 │ http://127.0.0.1:4000/firestore │
├────────────────┼────────────────┼─────────────────────────────────┤
│ Hosting        │ 127.0.0.1:5000 │ n/a                             │
└────────────────┴────────────────┴─────────────────────────────────┘
  Emulator Hub host: 127.0.0.1 port: 4400
  Other reserved ports: 4500, 9150

Issues? Report them at https://github.com/firebase/firebase-tools/issues and attach the *-debug.log files.

  • Test on an macOS machine to ensure parsing still works
terminal logs
$ firebase emulators:start --only auth,firestore,hosting --project demo-project
i  emulators: Starting emulators: auth, firestore, hosting
i  emulators: Detected demo project ID "demo-project", emulated services will use a demo configuration and attempts to access non-emulated services for this project will fail.
i  firestore: Firestore Emulator logging to firestore-debug.log
✔  firestore: Firestore Emulator UI websocket is running on 9150.
i  hosting[demo-project]: Serving hosting files from: public
✔  hosting[demo-project]: Local server: http://127.0.0.1:5000

┌─────────────────────────────────────────────────────────────┐
│ ✔  All emulators ready! It is now safe to connect your app. │
│ i  View Emulator UI at http://127.0.0.1:4000/               │
└─────────────────────────────────────────────────────────────┘

┌────────────────┬────────────────┬─────────────────────────────────┐
│ Emulator       │ Host:Port      │ View in Emulator UI             │
├────────────────┼────────────────┼─────────────────────────────────┤
│ Authentication │ 127.0.0.1:9099 │ http://127.0.0.1:4000/auth      │
├────────────────┼────────────────┼─────────────────────────────────┤
│ Firestore      │ 127.0.0.1:8080 │ http://127.0.0.1:4000/firestore │
├────────────────┼────────────────┼─────────────────────────────────┤
│ Hosting        │ 127.0.0.1:5000 │ n/a                             │
└────────────────┴────────────────┴─────────────────────────────────┘
  Emulator Hub host: 127.0.0.1 port: 4400
  Other reserved ports: 4500, 9150

Issues? Report them at https://github.com/firebase/firebase-tools/issues and attach the *-debug.log files.
  • Test on a Linux machine to ensure parsing still works

Sample Commands

Copy link
Copy Markdown
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 introduces logic to normalize the 'only' option in the Command class, ensuring that comma-separated values are correctly handled even when PowerShell replaces commas with spaces. The reviewer suggested removing a debugging console.log statement in favor of the project's logger utility, optimizing the retrieval of the 'only' option, and refactoring the added unit tests into a data-driven format to reduce code duplication.

src/command.ts Outdated
Comment on lines +345 to +353
if (getInheritedOption(options, "only")) {
// Handle cases where PowerShell replaces commas with spaces.
// see https://github.com/firebase/firebase-tools/issues/7506
options.only = getInheritedOption(options, "only")
.split(/[\s,]+/)
.filter(Boolean)
.join(",");
console.log(`--- ${options.only}`);
}
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

This debugging console.log statement should be removed. According to the repository's style guide, console.log() should not be used for output. If this logging is necessary for debugging, consider using logger.debug() instead.

Additionally, getInheritedOption(options, "only") is called twice. It would be more efficient and readable to call it once and store the result in a variable.

Suggested change
if (getInheritedOption(options, "only")) {
// Handle cases where PowerShell replaces commas with spaces.
// see https://github.com/firebase/firebase-tools/issues/7506
options.only = getInheritedOption(options, "only")
.split(/[\s,]+/)
.filter(Boolean)
.join(",");
console.log(`--- ${options.only}`);
}
const only = getInheritedOption(options, "only");
if (only) {
// Handle cases where PowerShell replaces commas with spaces.
// see https://github.com/firebase/firebase-tools/issues/7506
options.only = only
.split(/[\s,]+/)
.filter(Boolean)
.join(",");
}
References
  1. Use the central logger (src/logger.ts); never use console.log() for user-facing output. (link)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

good catch! Also, missed that console log

Comment on lines +174 to +226
it("should handle comma separated values in 'only' options", async () => {
const run = command
.action((options) => {
return {
only: options.only,
};
})
.runner();

const result = await run({
only: "firestore,hosting,auth",
});

expect(result).to.deep.eq({
only: "firestore,hosting,auth",
});
});

it("should normalize space separated values in 'only' options", async () => {
const run = command
.action((options) => {
return {
only: options.only,
};
})
.runner();

const result = await run({
only: "firestore hosting auth",
});

expect(result).to.deep.eq({
only: "firestore,hosting,auth",
});
});

it("should normalize space and commas separated values in 'only' options", async () => {
const run = command
.action((options) => {
return {
only: options.only,
};
})
.runner();

const result = await run({
only: "firestore, hosting, auth",
});

expect(result).to.deep.eq({
only: "firestore,hosting,auth",
});
});
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

These tests are great for covering different scenarios for the --only option. However, there's a lot of repeated code. To improve maintainability and make it easier to add new test cases in the future, you could refactor these tests into a data-driven format. This would reduce duplication and make the intent clearer, which aligns with the style guide's emphasis on code quality.

  const testCases = [
    {
      description: "should handle comma separated values in 'only' options",
      input: "firestore,hosting,auth",
    },
    {
      description: "should normalize space separated values in 'only' options",
      input: "firestore hosting auth",
    },
    {
      description: "should normalize space and commas separated values in 'only' options",
      input: "firestore, hosting,  auth",
    },
  ];

  for (const tc of testCases) {
    it(tc.description, async () => {
      const run = command
        .action((options) => {
          return {
            only: options.only,
          };
        })
        .runner();

      const result = await run({
        only: tc.input,
      });

      expect(result).to.deep.eq({
        only: "firestore,hosting,auth",
      });
    });
  }
References
  1. Code should avoid unnecessarily deep nesting or long periods of nesting. Handle edge cases early and exit or fold them into the general case. Consider helper functions that can completely encapsulate branching, e.g. multiple ways a variable can be populated. (link)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think the current tests are a bit more readable compared to this? But, I'm open to changing it if this is better

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.

Handle PowerShell comma behavior for parsing command arguments

2 participants