Skip to content

Commit ba17ecb

Browse files
authored
Query and use the repository.branch when defined in spec (#393)
* Query and use the repository.branch when defined in spec * Remove debug pritning * Query specific commit and not query branches * Merge two repository queries * Fix critical indentation error (and unused type) * Fix wrong query * Add changelog entry
1 parent c344c60 commit ba17ecb

File tree

6 files changed

+136
-21
lines changed

6 files changed

+136
-21
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ All notable changes to `src-cli` are documented in this file.
1919

2020
### Fixed
2121

22+
- 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)
23+
2224
### Removed
2325

2426
## 3.22.3

internal/campaigns/archive_fetcher.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,11 @@ func fetchRepositoryArchive(ctx context.Context, client api.Client, repo *graphq
120120
}
121121

122122
func repositoryZipArchivePath(repo *graphql.Repository) string {
123-
return path.Join("", repo.Name+"@"+repo.DefaultBranch.Name, "-", "raw")
123+
return path.Join("", repo.Name+"@"+repo.BaseRef(), "-", "raw")
124124
}
125125

126126
func localRepositoryZipArchivePath(dir string, repo *graphql.Repository) string {
127-
ref := repo.DefaultBranch.Target.OID
128-
return filepath.Join(dir, fmt.Sprintf("%s-%s.zip", repo.Slug(), ref))
127+
return filepath.Join(dir, fmt.Sprintf("%s-%s.zip", repo.Slug(), repo.Rev()))
129128
}
130129

131130
func unzip(zipFile, dest string) error {

internal/campaigns/archive_fetcher_test.go

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func TestWorkspaceCreator_Create(t *testing.T) {
3030
repo := &graphql.Repository{
3131
ID: "src-cli",
3232
Name: "github.com/sourcegraph/src-cli",
33-
DefaultBranch: &graphql.Branch{Name: "main", Target: struct{ OID string }{OID: "d34db33f"}},
33+
DefaultBranch: &graphql.Branch{Name: "main", Target: graphql.Target{OID: "d34db33f"}},
3434
}
3535

3636
archive := mockRepoArchive{
@@ -156,6 +156,44 @@ func TestWorkspaceCreator_Create(t *testing.T) {
156156
t.Fatalf("zip file in temp dir was not cleaned up")
157157
}
158158
})
159+
160+
t.Run("non-default branch", func(t *testing.T) {
161+
otherBranchOID := "f00b4r"
162+
repo := &graphql.Repository{
163+
ID: "src-cli-with-non-main-branch",
164+
Name: "github.com/sourcegraph/src-cli",
165+
DefaultBranch: &graphql.Branch{Name: "main", Target: graphql.Target{OID: "d34db33f"}},
166+
167+
Commit: graphql.Target{OID: otherBranchOID},
168+
Branch: graphql.Branch{Name: "other-branch", Target: graphql.Target{OID: otherBranchOID}},
169+
}
170+
171+
archive := mockRepoArchive{repo: repo, files: map[string]string{}}
172+
173+
ts := httptest.NewServer(newZipArchivesMux(t, nil, archive))
174+
defer ts.Close()
175+
176+
var clientBuffer bytes.Buffer
177+
client := api.NewClient(api.ClientOpts{Endpoint: ts.URL, Out: &clientBuffer})
178+
179+
testTempDir := workspaceTmpDir(t)
180+
181+
creator := &WorkspaceCreator{dir: testTempDir, client: client}
182+
183+
_, err := creator.Create(context.Background(), repo)
184+
if err != nil {
185+
t.Fatalf("unexpected error: %s", err)
186+
}
187+
188+
wantZipFile := "github.com-sourcegraph-src-cli-" + otherBranchOID + ".zip"
189+
ok, err := dirContains(creator.dir, wantZipFile)
190+
if err != nil {
191+
t.Fatal(err)
192+
}
193+
if !ok {
194+
t.Fatalf("temp dir doesnt contain zip file")
195+
}
196+
})
159197
}
160198

161199
func TestMkdirAll(t *testing.T) {

internal/campaigns/executor_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@ func TestExecutor_Integration(t *testing.T) {
3737
srcCLIRepo := &graphql.Repository{
3838
ID: "src-cli",
3939
Name: "github.com/sourcegraph/src-cli",
40-
DefaultBranch: &graphql.Branch{Name: "main", Target: struct{ OID string }{OID: "d34db33f"}},
40+
DefaultBranch: &graphql.Branch{Name: "main", Target: graphql.Target{OID: "d34db33f"}},
4141
}
4242
sourcegraphRepo := &graphql.Repository{
4343
ID: "sourcegraph",
4444
Name: "github.com/sourcegraph/sourcegraph",
4545
DefaultBranch: &graphql.Branch{
4646
Name: "main",
47-
Target: struct{ OID string }{OID: "f00b4r3r"},
47+
Target: graphql.Target{OID: "f00b4r3r"},
4848
},
4949
}
5050

@@ -220,7 +220,7 @@ func newZipArchivesMux(t *testing.T, callback http.HandlerFunc, archives ...mock
220220

221221
for _, archive := range archives {
222222
files := archive.files
223-
path := fmt.Sprintf("/%s@%s/-/raw", archive.repo.Name, archive.repo.DefaultBranch.Name)
223+
path := fmt.Sprintf("/%s@%s/-/raw", archive.repo.Name, archive.repo.BaseRef())
224224

225225
downloadName := filepath.Base(archive.repo.Name)
226226
mediaType := mime.FormatMediaType("Attachment", map[string]string{

internal/campaigns/graphql/repository.go

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,29 +19,61 @@ fragment repositoryFields on Repository {
1919
oid
2020
}
2121
}
22+
commit(rev: $rev) @include(if:$queryCommit) {
23+
oid
24+
}
2225
}
2326
`
2427

28+
type Target struct {
29+
OID string
30+
}
31+
2532
type Branch struct {
2633
Name string
27-
Target struct{ OID string }
34+
Target Target
2835
}
2936

3037
type Repository struct {
3138
ID string
3239
Name string
3340
URL string
3441
ExternalRepository struct{ ServiceType string }
35-
DefaultBranch *Branch
42+
43+
DefaultBranch *Branch
44+
45+
Commit Target
46+
// Branch is populated by resolveRepositoryNameAndBranch with the queried
47+
// branch's name and the contents of the Commit property.
48+
Branch Branch
3649

3750
FileMatches map[string]bool
3851
}
3952

53+
func (r *Repository) HasBranch() bool {
54+
return r.DefaultBranch != nil || (r.Commit.OID != "" && r.Branch.Name != "")
55+
}
56+
4057
func (r *Repository) BaseRef() string {
58+
if r.Branch.Name != "" {
59+
return ensurePrefix(r.Branch.Name)
60+
}
61+
4162
return r.DefaultBranch.Name
4263
}
4364

65+
func ensurePrefix(rev string) string {
66+
if strings.HasPrefix(rev, "refs/heads/") {
67+
return rev
68+
}
69+
return "refs/heads/" + rev
70+
}
71+
4472
func (r *Repository) Rev() string {
73+
if r.Branch.Target.OID != "" {
74+
return r.Branch.Target.OID
75+
}
76+
4577
return r.DefaultBranch.Target.OID
4678
}
4779

internal/campaigns/service.go

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -363,8 +363,7 @@ func (svc *Service) ResolveNamespace(ctx context.Context, namespace string) (str
363363
}
364364

365365
func (svc *Service) ResolveRepositories(ctx context.Context, spec *CampaignSpec) ([]*graphql.Repository, error) {
366-
final := []*graphql.Repository{}
367-
seen := map[string]struct{}{}
366+
seen := map[string]*graphql.Repository{}
368367
unsupported := UnsupportedRepoSet{}
369368

370369
// TODO: this could be trivially parallelised in the future.
@@ -375,11 +374,12 @@ func (svc *Service) ResolveRepositories(ctx context.Context, spec *CampaignSpec)
375374
}
376375

377376
for _, repo := range repos {
378-
if _, ok := seen[repo.ID]; !ok {
379-
if repo.DefaultBranch == nil {
380-
continue
381-
}
382-
seen[repo.ID] = struct{}{}
377+
if !repo.HasBranch() {
378+
continue
379+
}
380+
381+
if other, ok := seen[repo.ID]; !ok {
382+
seen[repo.ID] = repo
383383
switch st := strings.ToLower(repo.ExternalRepository.ServiceType); st {
384384
case "github", "gitlab", "bitbucketserver":
385385
default:
@@ -388,12 +388,20 @@ func (svc *Service) ResolveRepositories(ctx context.Context, spec *CampaignSpec)
388388
continue
389389
}
390390
}
391-
392-
final = append(final, repo)
391+
} else {
392+
// If we've already seen this repository, we overwrite the
393+
// Commit/Branch fields with the latest value we have
394+
other.Commit = repo.Commit
395+
other.Branch = repo.Branch
393396
}
394397
}
395398
}
396399

400+
final := make([]*graphql.Repository, 0, len(seen))
401+
for _, repo := range seen {
402+
final = append(final, repo)
403+
}
404+
397405
if unsupported.hasUnsupported() && !svc.allowUnsupported {
398406
return final, unsupported
399407
}
@@ -404,6 +412,12 @@ func (svc *Service) ResolveRepositories(ctx context.Context, spec *CampaignSpec)
404412
func (svc *Service) ResolveRepositoriesOn(ctx context.Context, on *OnQueryOrRepository) ([]*graphql.Repository, error) {
405413
if on.RepositoriesMatchingQuery != "" {
406414
return svc.resolveRepositorySearch(ctx, on.RepositoriesMatchingQuery)
415+
} else if on.Repository != "" && on.Branch != "" {
416+
repo, err := svc.resolveRepositoryNameAndBranch(ctx, on.Repository, on.Branch)
417+
if err != nil {
418+
return nil, err
419+
}
420+
return []*graphql.Repository{repo}, nil
407421
} else if on.Repository != "" {
408422
repo, err := svc.resolveRepositoryName(ctx, on.Repository)
409423
if err != nil {
@@ -418,7 +432,7 @@ func (svc *Service) ResolveRepositoriesOn(ctx context.Context, on *OnQueryOrRepo
418432
}
419433

420434
const repositoryNameQuery = `
421-
query Repository($name: String!) {
435+
query Repository($name: String!, $queryCommit: Boolean!, $rev: String!) {
422436
repository(name: $name) {
423437
...repositoryFields
424438
}
@@ -428,7 +442,9 @@ query Repository($name: String!) {
428442
func (svc *Service) resolveRepositoryName(ctx context.Context, name string) (*graphql.Repository, error) {
429443
var result struct{ Repository *graphql.Repository }
430444
if ok, err := svc.client.NewRequest(repositoryNameQuery, map[string]interface{}{
431-
"name": name,
445+
"name": name,
446+
"queryCommit": false,
447+
"rev": "",
432448
}).Do(ctx, &result); err != nil || !ok {
433449
return nil, err
434450
}
@@ -438,10 +454,36 @@ func (svc *Service) resolveRepositoryName(ctx context.Context, name string) (*gr
438454
return result.Repository, nil
439455
}
440456

457+
func (svc *Service) resolveRepositoryNameAndBranch(ctx context.Context, name, branch string) (*graphql.Repository, error) {
458+
var result struct{ Repository *graphql.Repository }
459+
if ok, err := svc.client.NewRequest(repositoryNameQuery, map[string]interface{}{
460+
"name": name,
461+
"queryCommit": true,
462+
"rev": branch,
463+
}).Do(ctx, &result); err != nil || !ok {
464+
return nil, err
465+
}
466+
if result.Repository == nil {
467+
return nil, errors.New("no repository found")
468+
}
469+
if result.Repository.Commit.OID == "" {
470+
return nil, fmt.Errorf("no branch matching %q found for repository %s", branch, name)
471+
}
472+
473+
result.Repository.Branch = graphql.Branch{
474+
Name: branch,
475+
Target: result.Repository.Commit,
476+
}
477+
478+
return result.Repository, nil
479+
}
480+
441481
// TODO: search result alerts.
442482
const repositorySearchQuery = `
443483
query ChangesetRepos(
444484
$query: String!,
485+
$queryCommit: Boolean!,
486+
$rev: String!,
445487
) {
446488
search(query: $query, version: V2) {
447489
results {
@@ -471,7 +513,9 @@ func (svc *Service) resolveRepositorySearch(ctx context.Context, query string) (
471513
}
472514
}
473515
if ok, err := svc.client.NewRequest(repositorySearchQuery, map[string]interface{}{
474-
"query": setDefaultQueryCount(query),
516+
"query": setDefaultQueryCount(query),
517+
"queryCommit": false,
518+
"rev": "",
475519
}).Do(ctx, &result); err != nil || !ok {
476520
return nil, err
477521
}

0 commit comments

Comments
 (0)