Skip to content

Comments

[Hotfix] Enhance Windows environment detection in BallerinaExtension#1549

Open
axewilledge wants to merge 5 commits intowso2:hotfix/windows-fixfrom
axewilledge:windows-hotfix
Open

[Hotfix] Enhance Windows environment detection in BallerinaExtension#1549
axewilledge wants to merge 5 commits intowso2:hotfix/windows-fixfrom
axewilledge:windows-hotfix

Conversation

@axewilledge
Copy link
Contributor

@axewilledge axewilledge commented Feb 24, 2026

Purpose

Describe the problems, issues, or needs driving this feature/fix and include links to related issues in the following format: Resolves issue1, issue2, etc.
Fixes:
wso2/product-ballerina-integrator#2269
wso2/product-ballerina-integrator#980

Goals

Describe the solutions that this feature/fix will introduce to resolve the problems described above

Approach

Describe how you are implementing the solutions. Include an animated GIF or screenshot if the change affects the UI (email documentation@wso2.com to review all UI text). Include a link to a Markdown file or Google doc if the feature write-up is too long to paste here.

UI Component Development

Specify the reason if following are not followed.

  • Added reusable UI components to the ui-toolkit. Follow the intructions when adding the componenent.
  • Use ui-toolkit components wherever possible. Run npm run storybook from the root directory to view current components.
  • Matches with the native VSCode look and feel.

Manage Icons

Specify the reason if following are not followed.

  • Added Icons to the font-wso2-vscode. Follow the instructions.

User stories

Summary of user stories addressed by this change>

Release note

Brief description of the new feature or bug fix as it will appear in the release notes

Documentation

Link(s) to product documentation that addresses the changes of this PR. If no doc impact, enter “N/A” plus brief explanation of why there’s no doc impact

Training

Link to the PR for changes to the training content in https://github.com/wso2/WSO2-Training, if applicable

Certification

Type “Sent” when you have provided new/updated certification questions, plus four answers for each question (correct answer highlighted in bold), based on this change. Certification questions/answers should be sent to certification@wso2.com and NOT pasted in this PR. If there is no impact on certification exams, type “N/A” and explain why.

Marketing

Link to drafts of marketing content that will describe and promote this feature, including product page changes, technical articles, blog posts, videos, etc., if applicable

Automation tests

  • Unit tests

    Code coverage information

  • Integration tests

    Details about the test cases and coverage

Security checks

Samples

Provide high-level details about the samples related to this feature

Related PRs

List any other related PRs

Migrations (if applicable)

Describe migration steps and platforms on which migration has been tested

Test environment

List all JDK versions, operating systems, databases, and browser/versions on which this feature/fix was tested

Learning

Describe the research phase and any blog posts, patterns, libraries, or add-ons you used to solve the problem.

Summary by CodeRabbit

  • Bug Fixes

    • Improved Windows support for automatically locating the Ballerina binary when not explicitly configured, with enhanced registry and installation directory searching capabilities.
    • Enhanced Windows environment variable handling during version detection to ensure recently installed packages and environment changes are properly detected.
  • Chores

    • Synchronized bn.js package version pinning across dependencies and devDependencies for consistency.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 24, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

PNPM configuration updated to synchronize bn.js version to 5.2.3 across dependencies. Windows-specific fallback mechanism added to locate Ballerina binary via registry and common installation directories, with enhanced environment variable handling and debug logging.

Changes

Cohort / File(s) Summary
PNPM Configuration
common/config/rush/.pnpmfile.cjs
Adds bn.js version pinning to 5.2.3 in both dependencies and devDependencies branches via readPackage hook.
Windows Ballerina Path Discovery
workspaces/ballerina/ballerina-extension/src/core/extension.ts
Introduces Windows-specific fallback logic to locate Ballerina binary via registry PATH entries and common install directories; enhances Windows environment variable handling to merge registry-derived PATH entries; adds debug logging throughout Windows-specific code paths for troubleshooting.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Poem

🐰 A bunny's tail hops with delight,
For Windows paths now shine so bright!
Registry searches, fallbacks so fine,
Ballerina binary found—all in line!
bn.js locked tight at 5.2.3,
Happy hopping through dependencies! 🌟

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description provides issue links in the Purpose section but fails to complete critical sections like Goals, Approach, Security checks, Automation tests, and others required by the repository template. Complete the missing sections: provide Goals describing the solutions, Approach describing implementation details, Security checks responses, Automation tests details, and other relevant template sections before merging.
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: enhancing Windows environment detection in the BallerinaExtension, which aligns with the code modifications shown in the raw summary.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@NipunaRanasinghe
Copy link
Contributor

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 24, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
workspaces/ballerina/ballerina-extension/src/core/extension.ts (1)

2752-2760: Versioned subdirectory picks the first filesystem-order match — may resolve to a stale version.

readdirSync order is non-deterministic. If multiple Ballerina versions exist under a root (e.g., ballerina-2201.8.0 and ballerina-2201.12.0), this could return the older one.

Sort versioned directories in descending order to prefer the latest
         try {
-            const children = fs.readdirSync(root);
+            const children = fs.readdirSync(root)
+                .filter(c => c.toLowerCase().startsWith('ballerina'))
+                .sort()
+                .reverse();
             for (const child of children) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@workspaces/ballerina/ballerina-extension/src/core/extension.ts` around lines
2752 - 2760, The code uses fs.readdirSync(root) and returns the first match,
which can pick a stale Ballerina version; before iterating children, sort the
array of directory names in descending (newest-first) order so the loop in
extension.ts that builds versionedBin (using path.join and checking
fs.existsSync(path.join(versionedBin, 'bal.bat'))) prefers the latest version;
implement a sort on children (e.g., children.sort(...).reverse() or
children.sort((a,b)=> b.localeCompare(a, undefined, {numeric:true,
sensitivity:'base'}))) before the for..of to ensure newest version is chosen.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@workspaces/ballerina/ballerina-extension/src/core/extension.ts`:
- Around line 2780-2792: The PowerShell snippet assigned to command currently
overwrites $e['Path'] with registry-only values ($mp + $up), which drops VS
Code-injected entries when updateProcessEnv later sets process.env.Path; change
the logic in the command construction so that $e['Path'] preserves the existing
process Path ($e['Path']) and prepends or merges the registry Machine/User
values ($mp, $up) into it (avoid simple replacement), ensuring process.env.Path
retains VS Code/internal paths after updateProcessEnv uses the returned
newEnv.Path.

---

Nitpick comments:
In `@workspaces/ballerina/ballerina-extension/src/core/extension.ts`:
- Around line 2752-2760: The code uses fs.readdirSync(root) and returns the
first match, which can pick a stale Ballerina version; before iterating
children, sort the array of directory names in descending (newest-first) order
so the loop in extension.ts that builds versionedBin (using path.join and
checking fs.existsSync(path.join(versionedBin, 'bal.bat'))) prefers the latest
version; implement a sort on children (e.g., children.sort(...).reverse() or
children.sort((a,b)=> b.localeCompare(a, undefined, {numeric:true,
sensitivity:'base'}))) before the for..of to ensure newest version is chosen.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4cb9435 and 58449ee.

📒 Files selected for processing (2)
  • common/config/rush/.pnpmfile.cjs
  • workspaces/ballerina/ballerina-extension/src/core/extension.ts

Comment on lines +2780 to +2792
// Windows: read from registry (Machine + User scopes) so that paths added by
// a fresh Ballerina install (which goes to the User PATH registry key) are
// picked up even when VS Code's process was launched before the installation.
// We start with the current Process environment so that VS Code-internal
// variables are preserved, but we override Path with the merged registry value.
command = 'powershell.exe -NoProfile -Command "' +
'$e=[Environment]::GetEnvironmentVariables(\'Process\');' +
'$mp=[Environment]::GetEnvironmentVariable(\'Path\',\'Machine\');' +
'$up=[Environment]::GetEnvironmentVariable(\'Path\',\'User\');' +
'if($mp -and $up){$e[\'Path\']=$mp+\';\'+$up}' +
'elseif($mp){$e[\'Path\']=$mp}' +
'elseif($up){$e[\'Path\']=$up};' +
'$e | ConvertTo-Json"';
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Overriding Path with registry-only values drops VS Code-internal PATH entries.

The new PowerShell command replaces $e['Path'] with Machine + User from the registry. Any paths that VS Code (or its extension host) injected into the process environment at runtime — for example, its embedded git or node binary directories — will be lost when updateProcessEnv later sets process.env.Path = newEnv.Path.

Consider merging the registry values with the current process PATH instead of replacing it, so that VS Code-internal tooling remains functional:

Proposed fix: merge registry PATH with existing process PATH
             command = 'powershell.exe -NoProfile -Command "' +
                 '$e=[Environment]::GetEnvironmentVariables(\'Process\');' +
                 '$mp=[Environment]::GetEnvironmentVariable(\'Path\',\'Machine\');' +
                 '$up=[Environment]::GetEnvironmentVariable(\'Path\',\'User\');' +
-                'if($mp -and $up){$e[\'Path\']=$mp+\';\'+$up}' +
-                'elseif($mp){$e[\'Path\']=$mp}' +
-                'elseif($up){$e[\'Path\']=$up};' +
+                '$pp=$e[\'Path\'];' +
+                '$merged=@($mp,$up,$pp|Where-Object{$_})-join\';\';' +
+                'if($merged){$e[\'Path\']=$merged};' +
                 '$e | ConvertTo-Json"';

This keeps existing process Path entries (including VS Code-injected ones) while prepending the registry Machine and User values so that freshly-installed tools are found first.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Windows: read from registry (Machine + User scopes) so that paths added by
// a fresh Ballerina install (which goes to the User PATH registry key) are
// picked up even when VS Code's process was launched before the installation.
// We start with the current Process environment so that VS Code-internal
// variables are preserved, but we override Path with the merged registry value.
command = 'powershell.exe -NoProfile -Command "' +
'$e=[Environment]::GetEnvironmentVariables(\'Process\');' +
'$mp=[Environment]::GetEnvironmentVariable(\'Path\',\'Machine\');' +
'$up=[Environment]::GetEnvironmentVariable(\'Path\',\'User\');' +
'if($mp -and $up){$e[\'Path\']=$mp+\';\'+$up}' +
'elseif($mp){$e[\'Path\']=$mp}' +
'elseif($up){$e[\'Path\']=$up};' +
'$e | ConvertTo-Json"';
command = 'powershell.exe -NoProfile -Command "' +
'$e=[Environment]::GetEnvironmentVariables(\'Process\');' +
'$mp=[Environment]::GetEnvironmentVariable(\'Path\',\'Machine\');' +
'$up=[Environment]::GetEnvironmentVariable(\'Path\',\'User\');' +
'$pp=$e[\'Path\'];' +
'$merged=@($mp,$up,$pp|Where-Object{$_})-join\';\';' +
'if($merged){$e[\'Path\']=$merged};' +
'$e | ConvertTo-Json"';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@workspaces/ballerina/ballerina-extension/src/core/extension.ts` around lines
2780 - 2792, The PowerShell snippet assigned to command currently overwrites
$e['Path'] with registry-only values ($mp + $up), which drops VS Code-injected
entries when updateProcessEnv later sets process.env.Path; change the logic in
the command construction so that $e['Path'] preserves the existing process Path
($e['Path']) and prepends or merges the registry Machine/User values ($mp, $up)
into it (avoid simple replacement), ensuring process.env.Path retains VS
Code/internal paths after updateProcessEnv uses the returned newEnv.Path.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Improves Windows-specific Ballerina CLI discovery for the VS Code Ballerina extension, targeting cases where VS Code’s inherited PATH is stale or restricted (per linked BI issues).

Changes:

  • Add a Windows fallback search that locates bal.bat via merged registry PATH and common install directories.
  • Update Windows shell-environment retrieval to merge Machine+User PATH from the registry into the returned env.
  • Pin bn.js to 5.2.3 via Rush/PNPM hooks.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
workspaces/ballerina/ballerina-extension/src/core/extension.ts Adds Windows fallback bin detection and adjusts Windows environment PATH sourcing to use registry values.
common/config/rush/.pnpmfile.cjs Adds a dependency/devDependency override to pin bn.js to a specific version.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1801 to +1805
const detectedBinPath = findWindowsBallerinaPath();
if (detectedBinPath) {
distPath = detectedBinPath;
debug(`[VERSION] Windows fallback search found Ballerina bin: ${distPath}`);
}
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

findWindowsBallerinaPath() can return an absolute bin path under locations like C:\Program Files\.... That distPath is later concatenated into a command string (e.g. distPath + 'bal' + exeExtension) and executed via exec() / cmd.exe /c. Without quoting or switching to execFile/spawn with args, paths containing spaces will fail to execute on Windows. Consider returning a fully-quoted executable path, or (preferably) avoid shell parsing by invoking bal.bat via spawn/execFile with an explicit file path + args.

Copilot uses AI. Check for mistakes.
Comment on lines +1794 to +1804
} else if (isWindows() && !ballerinaHome) {
// On Windows, if syncEnvironment() already merged the User+Machine PATH the
// 'bal.bat version' call below will just work via PATH lookup (distPath stays
// empty). But for restricted environments (where even User
// PATH is locked, or where VSCode's inherited PATH is still stale), we run a
// proactive directory search here so that we can use an absolute path instead
// of relying on PATH resolution.
const detectedBinPath = findWindowsBallerinaPath();
if (detectedBinPath) {
distPath = detectedBinPath;
debug(`[VERSION] Windows fallback search found Ballerina bin: ${distPath}`);
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

This fallback search runs unconditionally whenever isWindows() && !ballerinaHome, even though the comment suggests PATH-based resolution will often already work after syncEnvironment(). Since findWindowsBallerinaPath() does synchronous PowerShell + filesystem scans (up to 10s timeout), consider only running it after the initial bal(.bat) version attempt fails (e.g. ENOENT / "not recognized"), and/or caching the detected result so repeated version checks don’t repeatedly invoke PowerShell.

Copilot uses AI. Check for mistakes.
Comment on lines +2723 to +2726
if (fs.existsSync(candidate)) {
debug(`[WIN_BAL_FIND] Found bal.bat in registry PATH entry: ${entry}`);
return entry + path.sep;
}
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

findWindowsBallerinaPath() returns entry + path.sep when it finds a PATH entry containing bal.bat. If the PATH entry already ends with a separator, this can produce a double separator (e.g. ...\\). It’s safer to normalize before returning (e.g. ensure exactly one trailing separator) so downstream string concatenations produce consistent command paths.

Copilot uses AI. Check for mistakes.
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