Skip to content

Comments

Fix ci cd flows#1

Merged
jfalava merged 6 commits intomainfrom
fix-ci-cd-flows
Feb 7, 2026
Merged

Fix ci cd flows#1
jfalava merged 6 commits intomainfrom
fix-ci-cd-flows

Conversation

@jfalava
Copy link
Owner

@jfalava jfalava commented Feb 7, 2026

Summary by CodeRabbit

  • New Features

    • Publish and distribute platform-specific CLI packages for Linux x64, macOS ARM64, and Windows x64 for smoother installs.
    • CLI now selects and runs the correct platform binary and reports unsupported platforms clearly.
  • Chores

    • Bumped CLI version to 0.1.2 and adjusted packaging/publishing flow for platform artifacts.
    • Removed legacy native-install helper.
  • Tests

    • Added unit tests covering options, progress formatting, and UI output.
  • Documentation

    • Added platform README notes explaining optional native packages.

@coderabbitai
Copy link

coderabbitai bot commented Feb 7, 2026

Warning

Rate limit exceeded

@jfalava has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 3 minutes and 40 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

Walkthrough

Restructures native binary distribution to platform-specific optional npm packages, removes the postinstall installer, updates the CLI entry resolver to load platform packages dynamically, adds platform packaging artifacts and matrix publish workflow steps, and introduces unit tests for CLI utilities and UI.

Changes

Cohort / File(s) Summary
Platform-specific npm packages
cli/npm/darwin-arm64/package.json, cli/npm/linux-x64/package.json, cli/npm/win32-x64/package.json, cli/npm/darwin-arm64/README.md, cli/npm/linux-x64/README.md, cli/npm/win32-x64/README.md
Added three new npm packages and READMEs for darwin-arm64, linux-x64, win32-x64 binaries with platform constraints, files lists, and publish config.
CLI package manifest
cli/package.json
Bumped version to 0.1.2, removed postinstall script and scripts from files, removed empty dependencies, and added three platform packages under optionalDependencies.
Binary entrypoint resolver
cli/bin/cloudops-tools.js
Replaced ad-hoc postinstall-based resolution with a PLATFORMS map and dynamic resolution via createRequire, added platform validation and clearer error handling and exit codes.
Removed installer script
cli/scripts/install-native.js
Deleted the previous installer that downloaded native binaries from GitHub Releases.
CI: release & publish workflows
.github/workflows/cli-release.yml, .github/workflows/cli-publish.yml
Release workflow now stages platform npm artifacts and uploads them; publish workflow converted to matrix publish-platform-packages (per-platform artifact download, version check, publish) plus dependent publish-main job with tag/version validation and dry-run packaging. Added workflow_dispatch inputs for release context.
Git ignore
.gitignore
Added ignore patterns for cli/npm/*/cloudops-tools and cli/npm/*/cloudops-tools.exe.
Unit tests
cli/test/unit/lib/options.test.ts, cli/test/unit/lib/progress.test.ts, cli/test/unit/lib/ui.test.ts
Added tests for options exports, progress helpers (duration, progress bar, error parsing/formatting), and UI color/format helpers.
Root package deps
package.json
Bumped @typescript/native-preview and typedoc versions.

Sequence Diagram(s)

sequenceDiagram
  participant WF as GitHub Workflow (publish-platform-packages)
  participant Art as Release Run Artifacts
  participant Repo as Checkout (git/release_sha)
  participant Node as Node/npm environment
  participant NPM as npm Registry

  WF->>Art: request artifact (run-id = release_run_id, path per-platform)
  Art-->>WF: return platform artifact
  WF->>Repo: checkout head_sha or release_sha
  WF->>Node: setup Node.js & npm
  WF->>Node: verify package version not published
  alt version not published
    WF->>NPM: npm publish platform artifact
    NPM-->>WF: publish success
  else version exists
    WF-->>WF: skip publish
  end
  WF->>Node: after matrix, run publish-main job (tag/version validation, dry-run)
  Node->>NPM: npm publish main package
  NPM-->>Node: publish result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

You removed the kludgy installer—good.
Packages now know where they should,
Three platforms tidy on the shelf,
CI pushes them from staged-built self.
Userspace intact; don't break the world.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Title check ⚠️ Warning The title 'Fix ci cd flows' is vague and generic, failing to communicate the specific, substantive changes being made to the codebase. Use a descriptive title that captures the main change, such as: 'Add platform-specific CLI npm packages with matrix-driven publishing' or 'Refactor CLI distribution to use optional platform-specific dependencies'
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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
  • Commit unit tests in branch fix-ci-cd-flows

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.

Copy link

@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: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
cli/package.json (1)

14-16: ⚠️ Potential issue | 🟡 Minor

The release workflow handles this correctly, but the npm script is wrong.

The CI/CD pipeline works fine—the workflow properly outputs to cloudops-tools-macos-arm64 and correctly renames it to cloudops-tools when copying to the npm package. The darwin-arm64 package will ship with the right binary name.

However, the build:macOS-arm npm script in cli/package.json (line 15) is misleading. It says:

--outfile dist/cloudops-tools.app

But it should be:

--outfile dist/cloudops-tools

The .app extension is wrong—binaries on macOS don't use that extension (that's for application bundles). If someone runs bun run build:macOS-arm locally, they'll get a file named cloudops-tools.app instead of cloudops-tools, which breaks the consistency with the other platforms and confuses the naming scheme. Fix the npm script to match what the workflow does and what the npm package expects.

🤖 Fix all issues with AI agents
In @.github/workflows/cli-publish.yml:
- Around line 16-22: The job "publish-platform-packages" currently has a
condition using github.event.workflow_run.conclusion which is undefined for
manual runs (workflow_dispatch) causing the job to be skipped; either remove the
workflow_dispatch trigger if manual runs aren't intended, or change the
conditional logic around the if: ${{ github.event.workflow_run.conclusion ==
'success' }} to allow workflow_dispatch (e.g., check event name or allow missing
github.event.workflow_run), and if you keep workflow_dispatch also update
downstream artifact/checkout steps that rely on github.event.workflow_run.id and
github.event.workflow_run.head_sha by adding workflow_dispatch inputs (run
ID/SHA) or an alternate artifact retrieval strategy so manual runs have the
required values.

In @.github/workflows/cli-release.yml:
- Around line 116-121: The release job is downloading and publishing every
artifact (including the npm-${{ matrix.npm_dir }} uploads) causing npm platform
files to appear in the GitHub Release; fix by narrowing what gets downloaded or
what gets published: either change the actions/download-artifact@v4 step in the
release job to use the pattern parameter (e.g. only download artifacts matching
your zip/raw binary names like cloudops-tools-*) or change the
softprops/action-gh-release input glob from artifacts/**/* to a more specific
pattern that excludes npm-* (for example only include artifacts/**/*.zip or
artifacts/**/cloudops-tools-*), updating the steps that reference
actions/download-artifact@v4 and softprops/action-gh-release accordingly.

In `@cli/test/unit/lib/progress.test.ts`:
- Around line 248-291: The test file duplicates the helper functions
parseErrorPayload and formatParsedError multiple times (including inside the
prettifyError block); remove the duplicate declarations and declare a single
shared copy of parseErrorPayload and formatParsedError once at the top of the
describe("progress") block, then have prettifyError and all tests call those
shared helpers instead of redeclaring them.
- Around line 6-319: Your tests define local copies of formatDuration, makeBar,
parseErrorPayload, formatParsedError, and prettifyError so they don't exercise
the real implementations; either export the real helper functions from
progress.ts (e.g., export them as __internal exports: formatDuration, makeBar,
parseErrorPayload, formatParsedError, prettifyError) and import those into
progress.test.ts, or delete the local stubs and instead validate their behavior
by driving the public API startProgressRenderer (call startProgressRenderer and
assert rendered output/side-effects) so the tests exercise the actual code
paths.

In `@cli/test/unit/lib/ui.test.ts`:
- Around line 131-143: The test is relying on a fresh import but the ui module's
colors (the colors constant in ui.ts initialized via
pc.createColors(isColorEnabled())) is cached at first import, so setting
NO_COLOR before a dynamic import in the same process won't change behavior;
update the test to run in isolation: spawn a subprocess (Node/Bun) that sets
process.env.NO_COLOR and then imports "../../../src/ui" and calls ui.info(...)
and returns/prints the result, then assert the subprocess output equals "test".
Alternatively, if you prefer an in-process change, refactor ui.ts to defer color
checks (e.g., call isColorEnabled() inside ui.info or expose a getUi(colors?)
factory) so colors is resolved per-call and update tests to use that API;
reference ui.info, ui.ts, isColorEnabled, and the module-level colors constant
when locating code to change.
🧹 Nitpick comments (6)
cli/test/unit/lib/options.test.ts (2)

63-84: This entire "option types" block is redundant with the "exports" block above.

You literally test the exact same thing twice. The individual tests on lines 7–60 already assert every single one of these keys is toBeDefined(). This block adds zero additional coverage. It's not testing "types" — it's testing the same toBeDefined() with extra steps.

Remove it. Dead test code is still dead code, and it still wastes everyone's time when they read it.

🗑️ Proposed removal
-  describe("option types", () => {
-    test("all options are defined as Effect CLI Options", async () => {
-      const options = await import("../../../src/options");
-      const optionKeys = [
-        "account",
-        "region",
-        "initRegions",
-        "exportFormat",
-        "limitRegions",
-        "debugOption",
-        "describeOption",
-        "skipGlobalOption",
-        "onlyGlobalOption",
-        "modeOption",
-        "servicesOption",
-      ];
-
-      for (const key of optionKeys) {
-        expect(options[key as keyof typeof options]).toBeDefined();
-      }
-    });
-  });

6-60: Consider a data-driven approach instead of 11 copy-paste tests.

Every single test here is structurally identical: import the module, check toBeDefined(). That's fine as an intent, but you don't need to repeat the same boilerplate 11 times. A loop does the job with less noise and is trivially extensible when you add new options.

♻️ Suggested consolidation
   describe("exports", () => {
-    test("exports account option", async () => {
-      const options = await import("../../../src/options");
-      expect(options.account).toBeDefined();
-    });
-
-    test("exports region option", async () => {
-      const options = await import("../../../src/options");
-      expect(options.region).toBeDefined();
-    });
-
-    ... (repeat x11)
-
+    const expectedExports = [
+      "account",
+      "region",
+      "initRegions",
+      "exportFormat",
+      "limitRegions",
+      "debugOption",
+      "describeOption",
+      "skipGlobalOption",
+      "onlyGlobalOption",
+      "modeOption",
+      "servicesOption",
+    ] as const;
+
+    test.each(expectedExports)("exports %s", async (key) => {
+      const options = await import("../../../src/options");
+      expect(options[key as keyof typeof options]).toBeDefined();
+    });
   });
cli/test/unit/lib/ui.test.ts (1)

50-58: The delete process.env calls before await import(...) are no-ops after first import.

Lines 52-53 delete FORCE_COLOR and NO_COLOR before the dynamic import, presumably to ensure a clean color state. But the module is already cached from the "exports" tests above. These deletions affect nothing — picocolors already decided whether to use colors when it was first loaded.

This isn't harmful (the tests still pass because toContain is lenient enough to match through ANSI codes), but it's misleading. Either remove the env manipulation or add a comment acknowledging it's vestigial.

cli/bin/cloudops-tools.js (1)

26-37: The catch swallows the original error — consider logging it for debuggability.

Look, the resolver pattern is correct, createRequire + resolve is exactly how you do this in ESM. But when something goes wrong — and things will go wrong because this is the real world — you're throwing away the actual error. A user files a bug report saying "it told me to install optional dependencies" and you have nothing to debug with. Was it ENOENT? A permissions issue? A corrupted node_modules? You don't know, because you threw the error in the trash.

At minimum, log the original error in a debug/verbose mode, or just tack it on:

Proposed improvement
-} catch {
+} catch (err) {
   console.error(
     `cloudops-tools: could not find package "${platform.pkg}".\n` +
-      "Make sure optional dependencies are installed (do not use --no-optional).",
+      "Make sure optional dependencies are installed (do not use --no-optional).\n" +
+      `Details: ${err.message}`,
   );
   process.exit(1);
 }
.github/workflows/cli-publish.yml (2)

20-22: fail-fast: true means a single platform failure leaves you in a partially-published state.

Think about this scenario: darwin-arm64 publishes successfully, then linux-x64 fails. fail-fast: true cancels win32-x64. Now you have one platform package on npm and two missing. publish-main never runs, so the main CLI package isn't updated — but the darwin-arm64 package IS out there at the new version with no corresponding main package.

You probably want fail-fast: false here so all platforms get their best shot at publishing, and then let publish-main only proceed if all succeeded (which needs already enforces).

Suggested change
     strategy:
-      fail-fast: true
+      fail-fast: false
       matrix:

39-46: node-version: "latest" in a publish workflow is playing with fire.

I don't care if it's "just" a publish step. You do NOT use unpinned, rolling versions in CI that touches your release pipeline. One day Node 24 drops, something breaks in npm's provenance flow, and your release is dead until you figure out why.

Pin to an LTS version. You can update it deliberately and on your schedule, not Node.js's.

Suggested change
       - name: Setup Node.js
         uses: actions/setup-node@v6
         with:
-          node-version: "latest"
+          node-version: "22"
           registry-url: https://registry.npmjs.org

This applies to both jobs (lines 40-43 and 89-92).

Add workflow_dispatch inputs release_run_id and release_sha to allow
manual publish runs to download artifacts and checkout the correct
commit. Make publish job run on manual dispatch or successful
workflow_run. Use inputs.release_sha and inputs.release_run_id as
fallbacks for checkout ref and artifact download run-id. Add artifact
pattern filter in the release workflow.
Copy link

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/cli-publish.yml (1)

84-128: ⚠️ Potential issue | 🟠 Major

publish-main has no "already published" guard — unlike the platform jobs.

You gave the platform packages a nice npm view check (lines 68-77) to skip re-publishing. The main package? It just yeets npm publish and hopes for the best. If this workflow gets re-triggered (manual dispatch, re-run), it'll fail with a 403 "cannot publish over existing version" and you'll be staring at a red CI wondering what went wrong.

Be consistent. Apply the same guard here.

Proposed fix — add version check before publish
+     - name: Check if version already published
+       id: check
+       shell: bash
+       run: |
+         VERSION="$(node -p "require('./cli/package.json').version")"
+         PKG="$(node -p "require('./cli/package.json').name")"
+         if npm view "${PKG}@${VERSION}" version 2>/dev/null; then
+           echo "skip=true" >> "$GITHUB_OUTPUT"
+         else
+           echo "skip=false" >> "$GITHUB_OUTPUT"
+         fi
+
      - name: Publish package
+       if: steps.check.outputs.skip != 'true'
        working-directory: cli
        run: npm publish --access public --provenance
🤖 Fix all issues with AI agents
In @.github/workflows/cli-publish.yml:
- Around line 29-30: The workflow's matrix strategy currently enables fail-fast
(strategy: fail-fast: true), which can cancel remaining publish jobs and cause
partial releases; change the matrix configuration by setting fail-fast to false
(i.e., update the strategy's fail-fast setting in the workflow containing the
matrix/publish jobs) so all matrix publish attempts (e.g., cli-darwin-arm64,
cli-linux-x64, cli-win32-x64) run to completion and let the downstream
publish-main job decide whether to proceed.
- Around line 48-55: The CI is using unpinned versions: change the Setup Node.js
step (uses: actions/setup-node@v6) to set a stable node-version (e.g., replace
node-version: "latest" with node-version: "22" or "lts/*") and stop installing
npm@latest; instead pin the npm install to a specific known version (replace npm
install -g npm@latest with npm install -g npm@<major-or-fixed-version> such as
npm@10) or remove the explicit npm install if your chosen Node image already
provides the required npm; update the "Setup Node.js" and "Ensure npm CLI
supports trusted publishing" steps accordingly.
🧹 Nitpick comments (1)
.github/workflows/cli-publish.yml (1)

106-120: Tag selection is fragile when multiple tags point at HEAD.

git tag --points-at HEAD | head -n 1 picks whichever tag git feels like listing first (alphabetical by default). If someone tags both v1.2.3 and v1.2.3-rc1 on the same commit, you get non-deterministic behavior. That's the kind of thing that works 99 times and then breaks in the one case that matters.

Filter for your expected tag pattern:

Proposed fix
-         TAG="$(git tag --points-at HEAD | head -n 1)"
+         TAG="$(git tag --points-at HEAD | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+' | head -n 1)"

@jfalava
Copy link
Owner Author

jfalava commented Feb 7, 2026

@codex review

@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. Breezy!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@jfalava jfalava merged commit 148d078 into main Feb 7, 2026
1 check passed
This was referenced Feb 18, 2026
Merged
Merged
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