Skip to content

Avoid compressing cli files into zip for platform ext#1563

Merged
kaje94 merged 1 commit intorelease/bi-1.8.xfrom
devant-connections-v3
Feb 25, 2026
Merged

Avoid compressing cli files into zip for platform ext#1563
kaje94 merged 1 commit intorelease/bi-1.8.xfrom
devant-connections-v3

Conversation

@kaje94
Copy link
Contributor

@kaje94 kaje94 commented Feb 25, 2026

Purpose

$subject

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

  • Chores

    • Version bumped to 1.0.22
  • Refactor

    • Restructured CLI binary download and caching mechanism to handle each platform individually instead of combined archives
    • Simplified CLI installation readiness check with improved error messages pointing to expected CLI locations

@kaje94 kaje94 requested review from gigara and hevayo as code owners February 25, 2026 09:46
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

📝 Walkthrough

Walkthrough

This pull request refactors the Choreo CLI download and installation process. The configuration declares expected output folders, version is bumped, the download script transitions from combined-zip to per-platform binary extraction with a new CLI_PLATFORMS mapping structure, and the CLI install module is simplified to validate pre-existing binaries rather than handling extraction.

Changes

Cohort / File(s) Summary
Configuration & Version
config/rush-project.json, package.json
Adds output folder declaration to build operation and bumps extension version from 1.0.21 to 1.0.22.
CLI Download Refactoring
scripts/download-choreo-cli.js
Replaces combined-zip approach with per-platform CLI_PLATFORMS mapping; introduces getAssetName(), extractBinary(), and findFile(); restructures download/extract/cache logic to operate per-platform; simplifies cleanup to purge old version directories.
CLI Install Simplification
src/choreo-rpc/cli-install.ts
Removes extraction logic and temporary directory handling; changes to validate pre-existing binaries at resources/choreo-cli/{CLI_VERSION}/{OS}/{ARCH}; throws descriptive error if binary missing; applies minimal permission adjustments (chmod 755 on non-Windows).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 The CLI binaries now hop per-platform, no zips combined,
Each asset extracted neat, in folders aligned,
The installer checks if all's ready to run,
A cleaner approach—refactoring done! 🚀

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is largely incomplete with only a template structure and placeholder content. Critical sections like Purpose, Goals, and Approach contain no substantive information beyond template markers. Fill in all required sections: Purpose (with related issue links), Goals, Approach (with implementation details), and other relevant sections. The '$subject' placeholder must be replaced with actual content.
Docstring Coverage ⚠️ Warning Docstring coverage is 58.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 'Avoid compressing cli files into zip for platform ext' clearly and specifically describes the main change: removing ZIP compression for CLI files in the platform extension.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch devant-connections-v3

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.

@kaje94 kaje94 merged commit 7cd9807 into release/bi-1.8.x Feb 25, 2026
1 of 3 checks passed
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: 2

🧹 Nitpick comments (4)
workspaces/wso2-platform/wso2-platform-extension/scripts/download-choreo-cli.js (4)

263-308: No timeout on HTTPS requests.

downloadFile and httpsRequest don't set socket/request timeouts. If a connection hangs (e.g., network interruption mid-download), the build script will block indefinitely. Since this runs in CI/CD pipelines, a stalled build can be costly.

Example: add a timeout to downloadFile's request
             const req = https.request(requestUrl, {
                 headers: {
                     'User-Agent': 'Choreo-CLI-Downloader',
                     'Accept': 'application/octet-stream',
                     ...getAuthHeaders()
-                }
+                },
+                timeout: 120_000 // 2 minutes
             }, (res) => {

And handle the timeout event:

req.on('timeout', () => {
    req.destroy(new Error('Request timed out'));
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@workspaces/wso2-platform/wso2-platform-extension/scripts/download-choreo-cli.js`
around lines 263 - 308, downloadFile currently never times out, so hanging HTTPS
requests will block CI; update the request logic inside downloadFile (function
downloadFile and its inner makeRequest) to set a request/socket timeout (e.g., a
configurable timeoutMs constant or parameter), attach handlers for timeout
events (req.on('timeout', ...) and/or req.on('socket', socket =>
socket.setTimeout(...))), and on timeout destroy the request (req.destroy(new
Error('Request timed out'))), then call cleanupAndReject with that error so the
file is closed/removed and the Promise rejects; ensure the same timeout handling
is applied for redirected requests in makeRequest and that req.on('error', ...)
still routes errors to cleanupAndReject.

104-179: Sync logic is thorough but checkExistingCLI returning false triggers a full re-download of all platforms.

When the partial-sync path (Lines 148-178) leaves some platforms still missing, returning false causes downloadAndExtractCLI to re-download all platforms — including those already present. Consider passing the stillMissing list to the download function so it only fetches what's actually needed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@workspaces/wso2-platform/wso2-platform-extension/scripts/download-choreo-cli.js`
around lines 104 - 179, checkExistingCLI currently returns false when some
platforms remain missing which forces downloadAndExtractCLI to re-download all
platforms; modify checkExistingCLI to return the list of missing platforms
(stillMissing) or an object { allPresent: boolean, missing: Platform[] } instead
of a boolean, and update callers (e.g., downloadAndExtractCLI) to accept that
missing list and only download those entries; update function references to
checkExistingCLI and any call sites that expect a boolean to handle the new
return shape and pass the missing list into downloadAndExtractCLI so only
stillMissing platforms are fetched.

181-192: Old versions are cleaned up before verifying the new version is available.

cleanupOldFiles runs at Line 431 before checkExistingCLI at Line 434. If the current version's binaries aren't present and the subsequent download fails (network error, rate limit, missing release), the old working version has already been deleted. This leaves no fallback.

This is likely acceptable for CI builds but worth being aware of for local developer workflows.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@workspaces/wso2-platform/wso2-platform-extension/scripts/download-choreo-cli.js`
around lines 181 - 192, cleanupOldFiles currently removes old versions from
CLI_RESOURCES_DIR and CLI_CACHE_DIR before the script verifies the new release
(checkExistingCLI), which can leave no fallback if the download fails; change
the flow so old files are not deleted until the new binary is successfully
verified—either (a) call checkExistingCLI or perform the download+verification
to a temporary dir first, then on success atomically move/rename into place and
only then call cleanupOldFiles, or (b) modify cleanupOldFiles to move existing
entries to a backup location (or keep the latest working version) and remove
backups only after successful installation; reference cleanupOldFiles,
checkExistingCLI, CLI_RESOURCES_DIR and CLI_CACHE_DIR when making the change.

19-25: Platform matrix is missing 32-bit ARM variant.

cli-install.ts's getArchitecture() can return "arm" for 32-bit ARM systems, but CLI_PLATFORMS has no corresponding linux-arm entry. Users on 32-bit ARM Linux will get a "binary not found" error at runtime instead of an "unsupported architecture" error. If the Choreo CLI doesn't publish 32-bit ARM binaries, consider adding an explicit architecture check in getArchitecture() to reject "arm" early with a clear error message.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@workspaces/wso2-platform/wso2-platform-extension/scripts/download-choreo-cli.js`
around lines 19 - 25, CLI_PLATFORCTIONS lacks a linux-arm (32-bit ARM) entry
while getArchitecture() can return "arm", causing a confusing "binary not found"
error; update the code so getArchitecture() explicitly rejects the "arm" return
value with a clear, deterministic error (e.g., throw or return a failure message
stating 32-bit ARM is unsupported) or alternatively add a { assetSuffix:
'linux-arm', os: 'linux', arch: 'arm', ext: 'tar.gz', binary: 'choreo' } entry
to CLI_PLATFORMS if 32-bit ARM binaries are actually published; reference
getArchitecture() and CLI_PLATFORMS when making the change so runtime behavior
is consistent and users see a helpful unsupported-architecture message instead
of a missing-binary error.
🤖 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/wso2-platform/wso2-platform-extension/scripts/download-choreo-cli.js`:
- Around line 390-397: The loop over CLI_PLATFORMS currently logs a warning and
continues when an asset is missing (asset = releaseData.assets?.find(...)),
which allows downloadAndExtractCLI to succeed with missing platform artifacts;
instead, make the check for assetName (using getAssetName) fail fast by throwing
an Error or exiting the process when asset is not found so the build stops and
the extension cannot be produced in a partially broken state. Update the block
that references CLI_PLATFORMS, getAssetName, and releaseData.assets to replace
the console.warn + continue behavior with a thrown error (or process.exit with
non-zero code) including the missing assetName and version to aid debugging.
- Around line 334-363: The unzip invocation in extractBinary is missing the {
stdio: 'inherit' } option so its output/errors are not forwarded like the tar
and PowerShell calls; update the execSync call that runs unzip (the branch
handling platform.ext === '.zip' on non-win32) to pass { stdio: 'inherit' }
(consistent with the tar and powershell calls) so failures and diagnostic output
from extracting archivePath to tmpExtractDir (used by findFile and then copied
to destDir/platform.binary) are visible.

---

Nitpick comments:
In
`@workspaces/wso2-platform/wso2-platform-extension/scripts/download-choreo-cli.js`:
- Around line 263-308: downloadFile currently never times out, so hanging HTTPS
requests will block CI; update the request logic inside downloadFile (function
downloadFile and its inner makeRequest) to set a request/socket timeout (e.g., a
configurable timeoutMs constant or parameter), attach handlers for timeout
events (req.on('timeout', ...) and/or req.on('socket', socket =>
socket.setTimeout(...))), and on timeout destroy the request (req.destroy(new
Error('Request timed out'))), then call cleanupAndReject with that error so the
file is closed/removed and the Promise rejects; ensure the same timeout handling
is applied for redirected requests in makeRequest and that req.on('error', ...)
still routes errors to cleanupAndReject.
- Around line 104-179: checkExistingCLI currently returns false when some
platforms remain missing which forces downloadAndExtractCLI to re-download all
platforms; modify checkExistingCLI to return the list of missing platforms
(stillMissing) or an object { allPresent: boolean, missing: Platform[] } instead
of a boolean, and update callers (e.g., downloadAndExtractCLI) to accept that
missing list and only download those entries; update function references to
checkExistingCLI and any call sites that expect a boolean to handle the new
return shape and pass the missing list into downloadAndExtractCLI so only
stillMissing platforms are fetched.
- Around line 181-192: cleanupOldFiles currently removes old versions from
CLI_RESOURCES_DIR and CLI_CACHE_DIR before the script verifies the new release
(checkExistingCLI), which can leave no fallback if the download fails; change
the flow so old files are not deleted until the new binary is successfully
verified—either (a) call checkExistingCLI or perform the download+verification
to a temporary dir first, then on success atomically move/rename into place and
only then call cleanupOldFiles, or (b) modify cleanupOldFiles to move existing
entries to a backup location (or keep the latest working version) and remove
backups only after successful installation; reference cleanupOldFiles,
checkExistingCLI, CLI_RESOURCES_DIR and CLI_CACHE_DIR when making the change.
- Around line 19-25: CLI_PLATFORCTIONS lacks a linux-arm (32-bit ARM) entry
while getArchitecture() can return "arm", causing a confusing "binary not found"
error; update the code so getArchitecture() explicitly rejects the "arm" return
value with a clear, deterministic error (e.g., throw or return a failure message
stating 32-bit ARM is unsupported) or alternatively add a { assetSuffix:
'linux-arm', os: 'linux', arch: 'arm', ext: 'tar.gz', binary: 'choreo' } entry
to CLI_PLATFORMS if 32-bit ARM binaries are actually published; reference
getArchitecture() and CLI_PLATFORMS when making the change so runtime behavior
is consistent and users see a helpful unsupported-architecture message instead
of a missing-binary error.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f8453f6 and ab734ba.

📒 Files selected for processing (4)
  • workspaces/wso2-platform/wso2-platform-extension/config/rush-project.json
  • workspaces/wso2-platform/wso2-platform-extension/package.json
  • workspaces/wso2-platform/wso2-platform-extension/scripts/download-choreo-cli.js
  • workspaces/wso2-platform/wso2-platform-extension/src/choreo-rpc/cli-install.ts

Comment on lines +334 to 363
function extractBinary(archivePath, platform, destDir) {
ensureDirectoryExists(destDir);
const tmpExtractDir = fs.mkdtempSync(path.join(os.tmpdir(), `choreo-extract-`));

try {
if (platform.ext === '.tar.gz') {
execSync(`tar -xzf '${archivePath}' -C '${tmpExtractDir}'`, { stdio: 'inherit' });
} else if (platform.ext === '.zip') {
if (os.platform() === 'win32') {
execSync(`powershell.exe -Command "Expand-Archive -Path '${archivePath}' -DestinationPath '${tmpExtractDir}' -Force"`, { stdio: 'inherit' });
} else {
execSync(`unzip -q '${archivePath}' -d '${tmpExtractDir}'`);
}
}

// Find the binary recursively (it may be inside a subdirectory)
const binaryPath = findFile(tmpExtractDir, platform.binary);
if (!binaryPath) {
throw new Error(`Binary '${platform.binary}' not found after extracting ${archivePath}`);
}

const destPath = path.join(destDir, platform.binary);
fs.copyFileSync(binaryPath, destPath);
if (platform.binary !== 'choreo.exe') {
fs.chmodSync(destPath, 0o755);
}
console.log(` ✓ Extracted ${platform.os}/${platform.arch} binary`);
} finally {
fs.rmSync(tmpExtractDir, { recursive: true, force: true });
}
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 | 🟡 Minor

Inconsistent stdio option on unzip command.

Line 340 (tar) and Line 343 (powershell) both pass { stdio: 'inherit' }, but Line 345 (unzip) does not. This means extraction errors/output from unzip on macOS/Linux will be silently swallowed. execSync will still throw on a non-zero exit code, but diagnostic output won't be visible.

Proposed fix
-                execSync(`unzip -q '${archivePath}' -d '${tmpExtractDir}'`);
+                execSync(`unzip -q '${archivePath}' -d '${tmpExtractDir}'`, { stdio: 'inherit' });
📝 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
function extractBinary(archivePath, platform, destDir) {
ensureDirectoryExists(destDir);
const tmpExtractDir = fs.mkdtempSync(path.join(os.tmpdir(), `choreo-extract-`));
try {
if (platform.ext === '.tar.gz') {
execSync(`tar -xzf '${archivePath}' -C '${tmpExtractDir}'`, { stdio: 'inherit' });
} else if (platform.ext === '.zip') {
if (os.platform() === 'win32') {
execSync(`powershell.exe -Command "Expand-Archive -Path '${archivePath}' -DestinationPath '${tmpExtractDir}' -Force"`, { stdio: 'inherit' });
} else {
execSync(`unzip -q '${archivePath}' -d '${tmpExtractDir}'`);
}
}
// Find the binary recursively (it may be inside a subdirectory)
const binaryPath = findFile(tmpExtractDir, platform.binary);
if (!binaryPath) {
throw new Error(`Binary '${platform.binary}' not found after extracting ${archivePath}`);
}
const destPath = path.join(destDir, platform.binary);
fs.copyFileSync(binaryPath, destPath);
if (platform.binary !== 'choreo.exe') {
fs.chmodSync(destPath, 0o755);
}
console.log(` ✓ Extracted ${platform.os}/${platform.arch} binary`);
} finally {
fs.rmSync(tmpExtractDir, { recursive: true, force: true });
}
function extractBinary(archivePath, platform, destDir) {
ensureDirectoryExists(destDir);
const tmpExtractDir = fs.mkdtempSync(path.join(os.tmpdir(), `choreo-extract-`));
try {
if (platform.ext === '.tar.gz') {
execSync(`tar -xzf '${archivePath}' -C '${tmpExtractDir}'`, { stdio: 'inherit' });
} else if (platform.ext === '.zip') {
if (os.platform() === 'win32') {
execSync(`powershell.exe -Command "Expand-Archive -Path '${archivePath}' -DestinationPath '${tmpExtractDir}' -Force"`, { stdio: 'inherit' });
} else {
execSync(`unzip -q '${archivePath}' -d '${tmpExtractDir}'`, { stdio: 'inherit' });
}
}
// Find the binary recursively (it may be inside a subdirectory)
const binaryPath = findFile(tmpExtractDir, platform.binary);
if (!binaryPath) {
throw new Error(`Binary '${platform.binary}' not found after extracting ${archivePath}`);
}
const destPath = path.join(destDir, platform.binary);
fs.copyFileSync(binaryPath, destPath);
if (platform.binary !== 'choreo.exe') {
fs.chmodSync(destPath, 0o755);
}
console.log(` ✓ Extracted ${platform.os}/${platform.arch} binary`);
} finally {
fs.rmSync(tmpExtractDir, { recursive: true, force: true });
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@workspaces/wso2-platform/wso2-platform-extension/scripts/download-choreo-cli.js`
around lines 334 - 363, The unzip invocation in extractBinary is missing the {
stdio: 'inherit' } option so its output/errors are not forwarded like the tar
and PowerShell calls; update the execSync call that runs unzip (the branch
handling platform.ext === '.zip' on non-win32) to pass { stdio: 'inherit' }
(consistent with the tar and powershell calls) so failures and diagnostic output
from extracting archivePath to tmpExtractDir (used by findFile and then copied
to destDir/platform.binary) are visible.

Comment on lines +390 to +397
for (const platform of CLI_PLATFORMS) {
const assetName = getAssetName(version, platform);
const asset = releaseData.assets?.find(a => a.name === assetName);

async function downloadAndCombineCLI(version) {
const tempDir = createTempDirectory(`choreo-cli-${version}-`);

try {
// Ensure both directories exist
ensureDirectoryExists(CLI_RESOURCES_DIR);
ensureDirectoryExists(CLI_CACHE_DIR);
if (!asset) {
console.warn(`Warning: Asset not found: ${assetName}`);
continue;
}
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

Missing asset triggers continue — download succeeds partially without error.

If a GitHub release is missing an asset for one platform, the script logs a warning and continues. downloadAndExtractCLI will complete successfully, but the extension package will be broken for that platform. Consider failing the build instead of silently continuing, to avoid shipping an incomplete extension.

Proposed fix — fail fast on missing asset
             if (!asset) {
-                console.warn(`Warning: Asset not found: ${assetName}`);
-                continue;
+                throw new Error(`Required asset not found in release: ${assetName}. Available assets: ${(releaseData.assets || []).map(a => a.name).join(', ')}`);
             }
📝 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
for (const platform of CLI_PLATFORMS) {
const assetName = getAssetName(version, platform);
const asset = releaseData.assets?.find(a => a.name === assetName);
async function downloadAndCombineCLI(version) {
const tempDir = createTempDirectory(`choreo-cli-${version}-`);
try {
// Ensure both directories exist
ensureDirectoryExists(CLI_RESOURCES_DIR);
ensureDirectoryExists(CLI_CACHE_DIR);
if (!asset) {
console.warn(`Warning: Asset not found: ${assetName}`);
continue;
}
for (const platform of CLI_PLATFORMS) {
const assetName = getAssetName(version, platform);
const asset = releaseData.assets?.find(a => a.name === assetName);
if (!asset) {
throw new Error(`Required asset not found in release: ${assetName}. Available assets: ${(releaseData.assets || []).map(a => a.name).join(', ')}`);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@workspaces/wso2-platform/wso2-platform-extension/scripts/download-choreo-cli.js`
around lines 390 - 397, The loop over CLI_PLATFORMS currently logs a warning and
continues when an asset is missing (asset = releaseData.assets?.find(...)),
which allows downloadAndExtractCLI to succeed with missing platform artifacts;
instead, make the check for assetName (using getAssetName) fail fast by throwing
an Error or exiting the process when asset is not found so the build stops and
the extension cannot be produced in a partially broken state. Update the block
that references CLI_PLATFORMS, getAssetName, and releaseData.assets to replace
the console.warn + continue behavior with a thrown error (or process.exit with
non-zero code) including the missing assetName and version to aid debugging.

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