vault/tools/pipeline/internal/pkg/github/copy_pull_request_branch.go
Vault Automation 0c6c13dd38
license: update headers to IBM Corp. (#10229) (#10233)
* license: update headers to IBM Corp.
* `make proto`
* update offset because source file changed

Signed-off-by: Ryan Cragun <me@ryan.ec>
Co-authored-by: Ryan Cragun <me@ryan.ec>
2025-10-21 15:20:20 -06:00

126 lines
3.1 KiB
Go

// Copyright IBM Corp. 2016, 2025
// SPDX-License-Identifier: BUSL-1.1
package github
import (
"errors"
"fmt"
"strconv"
"strings"
)
// copyBranchPrefix is the prefix for copied pull request branches. It is used
// both for copying pull requests and for closing copied pull requests.
const copyBranchPrefix = "copy"
// encodeCopyPullRequestBranch returns the branch name to use for our PR copy operation.
// The branch name is important because we trigger post-merge automation based
// on the branch prefix. We also encode origin PR information for use in
// post-merge operations.
//
// The format is: <copy-branch-prefix>/<owner>/<repo>/<pr>/<pr-branch-name>
// eg: copy/hashicorp/vault/99999/my-feature-branch
//
// This informs the post-merge close operations that the Pull Request was originally
// copied from hashicorp/vault's Pull Request number 99999 and that the branch
// name of the pull request is my-feature-branch.
//
// It's imporant that both the encodeCopyPullRequestBranch and decodeCopyPullRequestBranch
// stay in sync.
func encodeCopyPullRequestBranch(
owner string,
repo string,
number uint,
prBranch string,
) string {
prNumber := strconv.Itoa(int(number))
name := strings.Join([]string{
copyBranchPrefix,
owner,
repo,
prNumber,
prBranch,
}, "/")
if len(name) > 250 {
// Handle Githubs branch name max length
name = name[:250]
}
return name
}
// decodeCopyPullRequestBranch returns the encoded origin PR details from the
// copied Pull Request branch name.
//
// The format must be the same as what is described in encodeCopyPullRequestBranch()
func decodeCopyPullRequestBranch(ref string) (
owner string,
repo string,
number uint,
branch string,
err error,
) {
if ref == "" {
err = errors.New("no copy branch provided")
return owner, repo, number, branch, err
}
if !strings.HasPrefix(ref, copyBranchPrefix) {
err = fmt.Errorf("invalid copy branch: branch does not start with %s", copyBranchPrefix)
return owner, repo, number, branch, err
}
// eg: copy/hashicorp/vault/99999/my-feature-branch
parts := strings.SplitN(ref, "/", 5)
if len(parts) < 5 {
err = fmt.Errorf("invalid copy branch: expected 5 parts, got %d", len(parts))
return owner, repo, number, branch, err
}
owner = parts[1]
repo = parts[2]
var signedNumber int
signedNumber, err = strconv.Atoi(parts[3])
if err != nil {
err = fmt.Errorf("invalid copy branch: pull request number is not a number: %w", err)
return owner, repo, number, branch, err
}
if signedNumber < 0 {
err = fmt.Errorf("invalid copy branch: number must be positive, got %d", signedNumber)
return owner, repo, number, branch, err
}
number = uint(signedNumber)
branch = parts[4]
return owner, repo, number, branch, err
}
func closingIssueRefEqual(a, b *ClosingIssueRef) bool {
if a == nil && b == nil {
return true
}
if (a == nil && b != nil) || (a != nil && b == nil) {
return false
}
if a.URL != b.URL {
return false
}
if a.Number != b.Number {
return false
}
if a.Title != b.Title {
return false
}
if a.Repository.NameWithOwner != b.Repository.NameWithOwner {
return false
}
return true
}