detached 8d436fd

test: share a scoped token builder and tidy the branch tests

Adds scopedToken in place of name2, renames the e2e anyRepo token, and drops the
SchemaVersion pin that the upgrade subtest already covers.
commit
8d436fd961e95d385dd0be6e4a7080360c763cd1
author
brice · · 2026-10-12 16:14 UTC
parent
160bcbb
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
3 files · +13 -20
M internal/adapters/kvstore/store_test.go +0 -1
@@ -197,7 +197,6 @@ func TestSchema(t *testing.T) {
197197 require.NoError(t, err)
198198 require.NoError(t, s.Close(ctx))
199199 assert.Equal(t, uint32(kvstore.SchemaVersion), readSchema(t, dir))
200- assert.Equal(t, uint32(2), uint32(kvstore.SchemaVersion), "branch prefixes need schema 2")
201200 })
202201
203202 t.Run("current is accepted and kept", func(t *testing.T) {
@@ -197,7 +197,6 @@ func TestSchema(t *testing.T) {
197 require.NoError(t, err)197 require.NoError(t, err)
198 require.NoError(t, s.Close(ctx))198 require.NoError(t, s.Close(ctx))
199 assert.Equal(t, uint32(kvstore.SchemaVersion), readSchema(t, dir))199 assert.Equal(t, uint32(kvstore.SchemaVersion), readSchema(t, dir))
200- assert.Equal(t, uint32(2), uint32(kvstore.SchemaVersion), "branch prefixes need schema 2")
201 })200 })
202 201
203 t.Run("current is accepted and kept", func(t *testing.T) {202 t.Run("current is accepted and kept", func(t *testing.T) {
M internal/app/e2e_branches_test.go +4 -4
@@ -105,12 +105,12 @@ func TestAC5BranchLimitedToken(t *testing.T) {
105105 out, err = h.git(wt, "push", "-q", h.urlAuth(secret, "/brand-new.git"), "agent/claude/x")
106106 require.Error(t, err, out)
107107 assert.NoDirExists(t, h.repoDir("brand-new"))
108- unlimited, _ := h.branchToken(scopes(domain.ScopeRepoWrite), []string{"agent/claude/"}) // not limited to a repository
109- out, err = h.git(wt, "push", "-q", h.urlAuth(unlimited, "/brand-new.git"), "agent/claude/x")
108+ anyRepo, _ := h.branchToken(scopes(domain.ScopeRepoWrite), []string{"agent/claude/"}) // not limited to a repository
109+ out, err = h.git(wt, "push", "-q", h.urlAuth(anyRepo, "/brand-new.git"), "agent/claude/x")
110110 require.Error(t, err, out)
111111 assert.NoDirExists(t, h.repoDir("brand-new"))
112- assert.Equal(t, 404, h.statusAuth("GET", "/brand-new.git/info/refs?service=git-receive-pack", unlimited))
113- _, err = h.api(unlimited).repo.CreateRepo(h.ctx, connect.NewRequest(&pb.CreateRepoRequest{Name: "via-api"}))
112+ assert.Equal(t, 404, h.statusAuth("GET", "/brand-new.git/info/refs?service=git-receive-pack", anyRepo))
113+ _, err = h.api(anyRepo).repo.CreateRepo(h.ctx, connect.NewRequest(&pb.CreateRepoRequest{Name: "via-api"}))
114114 assert.Equal(t, "permission_denied", codeName(err))
115115 assert.NoDirExists(t, h.repoDir("via-api"))
116116 // The same token without prefixes does both.
@@ -105,12 +105,12 @@ func TestAC5BranchLimitedToken(t *testing.T) {
105 out, err = h.git(wt, "push", "-q", h.urlAuth(secret, "/brand-new.git"), "agent/claude/x")105 out, err = h.git(wt, "push", "-q", h.urlAuth(secret, "/brand-new.git"), "agent/claude/x")
106 require.Error(t, err, out)106 require.Error(t, err, out)
107 assert.NoDirExists(t, h.repoDir("brand-new"))107 assert.NoDirExists(t, h.repoDir("brand-new"))
108- unlimited, _ := h.branchToken(scopes(domain.ScopeRepoWrite), []string{"agent/claude/"}) // not limited to a repository108+ anyRepo, _ := h.branchToken(scopes(domain.ScopeRepoWrite), []string{"agent/claude/"}) // not limited to a repository
109- out, err = h.git(wt, "push", "-q", h.urlAuth(unlimited, "/brand-new.git"), "agent/claude/x")109+ out, err = h.git(wt, "push", "-q", h.urlAuth(anyRepo, "/brand-new.git"), "agent/claude/x")
110 require.Error(t, err, out)110 require.Error(t, err, out)
111 assert.NoDirExists(t, h.repoDir("brand-new"))111 assert.NoDirExists(t, h.repoDir("brand-new"))
112- assert.Equal(t, 404, h.statusAuth("GET", "/brand-new.git/info/refs?service=git-receive-pack", unlimited))112+ assert.Equal(t, 404, h.statusAuth("GET", "/brand-new.git/info/refs?service=git-receive-pack", anyRepo))
113- _, err = h.api(unlimited).repo.CreateRepo(h.ctx, connect.NewRequest(&pb.CreateRepoRequest{Name: "via-api"}))113+ _, err = h.api(anyRepo).repo.CreateRepo(h.ctx, connect.NewRequest(&pb.CreateRepoRequest{Name: "via-api"}))
114 assert.Equal(t, "permission_denied", codeName(err))114 assert.Equal(t, "permission_denied", codeName(err))
115 assert.NoDirExists(t, h.repoDir("via-api"))115 assert.NoDirExists(t, h.repoDir("via-api"))
116 // The same token without prefixes does both.116 // The same token without prefixes does both.
M internal/usecase/repos_test.go +9 -15
@@ -191,8 +191,10 @@ func TestCreate(t *testing.T) {
191191 })
192192 }
193193
194-func tokenPrincipal(s domain.Scope, repos ...string) domain.Principal {
195- tok := domain.Token{ID: "t", Scopes: []domain.Scope{s}}
194+// scopedToken is the principal of a token with one scope, limited to the
195+// repositories and to the branch prefixes given (none means no limit).
196+func scopedToken(s domain.Scope, prefixes []string, repos ...string) domain.Principal {
197+ tok := domain.Token{ID: "t", Scopes: []domain.Scope{s}, BranchPrefixes: prefixes}
196198 for _, r := range repos {
197199 n, err := domain.ParseRepoName(r)
198200 if err != nil {
@@ -203,22 +205,14 @@ func tokenPrincipal(s domain.Scope, repos ...string) domain.Principal {
203205 return domain.TokenPrincipal(tok)
204206 }
205207
208+func tokenPrincipal(s domain.Scope, repos ...string) domain.Principal {
209+ return scopedToken(s, nil, repos...)
210+}
211+
206212 // branchLimited is a token with one scope, optionally limited to repositories,
207213 // and limited to the branches under "agent/".
208214 func branchLimited(s domain.Scope, repos ...string) domain.Principal {
209- tok := domain.Token{ID: "t", Scopes: []domain.Scope{s}, BranchPrefixes: []string{"agent/"}}
210- for _, r := range repos {
211- tok.Repos = append(tok.Repos, name2(r))
212- }
213- return domain.TokenPrincipal(tok)
214-}
215-
216-func name2(s string) domain.RepoName {
217- n, err := domain.ParseRepoName(s)
218- if err != nil {
219- panic(err)
220- }
221- return n
215+ return scopedToken(s, []string{"agent/"}, repos...)
222216 }
223217
224218 func TestGetAndListAccess(t *testing.T) {
@@ -191,8 +191,10 @@ func TestCreate(t *testing.T) {
191 })191 })
192 }192 }
193 193
194-func tokenPrincipal(s domain.Scope, repos ...string) domain.Principal {194+// scopedToken is the principal of a token with one scope, limited to the
195- tok := domain.Token{ID: "t", Scopes: []domain.Scope{s}}195+// repositories and to the branch prefixes given (none means no limit).
196+func scopedToken(s domain.Scope, prefixes []string, repos ...string) domain.Principal {
197+ tok := domain.Token{ID: "t", Scopes: []domain.Scope{s}, BranchPrefixes: prefixes}
196 for _, r := range repos {198 for _, r := range repos {
197 n, err := domain.ParseRepoName(r)199 n, err := domain.ParseRepoName(r)
198 if err != nil {200 if err != nil {
@@ -203,22 +205,14 @@ func tokenPrincipal(s domain.Scope, repos ...string) domain.Principal {
203 return domain.TokenPrincipal(tok)205 return domain.TokenPrincipal(tok)
204 }206 }
205 207
208+func tokenPrincipal(s domain.Scope, repos ...string) domain.Principal {
209+ return scopedToken(s, nil, repos...)
210+}
211+
206 // branchLimited is a token with one scope, optionally limited to repositories,212 // branchLimited is a token with one scope, optionally limited to repositories,
207 // and limited to the branches under "agent/".213 // and limited to the branches under "agent/".
208 func branchLimited(s domain.Scope, repos ...string) domain.Principal {214 func branchLimited(s domain.Scope, repos ...string) domain.Principal {
209- tok := domain.Token{ID: "t", Scopes: []domain.Scope{s}, BranchPrefixes: []string{"agent/"}}215+ return scopedToken(s, []string{"agent/"}, repos...)
210- for _, r := range repos {
211- tok.Repos = append(tok.Repos, name2(r))
212- }
213- return domain.TokenPrincipal(tok)
214-}
215-
216-func name2(s string) domain.RepoName {
217- n, err := domain.ParseRepoName(s)
218- if err != nil {
219- panic(err)
220- }
221- return n
222 }216 }
223 217
224 func TestGetAndListAccess(t *testing.T) {218 func TestGetAndListAccess(t *testing.T) {

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 2

Tags 43

↑↓ moveenter openesc close