Skip to content

Commit cffc85d

Browse files
Merge remote-tracking branch 'upstream/main' into feat/gerrit-adapter
# Conflicts: # README.md # internal/cli/auth.go # internal/config/config.go
2 parents 5d4d470 + 6a0dcf4 commit cffc85d

46 files changed

Lines changed: 1871 additions & 280 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ jobs:
1616
runs-on: ${{ matrix.os }}
1717

1818
steps:
19-
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
19+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
2020
with:
2121
persist-credentials: false
2222

2323
- name: Set up Go
24-
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
24+
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
2525
with:
2626
go-version-file: go.mod
2727

@@ -42,12 +42,12 @@ jobs:
4242
lint:
4343
runs-on: ubuntu-latest
4444
steps:
45-
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
45+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
4646
with:
4747
persist-credentials: false
4848

4949
- name: Set up Go
50-
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
50+
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
5151
with:
5252
go-version-file: go.mod
5353

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ jobs:
1414
runs-on: ubuntu-latest
1515

1616
steps:
17-
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
17+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
1818
with:
1919
fetch-depth: 0
2020
persist-credentials: false
2121

2222
- uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
2323

2424
- name: Set up Go
25-
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
25+
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
2626
with:
2727
go-version-file: go.mod
2828
cache: false

README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,18 @@ forge auth login # interactive: asks domain + token
4343
forge auth login --domain github.com --token ghp_abc123
4444
forge auth login --domain gitea.example.com --token abc123 --type gitea
4545
forge auth login --domain gerrit.example.com --token user:http_password --type gerrit
46+
forge auth login --domain github.com --token-cmd 'rbw get github-token'
47+
```
48+
49+
`--token-cmd` stores a shell command instead of a literal token; the command
50+
is run each time the token is needed (see [token commands](#token-commands) below).
51+
52+
When prompted for a token interactively, press **Ctrl+E** as the first key
53+
to enter a command instead:
54+
55+
```
56+
Token for github.com (Ctrl+E first for command):
57+
Command for token (e.g. rbw get github.com): rbw get github-token
4658
```
4759

4860
Check what's configured with `forge auth status`.
@@ -71,6 +83,38 @@ type = gerrit
7183
token = user:http_password
7284
```
7385

86+
### Token commands
87+
88+
Instead of a literal `token`, use `token-cmd` to specify a shell command (not supported on Windows).
89+
The command is executed via `sh -c` each time forge needs the token and its
90+
stdout is used as the value. This lets you fetch secrets from a password manager
91+
instead of storing them in plain text:
92+
93+
```ini
94+
[github.com]
95+
token-cmd = rbw get github-token
96+
97+
[gitlab.com]
98+
token-cmd = pass show forge/gitlab
99+
100+
[myhostedgitlab.example.com]
101+
token-cmd = rbw get --raw myhostedgitlab | jq -r '.fields | map(select(.name == "token"))[0].value'
102+
```
103+
104+
The variable `FORGE_DOMAIN` is set to the domain name when the command runs,
105+
so a single command can serve multiple domains:
106+
107+
```ini
108+
[github.com]
109+
token-cmd = pass show forge/$FORGE_DOMAIN
110+
111+
[myhostedgitlab.example.com]
112+
token-cmd = pass show forge/$FORGE_DOMAIN
113+
```
114+
115+
`forge auth login` sets this up interactively (Ctrl+E at the token prompt).
116+
`forge auth status` shows the command source instead of the resolved value.
117+
74118
`.forge` in the repo root is for per-project settings, committed to the repo, no tokens:
75119

76120
```ini

bitbucket/helpers_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ package bitbucket
22

33
import "testing"
44

5-
func assertEqual(t *testing.T, field, want, got string) {
5+
func assertEqual[T ~string](t *testing.T, field, want string, got T) {
66
t.Helper()
7-
if want != got {
7+
if want != string(got) {
88
t.Errorf("%s: want %q, got %q", field, want, got)
99
}
1010
}

bitbucket/issues.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,7 @@ func convertBitbucketIssue(bb bbIssue) forge.Issue {
107107
HTMLURL: bb.Links.HTML.Href,
108108
}
109109

110-
// Normalize Bitbucket states to open/closed
111-
switch bb.State {
112-
case "new", stateOpen:
113-
result.State = stateOpen
114-
default:
115-
result.State = stateClosed
116-
}
110+
result.State = forge.NormalizeIssueState(bb.State)
117111

118112
if bb.Reporter != nil {
119113
result.Author = forge.User{

bitbucket/prs.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -123,14 +123,9 @@ func convertBitbucketPR(bb bbPullRequest) forge.PullRequest {
123123
}
124124
}
125125

126-
switch bb.State {
127-
case "OPEN":
128-
result.State = "open"
129-
case "MERGED":
130-
result.State = "merged"
126+
result.State = forge.NormalizePRStatus(bb.State)
127+
if result.State == forge.PRStatusMerged {
131128
result.Merged = true
132-
default:
133-
result.State = "closed"
134129
}
135130

136131
if bb.Author != nil {

gerrit/changes.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,16 +79,16 @@ func (s *gerritPRService) convertAccount(a *gerritAccountInfo) forge.User {
7979
}
8080

8181
func (s *gerritPRService) convertChange(c gerritChangeInfo) forge.PullRequest {
82-
state := strings.ToLower(c.Status)
82+
state := forge.NormalizePRStatus(strings.ToLower(c.Status))
8383
merged := false
8484
switch c.Status {
8585
case "NEW":
86-
state = stateOpen
86+
state = forge.PRStatusOpen
8787
case "MERGED":
88-
state = stateMerged
88+
state = forge.PRStatusMerged
8989
merged = true
9090
case "ABANDONED":
91-
state = stateClosed
91+
state = forge.PRStatusClosed
9292
}
9393

9494
head := forge.PRBranch{SHA: c.CurrentRevision}

gitea/ci.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func convertGiteaWorkflowRun(r *gitea.ActionWorkflowRun) forge.CIRun {
2323
result := forge.CIRun{
2424
ID: r.ID,
2525
Title: r.DisplayTitle,
26-
Status: r.Status,
26+
Status: forge.NormalizeCIStatus(r.Status),
2727
Branch: r.HeadBranch,
2828
SHA: r.HeadSha,
2929
Event: r.Event,
@@ -32,7 +32,7 @@ func convertGiteaWorkflowRun(r *gitea.ActionWorkflowRun) forge.CIRun {
3232
}
3333

3434
if r.Conclusion != "" {
35-
result.Conclusion = r.Conclusion
35+
result.Conclusion = forge.NormalizeCIConclusion(r.Conclusion)
3636
}
3737

3838
if r.Actor != nil {
@@ -54,8 +54,8 @@ func convertGiteaWorkflowJob(j *gitea.ActionWorkflowJob) forge.CIJob {
5454
job := forge.CIJob{
5555
ID: j.ID,
5656
Name: j.Name,
57-
Status: j.Status,
58-
Conclusion: j.Conclusion,
57+
Status: forge.NormalizeCIStatus(j.Status),
58+
Conclusion: forge.NormalizeCIConclusion(j.Conclusion),
5959
HTMLURL: j.HTMLURL,
6060
}
6161
if !j.StartedAt.IsZero() {

gitea/collaborators.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func (s *giteaCollaboratorService) List(ctx context.Context, owner, repo string,
4141
}
4242
all = append(all, forge.Collaborator{
4343
Login: u.UserName,
44-
Permission: perm,
44+
Permission: forge.NormalizeAccessLevel(perm),
4545
})
4646
}
4747
if lastPage(resp, len(users), perPage) || (opts.Limit > 0 && len(all) >= opts.Limit) {
@@ -78,7 +78,7 @@ func (s *giteaCollaboratorService) getPermission(owner, repo, username string) (
7878
func (s *giteaCollaboratorService) Add(ctx context.Context, owner, repo, username string, opts forge.AddCollaboratorOpts) error {
7979
var perm *gitea.AccessMode
8080
if opts.Permission != "" {
81-
mode := gitea.AccessMode(opts.Permission)
81+
mode := gitea.AccessMode(giteaPermission(opts.Permission))
8282
perm = &mode
8383
}
8484

@@ -94,6 +94,19 @@ func (s *giteaCollaboratorService) Add(ctx context.Context, owner, repo, usernam
9494
return nil
9595
}
9696

97+
func giteaPermission(permission forge.AccessLevel) string {
98+
switch forge.NormalizeAccessLevel(string(permission)) {
99+
case forge.AccessLevelRead:
100+
return "read"
101+
case forge.AccessLevelWrite:
102+
return "write"
103+
case forge.AccessLevelAdmin:
104+
return "admin"
105+
default:
106+
return string(permission)
107+
}
108+
}
109+
97110
func (s *giteaCollaboratorService) Remove(ctx context.Context, owner, repo, username string) error {
98111
resp, err := s.client.DeleteCollaborator(owner, repo, username)
99112
if err != nil {

gitea/commit_statuses.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func (s *giteaCommitStatusService) List(ctx context.Context, owner, repo, sha st
5757
}
5858
for _, st := range statuses {
5959
cs := forge.CommitStatus{
60-
State: string(st.State),
60+
State: forge.NormalizeCommitStatusState(string(st.State)),
6161
Context: st.Context,
6262
Description: st.Description,
6363
TargetURL: st.TargetURL,
@@ -78,7 +78,7 @@ func (s *giteaCommitStatusService) List(ctx context.Context, owner, repo, sha st
7878

7979
func (s *giteaCommitStatusService) Set(ctx context.Context, owner, repo, sha string, opts forge.SetCommitStatusOpts) (*forge.CommitStatus, error) {
8080
result, resp, err := s.client.CreateStatus(owner, repo, sha, gitea.CreateStatusOption{
81-
State: gitea.StatusState(opts.State),
81+
State: gitea.StatusState(string(opts.State)),
8282
TargetURL: opts.TargetURL,
8383
Description: opts.Description,
8484
Context: opts.Context,
@@ -91,7 +91,7 @@ func (s *giteaCommitStatusService) Set(ctx context.Context, owner, repo, sha str
9191
}
9292

9393
cs := &forge.CommitStatus{
94-
State: string(result.State),
94+
State: forge.NormalizeCommitStatusState(string(result.State)),
9595
Context: result.Context,
9696
Description: result.Description,
9797
TargetURL: result.TargetURL,

0 commit comments

Comments
 (0)