Skip to content

feat: multi-ecosystem shim distribution and CI test coverage#356

Merged
rhuanbarreto merged 19 commits into
mainfrom
feat/multi-ecosystem-shims
May 28, 2026
Merged

feat: multi-ecosystem shim distribution and CI test coverage#356
rhuanbarreto merged 19 commits into
mainfrom
feat/multi-ecosystem-shims

Conversation

@rhuanbarreto

@rhuanbarreto rhuanbarreto commented May 28, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Multi-ecosystem shim distribution — Add platform-native shims for PyPI, NuGet, Go, Maven, and RubyGems alongside the existing npm shim. Each shim downloads the archgate binary from GitHub Releases on first run. Includes publish-shims.yml workflow with Trusted Publishing (OIDC) for RubyGems/NuGet, Central Portal for Maven, and PyPI.
  • CI shim test coverage — Wire all 6 shim test suites (npm, PyPI, Go, Maven, NuGet, RubyGem) into PR validation as independent parallel matrix jobs (fail-fast: false). Previously only PyPI and Go were tested, and the shim change detection was silently broken (shallow checkout missing origin/main).
  • npm shim tests — Refactor archgate.cjs for testability (optional platform params, conditional exports) and add 21 unit tests using Node.js built-in node:test — zero dependencies.
  • Pre-existing NuGet shim bugs fixed.NET 9-only Convert.ToHexStringLower (project targets net8.0), missing using Xunit;, missing InternalsVisibleTo — all caught by the new CI.
  • i18n translation drift rule — New i18n-translation-drift rule in GEN-002 catches when English docs are modified without updating the corresponding locale file in the same changeset.
  • Portuguese installation docs parity — Add missing PyPI, dotnet, Go, RubyGems, and Maven/jbang sections to the pt-br installation page.
  • ADR renameDIST-001ARCH-017 to follow the ARCH numbering convention.
  • Fix flaky mock.module test leakage — Extract pollForAccessToken to auth-poll.ts and credential-store implementation to credential-store-impl.ts with wrapper functions (not live re-exports) to break Bun's process-global ESM binding chain. Live export { X } from "./Y" re-exports are followed through by mock.module, poisoning the source module.

Test plan

  • bun run validate passes locally (lint, typecheck, format, test, ADR check, knip, build)
  • All 29 ADR rules pass
  • 1191 tests pass, 0 failures
  • npm shim: 21 tests via node --test
  • PyPI shim: 12 tests via python -m unittest
  • Go shim: 7 tests via go test
  • Maven shim: 11 tests via mvn test
  • NuGet shim: 5 tests via dotnet test
  • RubyGem shim: 12 tests via bundle exec ruby test/test_shim.rb
  • Shim matrix jobs run independently (fail-fast: false)
  • mock.module leakage fixed — auth-poll.test.ts and credential-store-impl.test.ts get real implementations

rhuanbarreto and others added 2 commits May 28, 2026 16:18
…RubyGems)

Replicate the existing npm thin-shim pattern for five additional package
managers so users can install archgate via their preferred ecosystem.

Each shim is a zero-dependency wrapper that downloads the platform binary
from GitHub Releases on first invocation, verifies SHA256 checksums, and
caches to ~/.archgate/bin/. All shims share the same cache directory.

Changes:
- Relocate npm shim from bin/ to shims/npm/ and add SHA256 verification
- Add PyPI shim (Python 3.8+ stdlib only)
- Add NuGet .NET global tool shim (.NET 8.0)
- Add Go module shim (Go 1.21+ stdlib only)
- Add Maven Central + jbang shim (Java 11+ stdlib only)
- Add RubyGem shim (Ruby 2.7+ stdlib only)
- Extend .simple-release.js to sync versions across all 6 shim packages
- Add publish-shims.yml CI workflow (triggers on release, publishes all)
- Add shim-tests job to code-pull-request.yml (PyPI + Go unit tests)
- Extend ARCH-013 ADR + rules with shim-version-sync enforcement
- Create DIST-001 ADR documenting the multi-ecosystem distribution pattern
- Update installation docs with new package manager instructions

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented May 28, 2026

Copy link
Copy Markdown

Deploying archgate-cli with  Cloudflare Pages  Cloudflare Pages

Latest commit: ebc80b6
Status: ✅  Deploy successful!
Preview URL: https://04af4984.archgate-cli.pages.dev
Branch Preview URL: https://feat-multi-ecosystem-shims.archgate-cli.pages.dev

View logs

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying archgate-cli with  Cloudflare Pages  Cloudflare Pages

Latest commit: ff31931
Status:⚡️  Build in progress...

View logs

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
…Gems and NuGet, migrate Maven to Central Portal

- Rename DIST-001-multi-ecosystem-distribution to ARCH-017 to follow ARCH numbering
- Switch RubyGems publish to OIDC via rubygems/release-gem (removes GEM_HOST_API_KEY secret)
- Switch NuGet publish to OIDC via NuGet/login (removes NUGET_API_KEY secret)
- Replace legacy nexus-staging-maven-plugin (OSSRH sunset) with central-publishing-maven-plugin
- Update actions/setup-java server-id from ossrh to central

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
…lation page

Add PyPI, dotnet, Go, RubyGems, and Maven/jbang install sections to
the pt-br installation page, matching the English version. Also update
the page description and align the editor plugin tip.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
When an English docs file is modified in a changeset, the corresponding
locale file must also be modified. Catches the scenario where the page
exists (passing page-parity) but its content has fallen behind.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
…-drift

Replace sequential await-in-loop with Promise.all for locale file glob.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
…ck.module leakage

auth-poll.test.ts and credential-store.test.ts used await import() to
load modules, which returned mocked versions when login-flow.test.ts
ran in parallel and called mock.module() on the same paths. Static
imports resolve during the module graph phase before any mock.module()
calls execute, giving these tests stable references to the real
implementations.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Run oxfmt on the two modified test files, and remove leftover dynamic
imports in the win32-only skipIf tests in credential-store.test.ts.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
…ck.module leakage

Bun's mock.module() is process-global and retroactive — it replaces live
ESM bindings even for static imports. login-flow.test.ts mocks both
"auth" and "credential-store", causing auth-poll.test.ts and
credential-store.test.ts to receive mocked implementations instead of
real ones when running in the same Bun process.

Fix: extract pollForAccessToken into src/helpers/auth-poll.ts and the
credential-store implementation into src/helpers/credential-store-impl.ts.
Tests import from these new paths which are not targeted by mock.module().
The original modules become thin re-export wrappers for backward compat.

Also ensure all mock.module() calls provide complete export surfaces so
any test file that resolves a mocked module gets callable functions
instead of undefined.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
… mock.module binding chain

Live re-exports (`export { X } from "./Y"`) create ESM bindings that
Bun's mock.module follows through to the source module, replacing the
binding in the implementation file and defeating the extraction strategy.

Replace with wrapper functions that delegate to the impl — these are
their own bindings. Mocking the wrapper module replaces the wrapper,
leaving the impl module's bindings untouched.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
@github-actions

github-actions Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

Code Coverage

Metric Value
Lines 90.0% (6550 / 7278)
Threshold 90% minimum — met
Platforms Linux + Windows

Full HTML report available in workflow artifacts.

Per-directory breakdown
Directory Coverage Lines
src/commands/ 88.1% 2069 / 2348
src/engine/ 93.1% 1207 / 1297
src/formats/ 100.0% 141 / 141
src/helpers/ 89.7% 3133 / 3492

…vailable

The shim-tests job used the default shallow checkout (depth=1) which
does not include origin/main. The git diff to detect shim changes
failed with "fatal: bad revision 'origin/main...HEAD'" — silently
swallowed by || true — causing shim tests to always be skipped on PRs.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
All three shims already had well-written test suites but were not
wired into CI. Only PyPI and Go tests were running on PRs.

- Maven: JUnit 5 via mvn test -B (Java 11, Temurin)
- NuGet: xUnit via dotnet test (.NET 8.0.x)
- RubyGem: Minitest via bundle exec (Ruby 3.3)

All use the same SHA-pinned action versions as publish-shims.yml and
are gated behind the shims_changed detection step.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
The npm shim was the only shim without tests. Refactored archgate.cjs
to accept optional platform/arch params for testability and export
helpers when required as a module (guarded by require.main check).

Tests cover: platform detection (all 3 platforms + unsupported),
binary name, archive extension, cache dir, null-byte stripping,
and SHA-256 checksum verification (pass, mismatch, unavailable).

Uses Node.js built-in test runner (node:test) — zero dependencies,
matching the shim's zero-dependency philosophy.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
…nternal members

Program and its methods are declared internal. Without InternalsVisibleTo,
the test assembly cannot reference Program.GetArtifactName() etc.,
causing a build failure on dotnet test.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Convert.ToHexStringLower was introduced in .NET 9 but the project
targets net8.0. Use Convert.ToHexString().ToLowerInvariant() instead.

Pre-existing bug caught by the newly added CI shim tests.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
The test file used xUnit attributes (Theory, Fact, InlineData, Assert)
without importing the Xunit namespace. Pre-existing bug caught by CI.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Each shim now runs in its own parallel job via a matrix strategy with
fail-fast: false, so a failure in one ecosystem (e.g. NuGet) does not
block or skip tests for the others (Go, Maven, Ruby, etc.).

Architecture:
- shim-changes: lightweight detection job (outputs shims_changed)
- shim-tests: matrix job [npm, pypi, go, maven, nuget, rubygem]
  only runs when shims_changed == true
- status gate: treats skipped shim-tests as success (no shim changes)

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
@rhuanbarreto rhuanbarreto changed the title feat: add multi-ecosystem shim distribution (PyPI, NuGet, Go, Maven, RubyGems) feat: multi-ecosystem shim distribution, CI shim tests, i18n drift detection, and mock.module test isolation May 28, 2026
@rhuanbarreto rhuanbarreto changed the title feat: multi-ecosystem shim distribution, CI shim tests, i18n drift detection, and mock.module test isolation feat: multi-ecosystem shim distribution and CI test coverage May 28, 2026
@rhuanbarreto rhuanbarreto merged commit 3bd562e into main May 28, 2026
51 of 58 checks passed
@rhuanbarreto rhuanbarreto deleted the feat/multi-ecosystem-shims branch May 28, 2026 20:16
@archgatebot archgatebot Bot mentioned this pull request May 28, 2026
rhuanbarreto added a commit to archgate/renovate-config that referenced this pull request May 28, 2026
After the multi-ecosystem shim distribution (archgate/cli#356),
Renovate detects Java/Maven, .NET/NuGet, Python, Go, and Ruby
dependencies but creates individual PRs for each package.

Add packageRules that group all updates per ecosystem into a single
PR with separateMajorMinor disabled, matching the existing docs
dependencies pattern.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
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