Skip to content

feat: add release archive/restore, sourcemap resolve, proguard uuid#1058

Merged
BYK merged 1 commit into
mainfrom
feat/parity-quick-wins
Jun 3, 2026
Merged

feat: add release archive/restore, sourcemap resolve, proguard uuid#1058
BYK merged 1 commit into
mainfrom
feat/parity-quick-wins

Conversation

@BYK

@BYK BYK commented Jun 3, 2026

Copy link
Copy Markdown
Member

Summary

Parity quick wins toward replacing the legacy Rust sentry-cli (ref #600). Adds three commands whose infrastructure already existed:

  • release archive / release restore — toggle a release's lifecycle status between archived and open via updateRelease({ status }). Archived releases are hidden from the default release list but retained; restore brings them back. Both support --dry-run.
  • sourcemap resolve — read-only diagnostic that reports, per JS file, how its sourcemap resolves (convention <name>.map / external sourceMappingURL / inline data: URL / remote / none) and whether a Sentry debug ID has been injected. Reuses the inject discovery logic and never mutates files. Helps debug why sourcemap upload may not find expected maps.
  • proguard uuid — computes the deterministic ProGuard/R8 mapping UUID. Pure TS via node:crypto, no native deps.

ProGuard UUID — verified against the legacy CLI

The UUID is a content checksum matching rust-proguard's ProguardMapping::uuid():

NAMESPACE = uuidv5(NAMESPACE_DNS, "guardsquare.com")  // 4f44f30f-24be-53d0-bab6-f47c7120ad6c
uuid      = uuidv5(NAMESPACE, <raw file bytes>)

Reproduced byte-for-byte against the legacy sentry-cli integration fixtures (used as golden tests):

  • void\n (5 bytes) → 5db7294d-87fc-5726-a5c0-4a90679657a5
  • sample mapping.txt (155 bytes) → c038584d-c366-570c-ad1e-034fa0d194d7

The variant-nibble encoding uses a string-based approach (no bitwise ops, to satisfy noBitwiseOperators); I verified it is mathematically equivalent to the canonical byte[8] & 0x3f | 0x80 bitmask for all 16 hex digits.

Changes

  • src/lib/api/releases.ts: add status? to updateRelease body type.
  • src/commands/release/{archive,restore}.ts + route wiring.
  • src/commands/sourcemap/resolve.ts + src/lib/sourcemap/inject.ts (resolveDirectorySourcemaps) + route wiring.
  • src/commands/proguard/{uuid,index}.ts + src/lib/proguard.ts + src/app.ts wiring.
  • src/lib/complete.ts: register the new org-positional release archive/restore verbs.
  • Docs fragments (release, sourcemap, new proguard) + regenerated skill references.

Tests

40 new tests (all green); full suite: 7440 passed / 0 failed / 13 skipped.

  • proguard.property.test.ts: golden vectors + properties (well-formed UUIDv5, determinism, content-sensitivity).
  • sourcemap/resolve.test.ts: companion-map detection, inline/remote/missing classification, debug-ID extraction, sort order.
  • release/archive.test.ts: archive/restore status calls, --dry-run, error paths.

Out of scope (tracked separately)

send-envelope is intentionally not revived (deprecated in favor of event send --raw).

Parity quick wins toward replacing the legacy Rust sentry-cli (ref #600):

- release archive/restore: toggle a release's status between archived and
  open via updateRelease({ status }). Hidden from the default list when
  archived; restore brings it back. Both support --dry-run.
- sourcemap resolve: read-only diagnostic reporting how each JS file's
  sourcemap resolves (convention / sourceMappingURL / inline / remote /
  none) and whether a debug ID is injected. Reuses the inject discovery
  logic; never mutates files.
- proguard uuid: compute the deterministic ProGuard/R8 mapping UUID. The
  algorithm (uuidv5(uuidv5(NAMESPACE_DNS, 'guardsquare.com'), bytes)) is
  verified byte-for-byte against the legacy CLI / rust-proguard fixtures
  and implemented in pure TS via node:crypto (no native deps, no bitwise).

Includes golden + property tests, command/skill doc fragments, and the
completion command-set entries for the new org-positional release verbs.

Deferred parity items tracked in #1052 (cron monitors), #1053 (proguard
upload), #1054 (inline base64 sourcemaps), #1055 (niche commands).
@BYK BYK enabled auto-merge (squash) June 3, 2026 14:22
@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://cli.sentry.dev/_preview/pr-1058/

Built to branch gh-pages at 2026-06-03 14:23 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

Comment thread src/lib/proguard.ts Dismissed
Comment thread src/commands/sourcemap/resolve.ts
Comment thread src/commands/release/restore.ts
@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Codecov Results 📊

❌ Patch coverage is 43.07%. Project has 4418 uncovered lines.
❌ Project coverage is 81.84%. Comparing base (base) to head (head).

Files with missing lines (6)
File Patch % Lines
src/commands/sourcemap/resolve.ts 2.78% ⚠️ 35 Missing
src/commands/release/restore.ts 51.85% ⚠️ 13 Missing and 3 partials
src/commands/proguard/uuid.ts 6.25% ⚠️ 15 Missing
src/commands/release/archive.ts 59.26% ⚠️ 11 Missing and 1 partials
src/lib/sourcemap/inject.ts 78.95% ⚠️ 4 Missing and 1 partials
src/lib/proguard.ts 100.00% ⚠️ 1 partials
Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
- Coverage    81.97%    81.84%    -0.13%
==========================================
  Files          334       341        +7
  Lines        24157     24334      +177
  Branches     15807     15908      +101
==========================================
+ Hits         19802     19916      +114
- Misses        4355      4418       +63
- Partials      1659      1664        +5

Generated by Codecov Action

@BYK BYK merged commit 64a836f into main Jun 3, 2026
26 of 27 checks passed
@BYK BYK deleted the feat/parity-quick-wins branch June 3, 2026 14:30
BYK added a commit that referenced this pull request Jun 3, 2026
Follow-up to #1058. The SHA-1 clarifying comment was in a second commit
that didn't make the squashed merge. Adds it to `src/lib/proguard.ts` so
the codebase documents why SHA-1 is used (RFC 4122 §4.3 name-based
UUIDv5, required to match legacy sentry-cli mapping IDs — never for
security). The CodeQL `js/weak-cryptographic-algorithm` alert was
dismissed as a false positive.

Docs/comment-only; no behavior change.
BYK added a commit that referenced this pull request Jun 3, 2026
## Summary

Addresses findings from self-review of #1058 (release archive/restore,
sourcemap resolve, proguard uuid).

### Critical fixes
- **`proguard uuid` + `sourcemap resolve` require `auth: false`** — both
are purely local file operations that never call the Sentry API. Without
this, unauthenticated users get `AuthError` when trying to compute a
UUID or debug sourcemap linkage. Matches the legacy `sentry-cli`
behavior.
- **`sourcemap resolve` JSON leaks absolute filesystem paths** — the
`--json` output included `jsPath` and `mapPath` (absolute paths like
`/home/user/project/dist/app.js`). Now outputs `path` and `mapPath` as
relative paths only. No more `SourcemapResolution` spread in the output
shape.

### Medium fixes
- **`sourcemap resolve` "resolved" count excluded inline/remote
sourcemaps** — files with `//# sourceMappingURL=data:...` (inline) or
`https://...` (remote) were counted as unresolved even though they have
a sourcemap. Now `hasSourcemap()` includes all three types.
- **`updateRelease` status type narrowed** — `status?: string` →
`status?: "open" | "archived"` to prevent invalid values at compile
time.
- **Missing `release restore` error-path tests** — added "throws when no
version provided" and "throws when org cannot be resolved" tests
(archive already had these).

### Low
- Clarified `?? "0"` fallback comment in `proguard.ts` (satisfies
`noUncheckedIndexedAccess`, not dead code).

## Testing
42 targeted tests pass (proguard property, sourcemap resolve, release
archive/restore, completions drift).
Comment thread src/commands/sourcemap/resolve.ts
Comment thread src/lib/sourcemap/inject.ts
Comment thread src/lib/sourcemap/inject.ts
Comment thread src/lib/proguard.ts
Comment thread src/lib/proguard.ts
BYK added a commit that referenced this pull request Jun 4, 2026
## Summary

Follow-up to #1058 that addresses the review threads still **open**
after the
earlier follow-ups (#1059, #1063). Each thread is mapped below.

### Release commands — eliminate the silent `args.join(" ")` defect
(thread [3349270396])

The sentry bot flagged that `release restore 1.0.0 extra` silently joins
extra
positionals into `"1.0.0 extra"`. This `args.join(" ").trim()` pattern
was shared
by **all** release commands, so rather than a one-off guard this fixes
the whole
class:

- All version-only release commands (`archive`, `restore`, `create`,
`delete`,
  `deploys`, `finalize`, `view`, `set-commits`) now declare a single
`kind: "tuple"` positional, so **Stricli enforces arity** — extra args
are
  rejected instead of silently swallowed.
- `release deploy` becomes a 3-positional tuple (`<version>
<environment> [name]`);
multi-word deploy names must be quoted (e.g. `"Deploy #42"`), matching
standard
  CLI conventions and the existing docs example.
- New `resolveReleaseTarget()` helper in `src/commands/release/parse.ts`
centralizes the version-parse + org-resolution + `ContextError`
boilerplate.
- **New GritQL lint rule** `lint-rules/no-args-join-in-release.grit`
bans
`args.join()` in `src/commands/release/` so the anti-pattern cannot
return
  (verified it fires on a reintroduced `args.join`).

### `sourcemap resolve` — single counting loop (thread [3356439786])

Replaced two `files.filter(...)` passes with one `for...of` loop
tallying both
`resolved` and `withDebugId`.

### `sourcemap inject` — remote detection + sort (threads [3356454439],
[3356458605])

- Remote sourcemap detection now uses an anchored `^https?://` regex
instead of
  two `startsWith` checks.
- Path sort uses byte-wise comparison instead of locale-dependent
`localeCompare`
  (matching the plain `.sort()` already used in `upload.ts`).

### `proguard` — precompute namespace bytes (threads [3356471815],
[3356474050])

`uuidV5()` reparsed the hyphenated namespace UUID into bytes on every
call. The
namespace is fixed, so the bytes are now precomputed once at module
load.
**Behavior-preserving** — golden vectors unchanged (`void\n` →
`5db7294d-87fc-5726-a5c0-4a90679657a5`, namespace `4f44f30f-...`).

### Already handled (resolving with notes)

- [3349270382] (resolved-count): the count was fixed in #1063 via
`hasSourcemap()`.
The inject-hint sub-point is a non-issue — `sourcemap inject` adds debug
IDs to
the JS file itself regardless of where its sourcemap lives, so the hint
is correct.
- [3349258944] (CodeQL weak-crypto): already resolved/dismissed via
#1059.

## Testing

- Full unit suite: **7449 passed / 0 failed / 13 skipped**.
- `bun run typecheck`, `bun run lint` (incl. new GritQL rule),
`check:fragments`,
  `check:errors` all green.
- Added `resolveReleaseTarget` unit tests; updated the `release deploy`
and
  `sourcemap resolve` tests for the new signatures.

[3349270396]:
#1058 (comment)
[3356439786]:
#1058 (comment)
[3356454439]:
#1058 (comment)
[3356458605]:
#1058 (comment)
[3356471815]:
#1058 (comment)
[3356474050]:
#1058 (comment)
[3349270382]:
#1058 (comment)
[3349258944]:
#1058 (comment)
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.

2 participants