feat(code-mappings): Add git inference for repo and default branch#3208
feat(code-mappings): Add git inference for repo and default branch#3208
Conversation
|
684caab to
912da39
Compare
fb49d43 to
029aeaf
Compare
912da39 to
95e8814
Compare
|
Please check and resolve the open comments from the AI reviewers, before I do a full review. If any comments are inaccurate or non-actionable, please indicate that with a |
e405066 to
8f9babe
Compare
_#skip-changelog_ Add the `sentry-cli code-mappings upload` subcommand group and the `upload` subcommand with file parsing and validation. This is the first in a stack of 4 PRs to support bulk uploading code mappings from a JSON file — useful for Java/Android multi-module projects that need dozens of mappings. This PR adds: - Command scaffold following the `repos`/`deploys` pattern - JSON file reading and validation (empty arrays, empty stackRoot/sourceRoot) - CLI args: positional `PATH`, `--repo`, `--default-branch` - Help and no-subcommand trycmd integration tests Stack: **#3207** → #3208 → #3209 → #3210 Backend PRs: getsentry/sentry#109783, getsentry/sentry#109785, getsentry/sentry#109786 Closes getsentry/sentry-android-gradle-plugin#1076 Closes getsentry/sentry-android-gradle-plugin#1077 --------- Co-authored-by: Claude Opus 4.6 <[email protected]>
Add a new `code-mappings` subcommand group with an `upload` subcommand that reads and validates a JSON file of code mappings. This is the first step toward CLI support for bulk code mapping uploads to Sentry.
Add descriptive help text explaining what code mappings are and how they work. Replace unwrap with expect for the required path argument. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Automatically detect repository name and default branch from the local git repo when --repo or --default-branch are not provided. Respects SENTRY_VCS_REMOTE config, falling back to best-effort remote detection. Extract find_best_remote() into vcs.rs to deduplicate remote selection logic shared with git_repo_base_repo_name_preserve_case().
When --repo is provided but --default-branch is not, the code no longer requires a git remote to be present. Branch inference gracefully falls back to 'main' when no git repo or remote is available. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Use get_repo_from_remote_preserve_case instead of get_repo_from_remote to avoid lowercasing the repository name, which would cause mismatches with Sentry's case-sensitive API. Co-Authored-By: Claude Opus 4.6 <[email protected]>
70ddd86 to
6dae115
Compare
Replace the deeply nested match with two independent lookups for repo_name and default_branch. Extract resolve_git_remote, infer_repo_name, and infer_default_branch as utility functions. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Duplicate output when values are inferred from git
- Removed println! calls from inference helpers so only the summary lines are printed once.
Or push these changes by commenting:
@cursor push 7a276a79c2
Preview (7a276a79c2)
diff --git a/src/commands/code_mappings/upload.rs b/src/commands/code_mappings/upload.rs
--- a/src/commands/code_mappings/upload.rs
+++ b/src/commands/code_mappings/upload.rs
@@ -123,7 +123,6 @@
if inferred.is_empty() {
bail!("Could not parse repository name from remote URL: {remote_url}");
}
- println!("Inferred repository: {inferred}");
Ok(inferred)
}
@@ -143,6 +142,5 @@
debug!("No git repo or remote available, falling back to 'main'");
"main".to_owned()
});
- println!("Inferred default branch: {inferred}");
inferred
}This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
src/commands/code_mappings/upload.rs
Outdated
| let repo_name = if let Some(r) = explicit_repo { | ||
| r.to_owned() | ||
| } else { | ||
| infer_repo_name(git_repo.as_ref(), remote_name.as_deref())? | ||
| }; | ||
|
|
||
| let default_branch = if let Some(b) = explicit_branch { | ||
| b.to_owned() | ||
| } else { | ||
| infer_default_branch(git_repo.as_ref(), remote_name.as_deref()) | ||
| }; |
There was a problem hiding this comment.
This logic strikes me as a bit weird. If e.g. explicit_repo is Some("repo_name") but explicit_branch is None, on line 81 we would call infer_default_branch with git_repo (the repo inferred by git2), despite the fact that an explicit repo was given. Is that intentional?
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
…po is explicit When --repo is provided but --default-branch is omitted, find the local remote whose URL matches the given repo name and infer the branch from that remote's HEAD. This avoids using an unrelated remote (e.g. a fork) for branch inference. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Refactor resolve_repo_and_branch to accept a pre-opened Repository instead of opening one internally. This allows tests to pass a repo directly without setting GIT_DIR, which was causing flaky failures in unrelated vcs tests running concurrently on Windows CI. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
The tests no longer mutate shared env vars, and the Config binding is mutex-protected, so serial execution is not needed. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
…#3209) _#skip-changelog_ Connect the `code-mappings upload` command to the bulk code mappings API endpoint (`POST /api/0/organizations/{org}/code-mappings/bulk/`). Adds: - `bulk_upload_code_mappings()` method on `AuthenticatedApi` - Request/response data types in `src/api/data_types/code_mappings.rs` - Summary table and error reporting in the command output - Happy-path integration test with mock endpoint Stack: #3207 → #3208 → **#3209** → #3210 Backend PRs: getsentry/sentry#109783, getsentry/sentry#109785, getsentry/sentry#109786 Closes getsentry/sentry-android-gradle-plugin#1079 --------- Co-authored-by: Claude Opus 4.6 <[email protected]>
_#skip-changelog_ Split large mapping files into batches of 300 (the backend limit) per request. Each batch is sent sequentially with progress reporting, and results are merged into a single summary. Also changes the output table to only show error rows — for large uploads (hundreds of mappings), printing every row would flood the terminal. Successful mappings are reflected in the summary counts instead. Stack: #3207 → #3208 → #3209 → **#3210** Backend PRs: getsentry/sentry#109783, getsentry/sentry#109785, getsentry/sentry#109786 --------- Co-authored-by: Claude Opus 4.6 <[email protected]>


#skip-changelog
When
--repoor--default-branchare not provided, infer them from thelocal git repository. Uses the configured VCS remote (SENTRY_VCS_REMOTE / ini)
first, then falls back to best-effort remote detection (upstream > origin > first).
Also extracts
find_best_remote()as a shared utility insrc/utils/vcs.rs,replacing the inline logic that was duplicated in
git_repo_base_repo_name_preserve_case.Stack: #3207 → #3208 → #3209 → #3210
Backend PRs: getsentry/sentry#109783, getsentry/sentry#109785, getsentry/sentry#109786
Closes GRADLE-79