fix line number for bitbucket secrets (#4854)

This commit is contained in:
Shahzad Haider
2026-04-11 00:23:21 +05:00
committed by GitHub
parent c120e8ccba
commit 580628bb9d
2 changed files with 93 additions and 12 deletions
+39 -9
View File
@@ -15,10 +15,11 @@ import (
type provider string
const (
providerGithub provider = "Github"
providerGitlab provider = "Gitlab"
providerBitbucket provider = "Bitbucket"
providerAzure provider = "Azure"
providerGithub provider = "Github"
providerGitlab provider = "Gitlab"
providerBitbucket provider = "Bitbucket"
providerBitbucketServer provider = "BitbucketServer"
providerAzure provider = "Azure"
urlGithub = "github.com/"
urlGitlab = "gitlab.com/"
@@ -36,11 +37,25 @@ func determineProvider(repo string) provider {
return providerBitbucket
case strings.Contains(repo, urlAzure):
return providerAzure
case isBitbucketServerURL(repo):
return providerBitbucketServer
default:
return ""
}
}
// isBitbucketServerURL detects Bitbucket Server/Data Center URLs by their
// distinctive /projects/{KEY}/repos/{SLUG}/... path structure.
// See: https://developer.atlassian.com/server/bitbucket/rest/v1002/intro/#about
// See: https://community.atlassian.com/forums/Bitbucket-questions/Bitbucket-Hyperlinking-to-source-code-in-Bitbucket/qaq-p/618967
func isBitbucketServerURL(rawURL string) bool {
u, err := url.Parse(rawURL)
if err != nil {
return false
}
return strings.Contains(u.Path, "/projects/") && strings.Contains(u.Path, "/repos/")
}
func NormalizeBitbucketRepo(repoURL string) (string, error) {
if !strings.HasPrefix(repoURL, "https") {
return "", errors.New("Bitbucket requires https repo urls: e.g. https://bitbucket.org/org/repo.git")
@@ -127,7 +142,11 @@ func GenerateLink(repo, commit, file string, line int64) string {
switch determineProvider(repo) {
case providerBitbucket:
return repo[:len(repo)-4] + "/commits/" + commit
baseLink := repo[:len(repo)-4] + "/src/" + commit + "/" + file
if line > 0 {
baseLink += "#lines-" + strconv.FormatInt(line, 10)
}
return baseLink
case providerAzure:
// Azure Repos format: ?path=/file&version=GC<commit>&line=N&lineEnd=N+1&lineStartColumn=1
@@ -192,7 +211,10 @@ func GenerateLink(repo, commit, file string, line int64) string {
}
}
var linePattern = regexp.MustCompile(`L\d+`)
var (
linePattern = regexp.MustCompile(`L\d+`)
bbCloudLinePattern = regexp.MustCompile(`lines-\d+(:\d+)?`)
)
// UpdateLinkLineNumber updates the line number in a repository link.
// Used post-link generation to refine reported issue locations within large scanned blocks.
@@ -213,9 +235,17 @@ func UpdateLinkLineNumber(ctx context.Context, link string, newLine int64) strin
switch determineProvider(link) {
case providerBitbucket:
// For Bitbucket, it doesn't support line links (based on the GenerateLink function).
// So we don't need to change anything.
return link
// Bitbucket Cloud uses #lines-N format for source file views.
fragment := "lines-" + strconv.FormatInt(newLine, 10)
if bbCloudLinePattern.MatchString(parsedURL.Fragment) {
parsedURL.Fragment = bbCloudLinePattern.ReplaceAllString(parsedURL.Fragment, fragment)
} else {
parsedURL.Fragment = fragment
}
case providerBitbucketServer:
// Bitbucket Server/Data Center uses a bare line number as fragment: #N
parsedURL.Fragment = strconv.FormatInt(newLine, 10)
case providerAzure:
// For Azure, line numbers use query parameters: ?line=N&lineEnd=N+1&lineStartColumn=1
+54 -3
View File
@@ -171,6 +171,33 @@ func TestGenerateLink(t *testing.T) {
},
want: "https://dev.azure.com/org/project/_git/repo?version=GCabcdef",
},
{
name: "bitbucket cloud link gen",
args: args{
repo: "https://bitbucket.org/org/repo.git",
commit: "abc123",
file: "main.go",
},
want: "https://bitbucket.org/org/repo/src/abc123/main.go",
},
{
name: "bitbucket cloud link gen with line",
args: args{
repo: "https://bitbucket.org/org/repo.git",
commit: "abc123",
file: "main.go",
line: int64(19),
},
want: "https://bitbucket.org/org/repo/src/abc123/main.go#lines-19",
},
{
name: "bitbucket cloud link gen - no file",
args: args{
repo: "https://bitbucket.org/org/repo.git",
commit: "abc123",
},
want: "https://bitbucket.org/org/repo/src/abc123/",
},
{
name: "Unknown provider on-prem instance",
args: args{
@@ -270,12 +297,36 @@ func TestUpdateLinkLineNumber(t *testing.T) {
wantErr bool
}{
{
name: "Update bitbucket, no line number supported",
name: "Update Bitbucket Cloud link with line",
args: args{
link: "https://bitbucket.org/org/repo/blob/xyz123/main.go",
link: "https://bitbucket.org/org/repo/src/xyz123/main.go",
newLine: int64(10),
},
want: "https://bitbucket.org/org/repo/blob/xyz123/main.go",
want: "https://bitbucket.org/org/repo/src/xyz123/main.go#lines-10",
},
{
name: "Update Bitbucket Cloud link - replace existing line",
args: args{
link: "https://bitbucket.org/org/repo/src/xyz123/main.go#lines-5",
newLine: int64(10),
},
want: "https://bitbucket.org/org/repo/src/xyz123/main.go#lines-10",
},
{
name: "Update Bitbucket Server link with line",
args: args{
link: "https://enterprise.example.com/projects/PROJ/repos/repo/browse/main.go?at=xyz123",
newLine: int64(10),
},
want: "https://enterprise.example.com/projects/PROJ/repos/repo/browse/main.go?at=xyz123#10",
},
{
name: "Update Bitbucket Server link - replace existing line",
args: args{
link: "https://enterprise.example.com/projects/PROJ/repos/repo/browse/main.go?at=xyz123#5",
newLine: int64(20),
},
want: "https://enterprise.example.com/projects/PROJ/repos/repo/browse/main.go?at=xyz123#20",
},
{
name: "Update github link with line",