Merge branch 'trunk' into gh-attestation-download-windows-bug

This commit is contained in:
Meredith Lancaster 2024-12-10 08:25:31 -07:00
commit fb7f2bfea2
14 changed files with 283 additions and 47 deletions

View file

@ -0,0 +1,37 @@
# Set up env vars
env REPO=${SCRIPT_NAME}-${RANDOM_STRING}
# Use gh as a credential helper
exec gh auth setup-git
# Create a repository with a file so it has a default branch
exec gh repo create ${ORG}/${REPO} --add-readme --private
# Defer repo cleanup
defer gh repo delete --yes ${ORG}/${REPO}
# Clone the repo
exec gh repo clone ${ORG}/${REPO}
# Create a branch to act as the merge base branch
cd ${REPO}
exec git checkout -b long-lived-feature-branch
exec git push -u origin long-lived-feature-branch
# Create an issue to develop against
exec gh issue create --title 'Feature Request' --body 'Request Body'
stdout2env ISSUE_URL
# Create a new branch using issue develop with the long lived branch as the base
exec gh issue develop --name 'feature-branch' --base 'long-lived-feature-branch' --checkout ${ISSUE_URL}
# Prepare a PR on the develop branch
exec git commit --allow-empty -m 'Empty Commit'
exec git push -u origin feature-branch
# Create the PR
exec gh pr create --title 'Feature Title' --body 'Feature Body'
# Check the PR is created against the base branch we specified
exec gh pr view --json 'baseRefName' --jq '.baseRefName'
stdout 'long-lived-feature-branch'

View file

@ -0,0 +1,34 @@
# Set up env vars
env REPO=${SCRIPT_NAME}-${RANDOM_STRING}
# Use gh as a credential helper
exec gh auth setup-git
# Create a repository with a file so it has a default branch
exec gh repo create ${ORG}/${REPO} --add-readme --private
# Defer repo cleanup
defer gh repo delete --yes ${ORG}/${REPO}
# Clone the repo
exec gh repo clone ${ORG}/${REPO}
# Create a branch to act as the merge base branch
cd ${REPO}
exec git checkout -b long-lived-feature-branch
exec git push -u origin long-lived-feature-branch
# Prepare a branch from the merge base to PR
exec git checkout -b feature-branch
exec git commit --allow-empty -m 'Empty Commit'
exec git push -u origin feature-branch
# Set the merge-base branch config
exec git config 'branch.feature-branch.gh-merge-base' 'long-lived-feature-branch'
# Create the PR
exec gh pr create --title 'Feature Title' --body 'Feature Body'
# Check the PR is created against the merge base branch
exec gh pr view --json 'baseRefName' --jq '.baseRefName'
stdout 'long-lived-feature-branch'

View file

@ -20,6 +20,9 @@ import (
"github.com/cli/safeexec"
)
// MergeBaseConfig is the configuration setting to keep track of the PR target branch.
const MergeBaseConfig = "gh-merge-base"
var remoteRE = regexp.MustCompile(`(.+)\s+(.+)\s+\((push|fetch)\)`)
// This regexp exists to match lines of the following form:
@ -373,10 +376,10 @@ func (c *Client) lookupCommit(ctx context.Context, sha, format string) ([]byte,
return out, nil
}
// ReadBranchConfig parses the `branch.BRANCH.(remote|merge)` part of git config.
// ReadBranchConfig parses the `branch.BRANCH.(remote|merge|gh-merge-base)` part of git config.
func (c *Client) ReadBranchConfig(ctx context.Context, branch string) (cfg BranchConfig) {
prefix := regexp.QuoteMeta(fmt.Sprintf("branch.%s.", branch))
args := []string{"config", "--get-regexp", fmt.Sprintf("^%s(remote|merge)$", prefix)}
args := []string{"config", "--get-regexp", fmt.Sprintf("^%s(remote|merge|%s)$", prefix, MergeBaseConfig)}
cmd, err := c.Command(ctx, args...)
if err != nil {
return
@ -385,6 +388,8 @@ func (c *Client) ReadBranchConfig(ctx context.Context, branch string) (cfg Branc
if err != nil {
return
}
cfg.LocalName = branch
for _, line := range outputLines(out) {
parts := strings.SplitN(line, " ", 2)
if len(parts) < 2 {
@ -404,11 +409,26 @@ func (c *Client) ReadBranchConfig(ctx context.Context, branch string) (cfg Branc
}
case "merge":
cfg.MergeRef = parts[1]
case MergeBaseConfig:
cfg.MergeBase = parts[1]
}
}
return
}
// SetBranchConfig sets the named value on the given branch.
func (c *Client) SetBranchConfig(ctx context.Context, branch, name, value string) error {
name = fmt.Sprintf("branch.%s.%s", branch, name)
args := []string{"config", name, value}
cmd, err := c.Command(ctx, args...)
if err != nil {
return err
}
// No output expected but check for any printed git error.
_, err = cmd.Output()
return err
}
func (c *Client) DeleteLocalTag(ctx context.Context, tag string) error {
args := []string{"tag", "-d", tag}
cmd, err := c.Command(ctx, args...)

View file

@ -735,9 +735,9 @@ func TestClientReadBranchConfig(t *testing.T) {
}{
{
name: "read branch config",
cmdStdout: "branch.trunk.remote origin\nbranch.trunk.merge refs/heads/trunk",
wantCmdArgs: `path/to/git config --get-regexp ^branch\.trunk\.(remote|merge)$`,
wantBranchConfig: BranchConfig{RemoteName: "origin", MergeRef: "refs/heads/trunk"},
cmdStdout: "branch.trunk.remote origin\nbranch.trunk.merge refs/heads/trunk\nbranch.trunk.gh-merge-base trunk",
wantCmdArgs: `path/to/git config --get-regexp ^branch\.trunk\.(remote|merge|gh-merge-base)$`,
wantBranchConfig: BranchConfig{LocalName: "trunk", RemoteName: "origin", MergeRef: "refs/heads/trunk", MergeBase: "trunk"},
},
}
for _, tt := range tests {

View file

@ -71,7 +71,11 @@ type Commit struct {
}
type BranchConfig struct {
// LocalName of the branch.
LocalName string
RemoteName string
RemoteURL *url.URL
MergeRef string
// MergeBase is the optional base branch to target in a new PR if `--base` is not specified.
MergeBase string
MergeRef string
}

View file

@ -111,6 +111,25 @@ func TestVerifyIntegration(t *testing.T) {
require.Error(t, err)
require.ErrorContains(t, err, "verifying with issuer \"sigstore.dev\"")
})
t.Run("with bundle from OCI registry", func(t *testing.T) {
opts := Options{
APIClient: api.NewLiveClient(hc, host, logger),
ArtifactPath: "oci://ghcr.io/github/artifact-attestations-helm-charts/policy-controller:v0.10.0-github9",
UseBundleFromRegistry: true,
DigestAlgorithm: "sha256",
Logger: logger,
OCIClient: oci.NewLiveClient(),
OIDCIssuer: verification.GitHubOIDCIssuer,
Owner: "github",
PredicateType: verification.SLSAPredicateV1,
SANRegex: "^https://github.com/github/",
SigstoreVerifier: verification.NewLiveSigstoreVerifier(sigstoreConfig),
}
err := runVerify(&opts)
require.NoError(t, err)
})
}
func TestVerifyIntegrationCustomIssuer(t *testing.T) {

View file

@ -59,10 +59,18 @@ func NewCmdBrowse(f *cmdutil.Factory, runF func(*BrowseOptions) error) *cobra.Co
}
cmd := &cobra.Command{
Long: "Open the GitHub repository in the web browser.",
Short: "Open the repository in the browser",
Use: "browse [<number> | <path> | <commit-SHA>]",
Args: cobra.MaximumNArgs(1),
Short: "Open repositories, issues, pull requests, and more in the browser",
Long: heredoc.Doc(`
Transition from the terminal to the web browser to view and interact with:
- Issues
- Pull requests
- Repository content
- Repository home page
- Repository settings
`),
Use: "browse [<number> | <path> | <commit-SHA>]",
Args: cobra.MaximumNArgs(1),
Example: heredoc.Doc(`
$ gh browse
#=> Open the home page of the current repository

View file

@ -44,6 +44,13 @@ func NewCmdDevelop(f *cmdutil.Factory, runF func(*DevelopOptions) error) *cobra.
cmd := &cobra.Command{
Use: "develop {<number> | <url>}",
Short: "Manage linked branches for an issue",
Long: heredoc.Docf(`
Manage linked branches for an issue.
When using the %[1]s--base%[1]s flag, the new development branch will be created from the specified
remote branch. The new branch will be configured as the base branch for pull requests created using
%[1]sgh pr create%[1]s.
`, "`"),
Example: heredoc.Doc(`
# List branches for issue 123
$ gh issue develop --list 123
@ -171,6 +178,14 @@ func developRunCreate(opts *DevelopOptions, apiClient *api.Client, issueRepo ghr
return err
}
// Remember which branch to target when creating a PR.
if opts.BaseBranch != "" {
err = opts.GitClient.SetBranchConfig(ctx.Background(), branchName, git.MergeBaseConfig, opts.BaseBranch)
if err != nil {
return err
}
}
fmt.Fprintf(opts.IO.Out, "%s/%s/tree/%s\n", branchRepo.RepoHost(), ghrepo.FullName(branchRepo), branchName)
return checkoutBranch(opts, branchRepo, branchName)

View file

@ -399,6 +399,7 @@ func TestDevelopRun(t *testing.T) {
},
runStubs: func(cs *run.CommandStubber) {
cs.Register(`git fetch origin \+refs/heads/my-branch:refs/remotes/origin/my-branch`, 0, "")
cs.Register(`git config branch\.my-branch\.gh-merge-base main`, 0, "")
},
expectedOut: "github.com/OWNER/REPO/tree/my-branch\n",
},

View file

@ -77,6 +77,10 @@ func NewCmdChecks(f *cmdutil.Factory, runF func(*ChecksOptions) error) *cobra.Co
RunE: func(cmd *cobra.Command, args []string) error {
opts.Finder = shared.NewFinder(f)
if opts.Exporter != nil && opts.Watch {
return cmdutil.FlagErrorf("cannot use `--watch` with `--json` flag")
}
if repoOverride, _ := cmd.Flags().GetString("repo"); repoOverride != "" && len(args) == 0 {
return cmdutil.FlagErrorf("argument required when using the `--repo` flag")
}

View file

@ -78,6 +78,11 @@ func TestNewCmdChecks(t *testing.T) {
cli: "--fail-fast",
wantsError: "cannot use `--fail-fast` flag without `--watch` flag",
},
{
name: "watch with json flag",
cli: "--watch --json workflow",
wantsError: "cannot use `--watch` with `--json` flag",
},
{
name: "required flag",
cli: "--required",
@ -171,7 +176,7 @@ func Test_checksRun(t *testing.T) {
wantOut: heredoc.Doc(`
Some checks were not successful
0 cancelled, 1 failing, 1 successful, 0 skipped, and 1 pending checks
NAME DESCRIPTION ELAPSED URL
X sad tests 1m26s sweet link
cool tests 1m26s sweet link
@ -191,7 +196,7 @@ func Test_checksRun(t *testing.T) {
wantOut: heredoc.Doc(`
Some checks were cancelled
1 cancelled, 0 failing, 2 successful, 0 skipped, and 0 pending checks
NAME DESCRIPTION ELAPSED URL
cool tests 1m26s sweet link
- sad tests 1m26s sweet link
@ -211,7 +216,7 @@ func Test_checksRun(t *testing.T) {
wantOut: heredoc.Doc(`
Some checks are still pending
1 cancelled, 0 failing, 2 successful, 0 skipped, and 1 pending checks
NAME DESCRIPTION ELAPSED URL
cool tests 1m26s sweet link
rad tests 1m26s sweet link
@ -232,7 +237,7 @@ func Test_checksRun(t *testing.T) {
wantOut: heredoc.Doc(`
All checks were successful
0 cancelled, 0 failing, 3 successful, 0 skipped, and 0 pending checks
NAME DESCRIPTION ELAPSED URL
awesome tests 1m26s sweet link
cool tests 1m26s sweet link
@ -253,7 +258,7 @@ func Test_checksRun(t *testing.T) {
wantOut: heredoc.Docf(`
%[1]s[?1049hAll checks were successful
0 cancelled, 0 failing, 3 successful, 0 skipped, and 0 pending checks
NAME DESCRIPTION ELAPSED URL
awesome tests 1m26s sweet link
cool tests 1m26s sweet link
@ -281,17 +286,17 @@ func Test_checksRun(t *testing.T) {
},
wantOut: heredoc.Docf(`
%[1]s[?1049h%[1]s[0;0H%[1]s[JRefreshing checks status every 0 seconds. Press Ctrl+C to quit.
Some checks were not successful
0 cancelled, 1 failing, 1 successful, 0 skipped, and 1 pending checks
NAME DESCRIPTION ELAPSED URL
X sad tests 1m26s sweet link
cool tests 1m26s sweet link
* slow tests 1m26s sweet link
%[1]s[?1049lSome checks were not successful
0 cancelled, 1 failing, 1 successful, 0 skipped, and 1 pending checks
NAME DESCRIPTION ELAPSED URL
X sad tests 1m26s sweet link
cool tests 1m26s sweet link
@ -311,7 +316,7 @@ func Test_checksRun(t *testing.T) {
wantOut: heredoc.Doc(`
Some checks were not successful
0 cancelled, 1 failing, 2 successful, 0 skipped, and 0 pending checks
NAME DESCRIPTION ELAPSED URL
X a status sweet link
cool tests 1m26s sweet link
@ -397,7 +402,7 @@ func Test_checksRun(t *testing.T) {
wantOut: heredoc.Doc(`
All checks were successful
0 cancelled, 0 failing, 1 successful, 2 skipped, and 0 pending checks
NAME DESCRIPTION ELAPSED URL
cool tests 1m26s sweet link
- rad tests 1m26s sweet link
@ -429,7 +434,7 @@ func Test_checksRun(t *testing.T) {
wantOut: heredoc.Doc(`
All checks were successful
0 cancelled, 0 failing, 1 successful, 0 skipped, and 0 pending checks
NAME DESCRIPTION ELAPSED URL
cool tests 1m26s sweet link
`),
@ -484,7 +489,7 @@ func Test_checksRun(t *testing.T) {
wantOut: heredoc.Doc(`
All checks were successful
0 cancelled, 0 failing, 3 successful, 0 skipped, and 0 pending checks
NAME DESCRIPTION ELAPSED URL
awesome tests awesome description 1m26s sweet link
cool tests cool description 1m26s sweet link
@ -515,7 +520,7 @@ func Test_checksRun(t *testing.T) {
wantOut: heredoc.Doc(`
All checks were successful
0 cancelled, 0 failing, 2 successful, 0 skipped, and 0 pending checks
NAME DESCRIPTION ELAPSED URL
tests/cool tests (pull_request) cool description 1m26s sweet link
tests/cool tests (push) cool description 1m26s sweet link
@ -535,7 +540,7 @@ func Test_checksRun(t *testing.T) {
wantOut: heredoc.Doc(`
All checks were successful
0 cancelled, 0 failing, 1 successful, 0 skipped, and 0 pending checks
NAME DESCRIPTION ELAPSED URL
tests/cool tests cool description 1m26s sweet link
`),

View file

@ -119,6 +119,10 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co
alongside %[1]s--fill%[1]s, the values specified by %[1]s--title%[1]s and/or %[1]s--body%[1]s will
take precedence and overwrite any autofilled content.
The base branch for the created PR can be specified using the %[1]s--base%[1]s flag. If not provided,
the value of %[1]sgh-merge-base%[1]s git branch config will be used. If not configured, the repository's
default branch will be used.
Link an issue to the pull request by referencing the issue in the body of the pull
request. If the body text mentions %[1]sFixes #123%[1]s or %[1]sCloses #123%[1]s, the referenced issue
will automatically get closed when the pull request gets merged.
@ -513,11 +517,10 @@ func initDefaultTitleBody(ctx CreateContext, state *shared.IssueMetadataState, u
return nil
}
func determineTrackingBranch(gitClient *git.Client, remotes ghContext.Remotes, headBranch string) *git.TrackingRef {
func determineTrackingBranch(gitClient *git.Client, remotes ghContext.Remotes, headBranchConfig *git.BranchConfig) *git.TrackingRef {
refsForLookup := []string{"HEAD"}
var trackingRefs []git.TrackingRef
headBranchConfig := gitClient.ReadBranchConfig(context.Background(), headBranch)
if headBranchConfig.RemoteName != "" {
tr := git.TrackingRef{
RemoteName: headBranchConfig.RemoteName,
@ -530,7 +533,7 @@ func determineTrackingBranch(gitClient *git.Client, remotes ghContext.Remotes, h
for _, remote := range remotes {
tr := git.TrackingRef{
RemoteName: remote.Name,
BranchName: headBranch,
BranchName: headBranchConfig.LocalName,
}
trackingRefs = append(trackingRefs, tr)
refsForLookup = append(refsForLookup, tr.String())
@ -640,9 +643,10 @@ func NewCreateContext(opts *CreateOptions) (*CreateContext, error) {
var headRepo ghrepo.Interface
var headRemote *ghContext.Remote
headBranchConfig := gitClient.ReadBranchConfig(context.Background(), headBranch)
if isPushEnabled {
// determine whether the head branch is already pushed to a remote
if pushedTo := determineTrackingBranch(gitClient, remotes, headBranch); pushedTo != nil {
if pushedTo := determineTrackingBranch(gitClient, remotes, &headBranchConfig); pushedTo != nil {
isPushEnabled = false
if r, err := remotes.FindByName(pushedTo.RemoteName); err == nil {
headRepo = r
@ -715,6 +719,9 @@ func NewCreateContext(opts *CreateOptions) (*CreateContext, error) {
}
baseBranch := opts.BaseBranch
if baseBranch == "" {
baseBranch = headBranchConfig.MergeBase
}
if baseBranch == "" {
baseBranch = baseRepo.DefaultBranchRef.Name
}

View file

@ -1,6 +1,7 @@
package create
import (
ctx "context"
"encoding/json"
"errors"
"fmt"
@ -261,6 +262,15 @@ func TestNewCmdCreate(t *testing.T) {
cli: "--editor",
wantsErr: true,
},
{
name: "fill and base",
cli: "--fill --base trunk",
wantsOpts: CreateOptions{
Autofill: true,
BaseBranch: "trunk",
MaintainerCanModify: true,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -323,17 +333,18 @@ func TestNewCmdCreate(t *testing.T) {
func Test_createRun(t *testing.T) {
tests := []struct {
name string
setup func(*CreateOptions, *testing.T) func()
cmdStubs func(*run.CommandStubber)
promptStubs func(*prompter.PrompterMock)
httpStubs func(*httpmock.Registry, *testing.T)
expectedOutputs []string
expectedOut string
expectedErrOut string
expectedBrowse string
wantErr string
tty bool
name string
setup func(*CreateOptions, *testing.T) func()
cmdStubs func(*run.CommandStubber)
promptStubs func(*prompter.PrompterMock)
httpStubs func(*httpmock.Registry, *testing.T)
expectedOutputs []string
expectedOut string
expectedErrOut string
expectedBrowse string
wantErr string
tty bool
customBranchConfig bool
}{
{
name: "nontty web",
@ -626,7 +637,6 @@ func Test_createRun(t *testing.T) {
}))
},
cmdStubs: func(cs *run.CommandStubber) {
cs.Register(`git config --get-regexp.+branch\\\.feature\\\.`, 0, "")
cs.Register(`git show-ref --verify -- HEAD refs/remotes/origin/feature`, 0, "")
cs.Register(`git push --set-upstream origin HEAD:refs/heads/feature`, 0, "")
},
@ -690,7 +700,6 @@ func Test_createRun(t *testing.T) {
}))
},
cmdStubs: func(cs *run.CommandStubber) {
cs.Register(`git config --get-regexp.+branch\\\.feature\\\.`, 0, "")
cs.Register(`git show-ref --verify -- HEAD refs/remotes/origin/feature`, 0, "")
cs.Register(`git push --set-upstream origin HEAD:refs/heads/feature`, 0, "")
},
@ -737,7 +746,6 @@ func Test_createRun(t *testing.T) {
}))
},
cmdStubs: func(cs *run.CommandStubber) {
cs.Register(`git config --get-regexp.+branch\\\.feature\\\.`, 0, "")
cs.Register(`git show-ref --verify -- HEAD refs/remotes/origin/feature`, 0, "")
cs.Register(`git push --set-upstream origin HEAD:refs/heads/feature`, 0, "")
},
@ -787,7 +795,6 @@ func Test_createRun(t *testing.T) {
}))
},
cmdStubs: func(cs *run.CommandStubber) {
cs.Register(`git config --get-regexp.+branch\\\.feature\\\.`, 0, "")
cs.Register(`git show-ref --verify -- HEAD refs/remotes/origin/feature`, 0, "")
cs.Register("git remote rename origin upstream", 0, "")
cs.Register(`git remote add origin https://github.com/monalisa/REPO.git`, 0, "")
@ -846,7 +853,6 @@ func Test_createRun(t *testing.T) {
}))
},
cmdStubs: func(cs *run.CommandStubber) {
cs.Register(`git config --get-regexp \^branch\\\.feature\\\.`, 1, "") // determineTrackingBranch
cs.Register("git show-ref --verify", 0, heredoc.Doc(`
deadbeef HEAD
deadb00f refs/remotes/upstream/feature
@ -878,6 +884,7 @@ func Test_createRun(t *testing.T) {
assert.Equal(t, "my-feat2", input["headRefName"].(string))
}))
},
customBranchConfig: true,
cmdStubs: func(cs *run.CommandStubber) {
cs.Register(`git config --get-regexp \^branch\\\.feature\\\.`, 0, heredoc.Doc(`
branch.feature.remote origin
@ -1066,7 +1073,6 @@ func Test_createRun(t *testing.T) {
httpmock.StringResponse(`{"data": {"viewer": {"login": "OWNER"} } }`))
},
cmdStubs: func(cs *run.CommandStubber) {
cs.Register(`git config --get-regexp.+branch\\\.feature\\\.`, 0, "")
cs.Register(`git show-ref --verify -- HEAD refs/remotes/origin/feature`, 0, "")
cs.Register(`git( .+)? log( .+)? origin/master\.\.\.feature`, 0, "")
cs.Register(`git push --set-upstream origin HEAD:refs/heads/feature`, 0, "")
@ -1099,7 +1105,6 @@ func Test_createRun(t *testing.T) {
mockRetrieveProjects(t, reg)
},
cmdStubs: func(cs *run.CommandStubber) {
cs.Register(`git config --get-regexp.+branch\\\.feature\\\.`, 0, "")
cs.Register(`git show-ref --verify -- HEAD refs/remotes/origin/feature`, 0, "")
cs.Register(`git( .+)? log( .+)? origin/master\.\.\.feature`, 0, "")
cs.Register(`git push --set-upstream origin HEAD:refs/heads/feature`, 0, "")
@ -1464,6 +1469,65 @@ func Test_createRun(t *testing.T) {
},
expectedOut: "https://github.com/OWNER/REPO/pull/12\n",
},
{
name: "gh-merge-base",
tty: true,
setup: func(opts *CreateOptions, t *testing.T) func() {
opts.TitleProvided = true
opts.BodyProvided = true
opts.Title = "my title"
opts.Body = "my body"
opts.Branch = func() (string, error) {
return "task1", nil
}
opts.Remotes = func() (context.Remotes, error) {
return context.Remotes{
{
Remote: &git.Remote{
Name: "upstream",
Resolved: "base",
},
Repo: ghrepo.New("OWNER", "REPO"),
},
{
Remote: &git.Remote{
Name: "origin",
},
Repo: ghrepo.New("monalisa", "REPO"),
},
}, nil
}
return func() {}
},
httpStubs: func(reg *httpmock.Registry, t *testing.T) {
reg.Register(
httpmock.GraphQL(`mutation PullRequestCreate\b`),
httpmock.GraphQLMutation(`
{ "data": { "createPullRequest": { "pullRequest": {
"URL": "https://github.com/OWNER/REPO/pull/12"
} } } }
`, func(input map[string]interface{}) {
assert.Equal(t, "REPOID", input["repositoryId"].(string))
assert.Equal(t, "my title", input["title"].(string))
assert.Equal(t, "my body", input["body"].(string))
assert.Equal(t, "feature/feat2", input["baseRefName"].(string))
assert.Equal(t, "monalisa:task1", input["headRefName"].(string))
}))
},
customBranchConfig: true,
cmdStubs: func(cs *run.CommandStubber) {
cs.Register(`git config --get-regexp \^branch\\\.task1\\\.\(remote\|merge\|gh-merge-base\)\$`, 0, heredoc.Doc(`
branch.task1.remote origin
branch.task1.merge refs/heads/task1
branch.task1.gh-merge-base feature/feat2`)) // ReadBranchConfig
cs.Register(`git show-ref --verify`, 0, heredoc.Doc(`
deadbeef HEAD
deadb00f refs/remotes/upstream/feature/feat2
deadbeef refs/remotes/origin/task1`)) // determineTrackingBranch
},
expectedOut: "https://github.com/OWNER/REPO/pull/12\n",
expectedErrOut: "\nCreating pull request for monalisa:task1 into feature/feat2 in OWNER/REPO\n\n",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -1485,6 +1549,9 @@ func Test_createRun(t *testing.T) {
cs, cmdTeardown := run.Stub()
defer cmdTeardown(t)
cs.Register(`git status --porcelain`, 0, "")
if !tt.customBranchConfig {
cs.Register(`git config --get-regexp \^branch\\\..+\\\.\(remote\|merge\|gh-merge-base\)\$`, 0, "")
}
if tt.cmdStubs != nil {
tt.cmdStubs(cs)
@ -1651,7 +1718,8 @@ func Test_determineTrackingBranch(t *testing.T) {
GhPath: "some/path/gh",
GitPath: "some/path/git",
}
ref := determineTrackingBranch(gitClient, tt.remotes, "feature")
headBranchConfig := gitClient.ReadBranchConfig(ctx.Background(), "feature")
ref := determineTrackingBranch(gitClient, tt.remotes, &headBranchConfig)
tt.assert(ref, t)
})
}

View file

@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -euo pipefail
# Get the root directory of the repository
rootDir="$(git rev-parse --show-toplevel)"
ghBuildPath="$rootDir/bin/gh"
# Verify an OCI artifact with bundles stored on the GHCR OCI registry
echo "Testing with OCI image ghcr.io/github/artifact-attestations-helm-charts/policy-controller:v0.10.0-github9 with the --bundle-from-oci flag"
if ! $ghBuildPath attestation verify oci://ghcr.io/github/artifact-attestations-helm-charts/policy-controller:v0.10.0-github9 --owner=github --bundle-from-oci; then
echo "Failed to verify oci://ghcr.io/github/artifact-attestations-helm-charts/policy-controller:v0.10.0-github9 with bundles from the GHCR OCI registry"
exit 1
fi