Skip to content

feat: auto-detect provider/organization/repository from git remote#11

Merged
alerizzo merged 2 commits into
mainfrom
feat/auto-detect-repo
Jun 1, 2026
Merged

feat: auto-detect provider/organization/repository from git remote#11
alerizzo merged 2 commits into
mainfrom
feat/auto-detect-repo

Conversation

@alerizzo
Copy link
Copy Markdown
Collaborator

@alerizzo alerizzo commented Jun 1, 2026

Summary

  • All repository-scoped commands now auto-detect provider, organization, and repository from the origin git remote URL when those arguments are omitted
  • Adds git-remote and resolve-repo-args utilities that parse SSH and HTTPS remote URLs for GitHub, GitLab, and Bitbucket
  • Updates all 11 repo-scoped commands to accept optional positional args with auto-detection fallback, plus corresponding tests
  • Documents the feature in the README with usage examples

Test plan

  • npm test — all new and existing tests pass
  • Inside a GitHub repo: npx ts-node src/index.ts issues auto-detects provider/org/repo
  • Outside a git repo: npx ts-node src/index.ts issues shows a helpful error message
  • Explicit args still work: npx ts-node src/index.ts issues gh my-org my-repo

🤖 Generated with Claude Code

All repository-scoped commands now resolve provider, organization, and
repository from the origin remote URL when those arguments are omitted.
This lets users run e.g. `codacy issues` or `codacy pull-request 42`
inside a git checkout instead of spelling out the full triple every time.

Adds git-remote and resolve-repo-args utilities, updates all 11 commands
to use optional positional arguments with auto-detection fallback, and
documents the feature in the README.

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 1, 2026 15:14
@codacy-production
Copy link
Copy Markdown

codacy-production Bot commented Jun 1, 2026

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 73 complexity · 9 duplication

Metric Results
Complexity 73
Duplication 9

View in Codacy

AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.

Run reviewer

TIP This summary will be updated as you push new changes.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces repository auto-detection from the git remote origin URL, allowing repository-scoped CLI commands to run without explicitly specifying the provider, organization, and repository arguments. It also adds a 'False Positives' section to the issues overview and updates dependencies. The review feedback suggests making the git remote URL parser more robust to support GitLab subgroups and ssh:// prefixes, and safely handling potential undefined values for the new potentialFalsePositives field.

Comment thread src/utils/git-remote.ts Outdated
Comment on lines +15 to +27
const SSH_REGEX = /^git@([^:]+):([^/]+)\/([^/.]+?)(?:\.git)?$/;
const HTTPS_REGEX = /^https?:\/\/([^/]+)\/([^/]+)\/([^/.]+?)(?:\.git)?$/;

export function parseGitRemoteUrl(url: string): RepoContext | null {
const match = url.match(SSH_REGEX) || url.match(HTTPS_REGEX);
if (!match) return null;

const [, host, org, repo] = match;
const provider = HOST_TO_PROVIDER[host];
if (!provider) return null;

return { provider, organization: org, repository: repo };
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current regular expressions for parsing git remote URLs do not support subgroups (e.g., org/subgroup/repo on GitLab) or SSH URLs prefixed with ssh:// (e.g., ssh://git@github.com/org/repo.git).\n\nWe can simplify and make the parser significantly more robust by finding the supported hostnames directly in the URL and splitting the path after the host. This naturally handles subgroups, custom SSH prefixes, and trailing .git suffixes.

export function parseGitRemoteUrl(url: string): RepoContext | null {\n  const host = Object.keys(HOST_TO_PROVIDER).find((h) => url.includes(h));\n  if (!host) return null;\n\n  const provider = HOST_TO_PROVIDER[host];\n  const pathPart = url\n    .slice(url.indexOf(host) + host.length)\n    .replace(/^[:/]+/, '')\n    .replace(/\\.git$/, '');\n\n  const parts = pathPart.split('/');\n  if (parts.length < 2) return null;\n\n  const repo = parts.pop()!;\n  const org = parts.join('/');\n\n  return { provider, organization: org, repository: repo };\n}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — the regexes now support dots in repo names (changed [^/.]+? to [^/]+?), and HTTPS URLs with credentials are handled by stripping the userinfo prefix from the host before provider lookup.

GitLab subgroups (org/subgroup/repo) are out of scope for this PR — the Codacy API takes organization as a single path segment, so subgroup support needs a separate design pass.

🤖 Generated by /pr-fixup command

Comment thread src/commands/issues.ts
Comment on lines +163 to +165
if (counts.authors.length > 0 && counts.potentialFalsePositives.length > 0)
console.log();
printCountTable("False Positives", counts.potentialFalsePositives);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Safely handle potential undefined values for potentialFalsePositives using optional chaining and nullish coalescing.

  if (counts.authors.length > 0 && (counts.potentialFalsePositives?.length ?? 0) > 0)\n    console.log();\n  printCountTable('False Positives', counts.potentialFalsePositives || []);

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The potentialFalsePositives field is part of the IssuesOverviewCounts type returned by the API — if the API doesn't include it, that's a client generation issue. The type check already enforces its presence. No optional chaining needed here.

🤖 Generated by /pr-fixup command

Copy link
Copy Markdown

@codacy-production codacy-production Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

The pull request is currently not up to standards due to a combination of security risks, logic gaps in git remote parsing, and missing implementations. A critical security concern was identified in the use of execSync for shell commands, which is vulnerable to injection. Additionally, the regex patterns for remote parsing do not support GitLab subgroups or repository names containing dots, both of which are common use cases.

While the PR aims to update 11 repository-scoped commands, only 9 are implemented, and the documentation for the repositories command is misleading as the implementation was omitted. There is also undocumented scope creep regarding a 'Potential False Positives' feature and a reference to a non-existent version of lodash (4.18.1). The findings command lacks architectural consistency by not using the new resolveRepoArgs utility, resulting in unnecessarily complex and long code blocks.

About this PR

  • The PR description mentions updating 11 commands to support auto-detection, but the implementation only covers 9 (findings, issue, issues, pattern, patterns, pull-request, repository, tool, tools). Organization-scoped commands like 'repositories' appear to be missing despite documentation updates.

Test suggestions

  • Parse GitHub SSH URL (with and without .git suffix)
  • Parse GitHub HTTPS URL (with and without .git suffix)
  • Parse GitLab and Bitbucket remote URLs
  • Detect repository context using 'git remote get-url origin'
  • Handle errors when git is not available or the host is unknown
  • Auto-detection for commands with 0 additional arguments (e.g., issues)
  • Auto-detection for commands with trailing arguments (e.g., issue )
  • Verification that explicit arguments still take precedence
  • Parse GitLab subgroups (e.g., org/subgroup/repo)
  • Parse repository names containing dots (e.g., my.repo.git)
Prompt proposal for missing tests
Consider implementing these tests if applicable:
1. Parse GitLab subgroups (e.g., org/subgroup/repo)
2. Parse repository names containing dots (e.g., my.repo.git)

TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback

Comment thread src/utils/git-remote.ts Outdated

export function getGitRemoteUrl(remoteName = "origin"): string | null {
try {
return execSync(`git remote get-url ${remoteName}`, {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 HIGH RISK

Using execSync with template strings is susceptible to command injection if remoteName is manipulated. Refactor getGitRemoteUrl to use execFileSync from child_process and pass arguments as an array: ['remote', 'get-url', remoteName].

See Issue in Codacy

Comment thread src/utils/git-remote.ts Outdated
Comment on lines +15 to +16
const SSH_REGEX = /^git@([^:]+):([^/]+)\/([^/.]+?)(?:\.git)?$/;
const HTTPS_REGEX = /^https?:\/\/([^/]+)\/([^/]+)\/([^/.]+?)(?:\.git)?$/;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 HIGH RISK

The regexes for parsing git remotes are too restrictive and will fail for repository names containing dots or GitLab subgroups.

Suggested update: Use ^git@([^:]+):(.+)\/([^/]+?)(?:\.git)?$ for SSH and ^https?:\/\/([^/]+)\/(.+)\/([^/]+?)(?:\.git)?$ for HTTPS.

Comment thread package.json
"date-fns": "4.1.0",
"gitdiff-parser": "0.3.1",
"lodash": "4.17.23",
"lodash": "4.18.1",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 HIGH RISK

Lodash version '4.18.1' was not found in the public registry. This will cause installation failures. Please revert to the latest stable version (4.17.21).

Comment thread README.md Outdated
| `pattern <provider> <org> <repo> <tool> <id>` | Enable, disable, or set parameters for a pattern |

Provider shortcodes: `gh` (GitHub), `gl` (GitLab), `bb` (Bitbucket).
| `repositories [provider] [org]` | List repositories for an organization |
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MEDIUM RISK

The README suggests the repositories command now supports auto-detection, but src/commands/repositories.ts was not modified. Please implement the logic in the command or revert the documentation change.

Comment thread src/commands/findings.ts
Comment on lines 194 to +236
.action(async function (
this: Command,
provider: string,
organization: string,
repository: string | undefined,
providerArg?: string,
organizationArg?: string,
repositoryArg?: string,
) {
try {
checkApiToken();

const argCount = [providerArg, organizationArg, repositoryArg].filter(
(v) => v !== undefined,
).length;
let provider: string;
let organization: string;
let repository: string | undefined;

if (argCount === 3) {
provider = providerArg!;
organization = organizationArg!;
repository = repositoryArg;
} else if (argCount === 2) {
provider = providerArg!;
organization = organizationArg!;
repository = undefined;
} else if (argCount === 0) {
const ctx = detectRepoContext();
console.error(
ansis.dim(
` Using ${ctx.provider} / ${ctx.organization} / ${ctx.repository} (from git remote)`,
),
);
provider = ctx.provider;
organization = ctx.organization;
repository = ctx.repository;
} else {
throw new Error(
"Ambiguous arguments for 'findings'. Expected 0, 2, or 3 positional arguments.\n\n" +
"Usage:\n" +
" codacy findings (auto-detect from git remote)\n" +
" codacy findings <provider> <organization> (organization-wide)\n" +
" codacy findings <provider> <organization> <repository> (repo-specific)",
);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MEDIUM RISK

The action handler for the 'findings' command (102 lines) exceeds the quality threshold. This is caused by manual argument resolution logic that is inconsistent with the 'resolveRepoArgs' utility used elsewhere. Refactor this to use the shared utility to reduce complexity and ensure maintainability.

Comment thread src/commands/issues.ts
tags: Count[];
patterns: PatternsCount[];
authors: Count[];
potentialFalsePositives: Count[];
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚪ LOW RISK

The addition of 'Potential False Positives' to the issues overview is scope creep unrelated to git remote auto-detection. This should be moved to a separate PR or properly documented.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds automatic detection of provider, organization, and repository from the local git origin remote when repo-scoped command positional args are omitted, reducing required CLI arguments when running inside a cloned repository.

Changes:

  • Added git-remote parsing + repo-context detection, plus resolve-repo-args to reconcile optional positional args with auto-detection fallback.
  • Updated multiple repo-scoped commands (and tests) to accept optional positional args and use the new resolver.
  • Documented the feature in README.md and bumped API fetch version / dependencies.

Reviewed changes

Copilot reviewed 25 out of 26 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/utils/resolve-repo-args.ts New utility to resolve positional args with auto-detect fallback.
src/utils/resolve-repo-args.test.ts Tests for argument resolution behavior and error messages.
src/utils/git-remote.ts New git remote URL parsing + context detection from origin.
src/utils/git-remote.test.ts Tests for SSH/HTTPS parsing and detect behavior (mocked execSync).
src/commands/tools.ts Make repo args optional and auto-detect when omitted.
src/commands/tools.test.ts Add coverage for tools command auto-detect path.
src/commands/tool.ts Make repo/tool args optional and auto-detect repo when omitted.
src/commands/tool.test.ts Add coverage for tool command auto-detect path.
src/commands/repository.ts Make repo args optional and auto-detect when omitted.
src/commands/repository.test.ts Add coverage for repository command auto-detect path.
src/commands/pull-request.ts Make repo/pr args optional and auto-detect repo when omitted.
src/commands/pull-request.test.ts Add coverage for pull-request command auto-detect path.
src/commands/patterns.ts Make repo/tool args optional and auto-detect repo when omitted.
src/commands/patterns.test.ts Add coverage for patterns command auto-detect path.
src/commands/pattern.ts Make repo/tool/pattern args optional and auto-detect repo when omitted.
src/commands/pattern.test.ts Add coverage for pattern command auto-detect path.
src/commands/issues.ts Make repo args optional + extend overview output (false positives) and JSON pick list.
src/commands/issues.test.ts Update issues tests for new overview field + auto-detect path.
src/commands/issue.ts Make repo/issue args optional and auto-detect repo when omitted.
src/commands/issue.test.ts Add coverage for issue command auto-detect path.
src/commands/findings.ts Add “0 args => auto-detect” behavior for findings (repo filter).
src/commands/findings.test.ts Add coverage for findings command auto-detect path.
README.md Document repository auto-detection + update command signatures/examples.
package.json Bump API spec fetch version and update lodash dependency.
package-lock.json Lockfile updates for version/dependency bumps.
.changeset/auto-detect-repo-from-git-remote.md Changeset entry for the new feature release.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +18 to +36
const fullCount = 3 + trailingCount;

if (defined.length === fullCount) {
return {
provider: defined[0],
organization: defined[1],
repository: defined[2],
trailingArgs: defined.slice(3),
};
}

if (defined.length === trailingCount && trailingCount > 0) {
const ctx = detectRepoContext();
printAutoDetected(ctx);
return {
...ctx,
trailingArgs: defined,
};
}
Comment thread src/utils/git-remote.ts Outdated
Comment on lines +15 to +16
const SSH_REGEX = /^git@([^:]+):([^/]+)\/([^/.]+?)(?:\.git)?$/;
const HTTPS_REGEX = /^https?:\/\/([^/]+)\/([^/]+)\/([^/.]+?)(?:\.git)?$/;
Comment thread src/utils/git-remote.ts Outdated
Comment on lines +22 to +24
const [, host, org, repo] = match;
const provider = HOST_TO_PROVIDER[host];
if (!provider) return null;
Comment thread src/utils/git-remote.ts
Comment on lines +56 to +59
throw new Error(
`Could not determine provider from git remote URL '${url}'. ` +
`Supported providers: ${supported}.`,
);
Comment thread README.md Outdated
| `pattern <provider> <org> <repo> <tool> <id>` | Enable, disable, or set parameters for a pattern |

Provider shortcodes: `gh` (GitHub), `gl` (GitLab), `bb` (Bitbucket).
| `repositories [provider] [org]` | List repositories for an organization |
Comment thread README.md Outdated
| `issues [provider] [org] [repo]` | Search issues in a repository with filters |
| `issue [provider] [org] [repo] <id>` | Show details for a single issue, or ignore/unignore it |
| `findings [provider] [org] [repo]` | Show security findings for a repository or organization |
| `finding [provider] [org] <id>` | Show details for a single security finding, or ignore/unignore it |
- Replace execSync with execFileSync to eliminate command injection vector
- Support dots in repo names by changing [^/.]+? to [^/]+? in regexes
- Strip userinfo from HTTPS URLs before provider lookup
- Redact credentials in error messages to prevent secret leakage
- Fix README: revert repositories/finding to required args (not updated)
- Add missing potentialFalsePositives to repository.test.ts mocks (CI fix)

Co-Authored-By: Claude <noreply@anthropic.com>
@alerizzo alerizzo merged commit 12ad8a3 into main Jun 1, 2026
4 checks passed
@alerizzo alerizzo deleted the feat/auto-detect-repo branch June 1, 2026 15:39
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