Skip to content

feat(wb): add built-in concurrently command#601

Open
exKAZUu wants to merge 4 commits intomainfrom
feat/wb-concurrently-command
Open

feat(wb): add built-in concurrently command#601
exKAZUu wants to merge 4 commits intomainfrom
feat/wb-concurrently-command

Conversation

@exKAZUu
Copy link
Member

@exKAZUu exKAZUu commented Mar 3, 2026

Summary

  • add new wb concurrently command to run multiple commands in parallel without external concurrently
  • replace YARN concurrently usage in wb-generated scripts with YARN wb concurrently
  • add tests for concurrent execution behavior (all success, success first, kill-others-on-fail)

Verification

  • yarn workspace @willbooster/wb vitest run test/concurrently.test.ts
  • yarn check-for-ai

exKAZUu and others added 2 commits March 4, 2026 00:22
Co-authored-by: WillBooster (Codex CLI) <agent@willbooster.com>
Co-authored-by: WillBooster (Codex CLI) <agent@willbooster.com>
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, 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 integrates a custom concurrently command directly into the wb CLI, eliminating the dependency on an external concurrently package. This change streamlines command execution within wb projects, ensuring consistent parallel command handling and reducing external tool requirements by internalizing this common functionality.

Highlights

  • New wb concurrently command: Introduced a new wb concurrently command to run multiple shell commands in parallel directly within the wb CLI, eliminating the dependency on an external concurrently package.
  • Integration into wb-generated scripts: Replaced existing calls to the external concurrently package in wb-generated scripts with the new built-in wb concurrently command, standardizing parallel execution.
  • Comprehensive testing: Added comprehensive tests to verify the concurrent execution behavior, covering scenarios for all commands succeeding, success based on the first command, and killing other processes upon failure.

🧠 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
  • packages/wb/src/commands/concurrently.ts
    • Added the concurrentlyCommand module for yargs to define the new command.
    • Implemented the runConcurrently function to manage parallel child processes, including options for killing others on exit/fail and defining success criteria.
    • Included signal handling for graceful termination of child processes.
  • packages/wb/src/index.ts
    • Imported the concurrentlyCommand module.
    • Registered the concurrentlyCommand with the main yargs instance, making it available in the wb CLI.
  • packages/wb/src/scripts/execution/baseScripts.ts
    • Updated startDev method to use YARN wb concurrently.
    • Updated startProduction method to use YARN wb concurrently.
    • Updated testStart method to use YARN wb concurrently.
    • Updated testE2EProtected method to use YARN wb concurrently.
  • packages/wb/src/scripts/execution/httpServerScripts.ts
    • Modified testE2E method to utilize YARN wb concurrently.
  • packages/wb/test/concurrently.test.ts
    • Added a new test file for concurrently command.
    • Included tests for runConcurrently covering successful execution of all commands.
    • Added tests for success based on the first command exiting.
    • Included tests for failure scenarios with kill-others-on-fail.
Activity
  • No specific activity (comments, reviews, or progress updates) has been recorded for 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

このプルリクエストは、外部のconcurrentlyパッケージの代わりに、複数のコマンドを並行して実行するための新しいwb concurrentlyコマンドを追加します。全体的に良い変更ですが、concurrently.tsの実装について、いくつか改善提案があります。シグナルハンドリングのメモリリークの可能性、ロジックの簡略化、エラーハンドリングの改善に関するコメントを確認してください。

Co-authored-by: WillBooster (Codex CLI) <agent@willbooster.com>
@exKAZUu
Copy link
Member Author

exKAZUu commented Mar 3, 2026

/gemini review

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

このプルリクエストでは、外部の concurrently パッケージに依存しない、新しい wb concurrently コマンドが追加されています。これにより、複数のコマンドを並列実行できるようになります。また、既存のスクリプトで YARN concurrently を使用している箇所が、新しい YARN wb concurrently に置き換えられています。全体的に良い変更だと思いますが、concurrently コマンドの --raw オプションについて、1点フィードバックがあります。

Co-authored-by: WillBooster (Codex CLI) <agent@willbooster.com>
@exKAZUu
Copy link
Member Author

exKAZUu commented Mar 5, 2026

/gemini review

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

このプルリクエストでは、外部ツールへの依存を減らすための新しい wb concurrently コマンドが導入されており、素晴らしい追加機能です。しかし、セキュリティの観点から、プロジェクトのスクリプト内での concurrently コマンドの呼び出し方法にコマンドインジェクションの脆弱性があります。特に、BaseScripts および HttpServerScripts の複数のメソッドが、変数を文字列に補間し、二重引用符で囲む際に適切なエスケープ処理を行っていないため、攻撃者がコマンドライン引数に影響を与えることができる場合(例:CI/CD環境)、任意のシェルコマンドを実行される可能性があります。この脆弱性に対処するためには、補間されるすべての変数に対して堅牢なシェルエスケープメカニズムを実装するか、複雑なシェルコマンドを文字列として構築することを完全に避けることを強く推奨します。実装は子プロセスやシグナルの処理など堅牢で、既存のスクリプトも新しいコマンドを使用するように更新されており、主要なシナリオをカバーするテストも追加されていますが、堅牢性とテストの正確性を向上させるための提案もいくつかあります。

Comment on lines +33 to 35
return `YARN wb concurrently --kill-others-on-fail
"${this.startDevProtected(project, argv)}"
"${this.waitAndOpenApp(project)}"`;
Copy link
Contributor

Choose a reason for hiding this comment

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

security-high high

The code constructs shell commands by interpolating variables into strings that are subsequently executed. Specifically, it wraps commands in double quotes but does not escape any double quotes or other shell-sensitive characters that might be present in the variables (e.g., this.startDevProtected(project, argv)). If an attacker can influence these variables—for instance, through command-line arguments like normalizedArgsText or targets—they can break out of the quoted string and execute arbitrary shell commands. This is particularly risky in CI/CD environments where arguments might be derived from untrusted sources such as branch names or PR metadata.

Comment on lines +41 to 43
return `YARN wb concurrently --kill-others-on-fail
"${this.startProductionProtected(project, argv)}"
"${this.waitAndOpenApp(project)}"`;
Copy link
Contributor

Choose a reason for hiding this comment

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

security-high high

Similar to the issue in startDev, the startProduction method constructs a shell command using unescaped variables wrapped in double quotes, leading to potential command injection.

Comment on lines +57 to 59
&& YARN wb concurrently --kill-others-on-fail
"${dockerScripts.stopAndStart(project, argv.normalizedDockerOptionsText ?? '', argv.normalizedArgsText ?? '')}"
"${this.waitAndOpenApp(project)}"`;
Copy link
Contributor

Choose a reason for hiding this comment

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

security-high high

The startDocker method constructs a shell command using unescaped variables wrapped in double quotes, leading to potential command injection.

await checkAndKillPortProcess(project.env.PORT, project);
// Use empty NODE_ENV to avoid "production" mode in some frameworks like Blitz.js.
return `NODE_ENV="" YARN concurrently --kill-others --raw --success first "${this.startDevProtected(project, argv)}" "${this.waitApp(project)}"`;
return `NODE_ENV="" YARN wb concurrently --kill-others --success first "${this.startDevProtected(project, argv)}" "${this.waitApp(project)}"`;
Copy link
Contributor

Choose a reason for hiding this comment

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

security-high high

The testStart method constructs a shell command using unescaped variables wrapped in double quotes, leading to potential command injection.

Comment on lines +109 to 112
return `YARN wb concurrently --kill-others --success first
"${startCommand} && exit 1"
"wait-on -t 600000 -i 2000 http-get://127.0.0.1:${port}
&& ${playwrightCommand}${suffix}"`;
Copy link
Contributor

Choose a reason for hiding this comment

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

security-high high

The testE2EProtected method constructs a shell command using unescaped variables (startCommand, playwrightCommand, suffix) wrapped in double quotes, leading to potential command injection.

Comment on lines +36 to 39
return `YARN wb concurrently --kill-others --success first
"${startCommand} && exit 1"
"wait-on -t 600000 -i 2000 http-get://127.0.0.1:${port}
&& vitest run ${testTarget} --color --passWithNoTests --allowOnly${bailOption}${suffix}"`;
Copy link
Contributor

Choose a reason for hiding this comment

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

security-high high

The testE2EProtected method constructs a shell command using unescaped variables (startCommand, testTarget, bailOption, suffix) wrapped in double quotes, leading to potential command injection.

Comment on lines +64 to +72
const exitCode = await runConcurrently({
commands,
cwd: project.dirPath,
env: project.env,
killOthers: argv.killOthers ?? false,
killOthersOnFail: argv.killOthersOnFail ?? false,
success: argv.success,
});
process.exit(exitCode);
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

現在の実装では、runConcurrentlyが例外をスローした場合(例えば、プロセスの起動に失敗した場合など)、未処理のPromiseリジェクションが発生し、プロセスがクラッシュする可能性があります。堅牢性を高めるために、try...catchブロックでrunConcurrentlyの呼び出しを囲み、エラーを適切にハンドリングして終了コード1でプロセスを終了させることをお勧めします。

    try {
      const exitCode = await runConcurrently({
        commands,
        cwd: project.dirPath,
        env: project.env,
        killOthers: argv.killOthers ?? false,
        killOthersOnFail: argv.killOthersOnFail ?? false,
        success: argv.success,
      });
      process.exit(exitCode);
    } catch (error) {
      console.error(chalk.red(error instanceof Error ? error.message : String(error)));
      process.exit(1);
    }

success: 'all',
});

expect(exitCode).not.toBe(0);
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

テストのアサーションがexpect(exitCode).not.toBe(0)となっていますが、より厳密にすることが可能です。このテストケースでは、最初のコマンドが終了コード1で失敗するため、runConcurrentlyは1を返すことが期待されます。アサーションをexpect(exitCode).toBe(1)のように、具体的な期待される終了コードに変更することで、テストの正確性が向上します。

Suggested change
expect(exitCode).not.toBe(0);
expect(exitCode).toBe(1);

@exKAZUu exKAZUu force-pushed the feat/wb-concurrently-command branch from 98a443a to 85d25bb Compare March 6, 2026 01:32
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