From 4739ee9959934640c8074133cb546c68ca56e7b4 Mon Sep 17 00:00:00 2001 From: Thorsten Ball Date: Mon, 23 Nov 2020 14:30:24 +0100 Subject: [PATCH 1/7] Query and use the repository.branch when defined in spec --- cmd/src/campaigns_common.go | 4 ++ internal/campaigns/archive_fetcher.go | 5 +- internal/campaigns/archive_fetcher_test.go | 44 ++++++++++++++++- internal/campaigns/executor_test.go | 15 ++++-- internal/campaigns/graphql/repository.go | 51 ++++++++++++++++++- internal/campaigns/service.go | 57 ++++++++++++++++++---- 6 files changed, 158 insertions(+), 18 deletions(-) diff --git a/cmd/src/campaigns_common.go b/cmd/src/campaigns_common.go index d9178b654f..457964bb5c 100644 --- a/cmd/src/campaigns_common.go +++ b/cmd/src/campaigns_common.go @@ -234,6 +234,10 @@ func campaignsExecute(ctx context.Context, out *output.Output, svc *campaigns.Se campaignsCompletePending(pending, "Resolved repositories") } + for _, r := range repos { + fmt.Printf("Name=%s, BaseRef()=%s, Rev()=%s\n", r.Name, r.BaseRef(), r.Rev()) + } + p := newCampaignProgressPrinter(out, *verbose, opts.Parallelism) specs, err := svc.ExecuteCampaignSpec(ctx, repos, executor, campaignSpec, p.PrintStatuses) if err != nil { diff --git a/internal/campaigns/archive_fetcher.go b/internal/campaigns/archive_fetcher.go index e472e64889..69d4a61fb9 100644 --- a/internal/campaigns/archive_fetcher.go +++ b/internal/campaigns/archive_fetcher.go @@ -120,12 +120,11 @@ func fetchRepositoryArchive(ctx context.Context, client api.Client, repo *graphq } func repositoryZipArchivePath(repo *graphql.Repository) string { - return path.Join("", repo.Name+"@"+repo.DefaultBranch.Name, "-", "raw") + return path.Join("", repo.Name+"@"+repo.BaseRef(), "-", "raw") } func localRepositoryZipArchivePath(dir string, repo *graphql.Repository) string { - ref := repo.DefaultBranch.Target.OID - return filepath.Join(dir, fmt.Sprintf("%s-%s.zip", repo.Slug(), ref)) + return filepath.Join(dir, fmt.Sprintf("%s-%s.zip", repo.Slug(), repo.Rev())) } func unzip(zipFile, dest string) error { diff --git a/internal/campaigns/archive_fetcher_test.go b/internal/campaigns/archive_fetcher_test.go index 87f6827f4d..1e304cf2c0 100644 --- a/internal/campaigns/archive_fetcher_test.go +++ b/internal/campaigns/archive_fetcher_test.go @@ -30,7 +30,7 @@ func TestWorkspaceCreator_Create(t *testing.T) { repo := &graphql.Repository{ ID: "src-cli", Name: "github.com/sourcegraph/src-cli", - DefaultBranch: &graphql.Branch{Name: "main", Target: struct{ OID string }{OID: "d34db33f"}}, + DefaultBranch: &graphql.Branch{Name: "main", Target: graphql.Target{OID: "d34db33f"}}, } archive := mockRepoArchive{ @@ -156,6 +156,48 @@ func TestWorkspaceCreator_Create(t *testing.T) { t.Fatalf("zip file in temp dir was not cleaned up") } }) + + t.Run("non-default branch", func(t *testing.T) { + otherBranchOID := "f00b4r" + repo := &graphql.Repository{ + ID: "src-cli-with-non-main-branch", + Name: "github.com/sourcegraph/src-cli", + DefaultBranch: &graphql.Branch{Name: "main", Target: graphql.Target{OID: "d34db33f"}}, + Branches: struct { + Nodes []*graphql.Branch + }{ + Nodes: []*graphql.Branch{ + &graphql.Branch{Name: "other-branch", Target: graphql.Target{OID: otherBranchOID}}, + }, + }, + } + + archive := mockRepoArchive{repo: repo, files: map[string]string{}} + + ts := httptest.NewServer(newZipArchivesMux(t, nil, archive)) + defer ts.Close() + + var clientBuffer bytes.Buffer + client := api.NewClient(api.ClientOpts{Endpoint: ts.URL, Out: &clientBuffer}) + + testTempDir := workspaceTmpDir(t) + + creator := &WorkspaceCreator{dir: testTempDir, client: client} + + _, err := creator.Create(context.Background(), repo) + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + + wantZipFile := "github.1485827954.workers.dev-sourcegraph-src-cli-" + otherBranchOID + ".zip" + ok, err := dirContains(creator.dir, wantZipFile) + if err != nil { + t.Fatal(err) + } + if !ok { + t.Fatalf("temp dir doesnt contain zip file") + } + }) } func TestMkdirAll(t *testing.T) { diff --git a/internal/campaigns/executor_test.go b/internal/campaigns/executor_test.go index fd42149697..0d438ca168 100644 --- a/internal/campaigns/executor_test.go +++ b/internal/campaigns/executor_test.go @@ -37,14 +37,23 @@ func TestExecutor_Integration(t *testing.T) { srcCLIRepo := &graphql.Repository{ ID: "src-cli", Name: "github.com/sourcegraph/src-cli", - DefaultBranch: &graphql.Branch{Name: "main", Target: struct{ OID string }{OID: "d34db33f"}}, + DefaultBranch: &graphql.Branch{Name: "main", Target: graphql.Target{OID: "d34db33f"}}, } sourcegraphRepo := &graphql.Repository{ ID: "sourcegraph", Name: "github.com/sourcegraph/sourcegraph", DefaultBranch: &graphql.Branch{ Name: "main", - Target: struct{ OID string }{OID: "f00b4r3r"}, + Target: graphql.Target{OID: "f00b4r3r"}, + }, + + Branches: graphql.Branches{ + Nodes: []*graphql.Branch{ + &graphql.Branch{ + Name: "other-branch", + Target: graphql.Target{OID: "0therbr4nch"}, + }, + }, }, } @@ -220,7 +229,7 @@ func newZipArchivesMux(t *testing.T, callback http.HandlerFunc, archives ...mock for _, archive := range archives { files := archive.files - path := fmt.Sprintf("/%s@%s/-/raw", archive.repo.Name, archive.repo.DefaultBranch.Name) + path := fmt.Sprintf("/%s@%s/-/raw", archive.repo.Name, archive.repo.BaseRef()) downloadName := filepath.Base(archive.repo.Name) mediaType := mime.FormatMediaType("Attachment", map[string]string{ diff --git a/internal/campaigns/graphql/repository.go b/internal/campaigns/graphql/repository.go index 6147bae78b..c3bd5679cb 100644 --- a/internal/campaigns/graphql/repository.go +++ b/internal/campaigns/graphql/repository.go @@ -22,9 +22,42 @@ fragment repositoryFields on Repository { } ` +const RepositoryWithBranchFragment = ` +fragment repositoryFieldsWithBranch on Repository { + id + name + url + externalRepository { + serviceType + } + defaultBranch { + name + target { + oid + } + } + branches(query: $branch, first: 1) @include(if:$queryBranch){ + nodes { + name + target { + oid + } + } + } +} +` + +type Target struct { + OID string +} + type Branch struct { Name string - Target struct{ OID string } + Target Target +} + +type Branches struct { + Nodes []*Branch } type Repository struct { @@ -32,16 +65,30 @@ type Repository struct { Name string URL string ExternalRepository struct{ ServiceType string } - DefaultBranch *Branch + + DefaultBranch *Branch + Branches Branches FileMatches map[string]bool } +func (r *Repository) HasBranch() bool { + return r.DefaultBranch != nil || len(r.Branches.Nodes) != 0 +} + func (r *Repository) BaseRef() string { + if len(r.Branches.Nodes) != 0 { + return r.Branches.Nodes[0].Name + } + return r.DefaultBranch.Name } func (r *Repository) Rev() string { + if len(r.Branches.Nodes) != 0 { + return r.Branches.Nodes[0].Target.OID + } + return r.DefaultBranch.Target.OID } diff --git a/internal/campaigns/service.go b/internal/campaigns/service.go index c6f532d1dc..f2bf22f0bb 100644 --- a/internal/campaigns/service.go +++ b/internal/campaigns/service.go @@ -363,8 +363,7 @@ func (svc *Service) ResolveNamespace(ctx context.Context, namespace string) (str } func (svc *Service) ResolveRepositories(ctx context.Context, spec *CampaignSpec) ([]*graphql.Repository, error) { - final := []*graphql.Repository{} - seen := map[string]struct{}{} + seen := map[string]*graphql.Repository{} unsupported := UnsupportedRepoSet{} // TODO: this could be trivially parallelised in the future. @@ -375,11 +374,12 @@ func (svc *Service) ResolveRepositories(ctx context.Context, spec *CampaignSpec) } for _, repo := range repos { - if _, ok := seen[repo.ID]; !ok { - if repo.DefaultBranch == nil { - continue - } - seen[repo.ID] = struct{}{} + if !repo.HasBranch() { + continue + } + + if other, ok := seen[repo.ID]; !ok { + seen[repo.ID] = repo switch st := strings.ToLower(repo.ExternalRepository.ServiceType); st { case "github", "gitlab", "bitbucketserver": default: @@ -388,12 +388,19 @@ func (svc *Service) ResolveRepositories(ctx context.Context, spec *CampaignSpec) continue } } - - final = append(final, repo) + } else { + // If we've already seen this repository, we overwrite the + // Branches field with the latest value we have + other.Branches = repo.Branches } } } + final := make([]*graphql.Repository, 0, len(seen)) + for _, repo := range seen { + final = append(final, repo) + } + if unsupported.hasUnsupported() && !svc.allowUnsupported { return final, unsupported } @@ -404,6 +411,12 @@ func (svc *Service) ResolveRepositories(ctx context.Context, spec *CampaignSpec) func (svc *Service) ResolveRepositoriesOn(ctx context.Context, on *OnQueryOrRepository) ([]*graphql.Repository, error) { if on.RepositoriesMatchingQuery != "" { return svc.resolveRepositorySearch(ctx, on.RepositoriesMatchingQuery) + } else if on.Repository != "" && on.Branch != "" { + repo, err := svc.resolveRepositoryNameAndBranch(ctx, on.Repository, on.Branch) + if err != nil { + return nil, err + } + return []*graphql.Repository{repo}, nil } else if on.Repository != "" { repo, err := svc.resolveRepositoryName(ctx, on.Repository) if err != nil { @@ -438,6 +451,32 @@ func (svc *Service) resolveRepositoryName(ctx context.Context, name string) (*gr return result.Repository, nil } +const repositoryNameAndBranchQuery = ` +query Repository($name: String!, $queryBranch: Boolean!, $branch: String!) { + repository(name: $name) { + ...repositoryFieldsWithBranch + } +} +` + graphql.RepositoryWithBranchFragment + +func (svc *Service) resolveRepositoryNameAndBranch(ctx context.Context, name, branch string) (*graphql.Repository, error) { + var result struct{ Repository *graphql.Repository } + if ok, err := svc.client.NewRequest(repositoryNameAndBranchQuery, map[string]interface{}{ + "name": name, + "queryBranch": true, + "branch": branch, + }).Do(ctx, &result); err != nil || !ok { + return nil, err + } + if result.Repository == nil { + return nil, errors.New("no repository found") + } + if len(result.Repository.Branches.Nodes) == 0 { + return nil, fmt.Errorf("no branch matching %q found for repository %s", branch, name) + } + return result.Repository, nil +} + // TODO: search result alerts. const repositorySearchQuery = ` query ChangesetRepos( From 8b945781c6d3ab670497713a388dc3d6d0ca189b Mon Sep 17 00:00:00 2001 From: Thorsten Ball Date: Mon, 23 Nov 2020 15:01:49 +0100 Subject: [PATCH 2/7] Remove debug pritning --- cmd/src/campaigns_common.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cmd/src/campaigns_common.go b/cmd/src/campaigns_common.go index 457964bb5c..d9178b654f 100644 --- a/cmd/src/campaigns_common.go +++ b/cmd/src/campaigns_common.go @@ -234,10 +234,6 @@ func campaignsExecute(ctx context.Context, out *output.Output, svc *campaigns.Se campaignsCompletePending(pending, "Resolved repositories") } - for _, r := range repos { - fmt.Printf("Name=%s, BaseRef()=%s, Rev()=%s\n", r.Name, r.BaseRef(), r.Rev()) - } - p := newCampaignProgressPrinter(out, *verbose, opts.Parallelism) specs, err := svc.ExecuteCampaignSpec(ctx, repos, executor, campaignSpec, p.PrintStatuses) if err != nil { From 5b5b1561319e51ef0ce1e2ac3c2abe1a138c0f54 Mon Sep 17 00:00:00 2001 From: Thorsten Ball Date: Mon, 23 Nov 2020 15:39:30 +0100 Subject: [PATCH 3/7] Query specific commit and not query branches --- internal/campaigns/executor_test.go | 9 ------ internal/campaigns/graphql/repository.go | 36 ++++++++++++++---------- internal/campaigns/service.go | 23 +++++++++------ 3 files changed, 36 insertions(+), 32 deletions(-) diff --git a/internal/campaigns/executor_test.go b/internal/campaigns/executor_test.go index 0d438ca168..d69f1d37ea 100644 --- a/internal/campaigns/executor_test.go +++ b/internal/campaigns/executor_test.go @@ -46,15 +46,6 @@ func TestExecutor_Integration(t *testing.T) { Name: "main", Target: graphql.Target{OID: "f00b4r3r"}, }, - - Branches: graphql.Branches{ - Nodes: []*graphql.Branch{ - &graphql.Branch{ - Name: "other-branch", - Target: graphql.Target{OID: "0therbr4nch"}, - }, - }, - }, } tests := []struct { diff --git a/internal/campaigns/graphql/repository.go b/internal/campaigns/graphql/repository.go index c3bd5679cb..0534d03eb0 100644 --- a/internal/campaigns/graphql/repository.go +++ b/internal/campaigns/graphql/repository.go @@ -22,8 +22,8 @@ fragment repositoryFields on Repository { } ` -const RepositoryWithBranchFragment = ` -fragment repositoryFieldsWithBranch on Repository { +const RepositoryWithCommitFragment = ` +fragment repositoryFieldsWithCommit on Repository { id name url @@ -36,13 +36,8 @@ fragment repositoryFieldsWithBranch on Repository { oid } } - branches(query: $branch, first: 1) @include(if:$queryBranch){ - nodes { - name - target { - oid - } - } + commit(rev: $rev) @include(if:$queryCommit) { + oid } } ` @@ -67,26 +62,37 @@ type Repository struct { ExternalRepository struct{ ServiceType string } DefaultBranch *Branch - Branches Branches + + Commit Target + // Branch is populated by resolveRepositoryNameAndBranch with the queried + // branch's name and the contents of the Commit property. + Branch Branch FileMatches map[string]bool } func (r *Repository) HasBranch() bool { - return r.DefaultBranch != nil || len(r.Branches.Nodes) != 0 + return r.DefaultBranch != nil || (r.Commit.OID != "" && r.Branch.Name != "") } func (r *Repository) BaseRef() string { - if len(r.Branches.Nodes) != 0 { - return r.Branches.Nodes[0].Name + if r.Branch.Name != "" { + return ensurePrefix(r.Branch.Name) } return r.DefaultBranch.Name } +func ensurePrefix(rev string) string { + if strings.HasPrefix(rev, "refs/heads/") { + return rev + } + return "refs/heads/" + rev +} + func (r *Repository) Rev() string { - if len(r.Branches.Nodes) != 0 { - return r.Branches.Nodes[0].Target.OID + if r.Branch.Target.OID != "" { + return r.Branch.Target.OID } return r.DefaultBranch.Target.OID diff --git a/internal/campaigns/service.go b/internal/campaigns/service.go index f2bf22f0bb..6540aa0f0e 100644 --- a/internal/campaigns/service.go +++ b/internal/campaigns/service.go @@ -390,8 +390,9 @@ func (svc *Service) ResolveRepositories(ctx context.Context, spec *CampaignSpec) } } else { // If we've already seen this repository, we overwrite the - // Branches field with the latest value we have - other.Branches = repo.Branches + // Commit/Branch fields with the latest value we have + other.Commit = repo.Commit + other.Branch = repo.Branch } } } @@ -452,28 +453,34 @@ func (svc *Service) resolveRepositoryName(ctx context.Context, name string) (*gr } const repositoryNameAndBranchQuery = ` -query Repository($name: String!, $queryBranch: Boolean!, $branch: String!) { +query Repository($name: String!, $queryCommit: Boolean!, $rev: String!) { repository(name: $name) { - ...repositoryFieldsWithBranch + ...repositoryFieldsWithCommit } } -` + graphql.RepositoryWithBranchFragment +` + graphql.RepositoryWithCommitFragment func (svc *Service) resolveRepositoryNameAndBranch(ctx context.Context, name, branch string) (*graphql.Repository, error) { var result struct{ Repository *graphql.Repository } if ok, err := svc.client.NewRequest(repositoryNameAndBranchQuery, map[string]interface{}{ "name": name, - "queryBranch": true, - "branch": branch, + "queryCommit": true, + "rev": branch, }).Do(ctx, &result); err != nil || !ok { return nil, err } if result.Repository == nil { return nil, errors.New("no repository found") } - if len(result.Repository.Branches.Nodes) == 0 { + if result.Repository.Commit.OID == "" { return nil, fmt.Errorf("no branch matching %q found for repository %s", branch, name) } + + result.Repository.Branch = graphql.Branch{ + Name: branch, + Target: result.Repository.Commit, + } + return result.Repository, nil } From 2b9125854622c056eb2a8bc9cd8ba973d52217fb Mon Sep 17 00:00:00 2001 From: Thorsten Ball Date: Mon, 23 Nov 2020 15:45:33 +0100 Subject: [PATCH 4/7] Merge two repository queries --- internal/campaigns/archive_fetcher_test.go | 10 +++------- internal/campaigns/graphql/repository.go | 17 ----------------- internal/campaigns/service.go | 22 ++++++++++------------ 3 files changed, 13 insertions(+), 36 deletions(-) diff --git a/internal/campaigns/archive_fetcher_test.go b/internal/campaigns/archive_fetcher_test.go index 1e304cf2c0..9e536173b7 100644 --- a/internal/campaigns/archive_fetcher_test.go +++ b/internal/campaigns/archive_fetcher_test.go @@ -163,13 +163,9 @@ func TestWorkspaceCreator_Create(t *testing.T) { ID: "src-cli-with-non-main-branch", Name: "github.com/sourcegraph/src-cli", DefaultBranch: &graphql.Branch{Name: "main", Target: graphql.Target{OID: "d34db33f"}}, - Branches: struct { - Nodes []*graphql.Branch - }{ - Nodes: []*graphql.Branch{ - &graphql.Branch{Name: "other-branch", Target: graphql.Target{OID: otherBranchOID}}, - }, - }, + + Commit: graphql.Target{OID: otherBranchOID}, + Branch: graphql.Branch{Name: "other-branch", Target: graphql.Target{OID: otherBranchOID}}, } archive := mockRepoArchive{repo: repo, files: map[string]string{}} diff --git a/internal/campaigns/graphql/repository.go b/internal/campaigns/graphql/repository.go index 0534d03eb0..bd3550b9fc 100644 --- a/internal/campaigns/graphql/repository.go +++ b/internal/campaigns/graphql/repository.go @@ -19,23 +19,6 @@ fragment repositoryFields on Repository { oid } } -} -` - -const RepositoryWithCommitFragment = ` -fragment repositoryFieldsWithCommit on Repository { - id - name - url - externalRepository { - serviceType - } - defaultBranch { - name - target { - oid - } - } commit(rev: $rev) @include(if:$queryCommit) { oid } diff --git a/internal/campaigns/service.go b/internal/campaigns/service.go index 6540aa0f0e..a1291bce3a 100644 --- a/internal/campaigns/service.go +++ b/internal/campaigns/service.go @@ -432,7 +432,7 @@ func (svc *Service) ResolveRepositoriesOn(ctx context.Context, on *OnQueryOrRepo } const repositoryNameQuery = ` -query Repository($name: String!) { +query Repository($name: String!, $queryCommit: Boolean!, $rev: String) { repository(name: $name) { ...repositoryFields } @@ -442,7 +442,9 @@ query Repository($name: String!) { func (svc *Service) resolveRepositoryName(ctx context.Context, name string) (*graphql.Repository, error) { var result struct{ Repository *graphql.Repository } if ok, err := svc.client.NewRequest(repositoryNameQuery, map[string]interface{}{ - "name": name, + "name": name, + "queryCommit": false, + "rev": "", }).Do(ctx, &result); err != nil || !ok { return nil, err } @@ -452,17 +454,9 @@ func (svc *Service) resolveRepositoryName(ctx context.Context, name string) (*gr return result.Repository, nil } -const repositoryNameAndBranchQuery = ` -query Repository($name: String!, $queryCommit: Boolean!, $rev: String!) { - repository(name: $name) { - ...repositoryFieldsWithCommit - } -} -` + graphql.RepositoryWithCommitFragment - func (svc *Service) resolveRepositoryNameAndBranch(ctx context.Context, name, branch string) (*graphql.Repository, error) { var result struct{ Repository *graphql.Repository } - if ok, err := svc.client.NewRequest(repositoryNameAndBranchQuery, map[string]interface{}{ + if ok, err := svc.client.NewRequest(repositoryNameQuery, map[string]interface{}{ "name": name, "queryCommit": true, "rev": branch, @@ -488,6 +482,8 @@ func (svc *Service) resolveRepositoryNameAndBranch(ctx context.Context, name, br const repositorySearchQuery = ` query ChangesetRepos( $query: String!, + $queryCommit: Boolean!, + $rev: String!, ) { search(query: $query, version: V2) { results { @@ -517,7 +513,9 @@ func (svc *Service) resolveRepositorySearch(ctx context.Context, query string) ( } } if ok, err := svc.client.NewRequest(repositorySearchQuery, map[string]interface{}{ - "query": setDefaultQueryCount(query), + "query": setDefaultQueryCount(query), + "queryCommit": false, + "rev": "", }).Do(ctx, &result); err != nil || !ok { return nil, err } From a55508e11aebe79820c65c247163773e4a15065f Mon Sep 17 00:00:00 2001 From: Thorsten Ball Date: Mon, 23 Nov 2020 15:46:19 +0100 Subject: [PATCH 5/7] Fix critical indentation error (and unused type) --- internal/campaigns/graphql/repository.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/internal/campaigns/graphql/repository.go b/internal/campaigns/graphql/repository.go index bd3550b9fc..4b1c4d98a8 100644 --- a/internal/campaigns/graphql/repository.go +++ b/internal/campaigns/graphql/repository.go @@ -21,7 +21,7 @@ fragment repositoryFields on Repository { } commit(rev: $rev) @include(if:$queryCommit) { oid - } + } } ` @@ -34,10 +34,6 @@ type Branch struct { Target Target } -type Branches struct { - Nodes []*Branch -} - type Repository struct { ID string Name string From 3f9bc9de8c26ccfbd9dc1bb2ac8b2a45ca8ebac5 Mon Sep 17 00:00:00 2001 From: Thorsten Ball Date: Mon, 23 Nov 2020 15:52:01 +0100 Subject: [PATCH 6/7] Fix wrong query --- internal/campaigns/service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/campaigns/service.go b/internal/campaigns/service.go index a1291bce3a..f59cca6c8a 100644 --- a/internal/campaigns/service.go +++ b/internal/campaigns/service.go @@ -432,7 +432,7 @@ func (svc *Service) ResolveRepositoriesOn(ctx context.Context, on *OnQueryOrRepo } const repositoryNameQuery = ` -query Repository($name: String!, $queryCommit: Boolean!, $rev: String) { +query Repository($name: String!, $queryCommit: Boolean!, $rev: String!) { repository(name: $name) { ...repositoryFields } From e74598e8274f04d0db1c8367104186bb4d3cb952 Mon Sep 17 00:00:00 2001 From: Thorsten Ball Date: Tue, 24 Nov 2020 09:35:58 +0100 Subject: [PATCH 7/7] Add changelog entry --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c8e0f02e6..fa206b0815 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ All notable changes to `src-cli` are documented in this file. ### Fixed +- The evaluation of the [`repository.branch` attribute](https://docs.sourcegraph.com/campaigns/references/campaign_spec_yaml_reference#on-repository) has been fixed to actually cause the correct version of the repository to be used. [#393](https://github.com/sourcegraph/src-cli/pull/393) + ### Removed ## 3.22.3