Make missing workflow regexp aware of GitHub App

Follow up of https://github.com/cli/cli/pull/7612

The `missingWorkflowScopeRE` is defined to capture
the error message when the `GH_TOKEN` does not have
`workflow` scope in `gh repo sync <remote>`,
but this is only intended for error messages for
OAuth Apps and does not work with GitHub Apps.

In GitHub App, you will get the following error:

```
{
  "message": "refusing to allow a GitHub App to create or update workflow `.github/workflows/teamcity-pr-checks.yml` without `workflows` permission",
  "documentation_url": "https://docs.github.com/rest/branches/branches#sync-a-fork-branch-with-the-upstream-repository",
  "status": "422"
}
```

As you can see above, the existing regexp does not
match the "`workflows` permission".

This change modifies the regexp to return
the user-friendly error message when the `workflow`
permission is missing, even in the case of a GitHub App.
This commit is contained in:
Kazuma Watanabe 2025-03-10 03:22:09 +00:00
parent fc19ff321a
commit b01288617a
2 changed files with 40 additions and 4 deletions

View file

@ -32,8 +32,8 @@ func latestCommit(client *api.Client, repo ghrepo.Interface, branch string) (com
type upstreamMergeErr struct{ error }
var missingWorkflowScopeRE = regexp.MustCompile("refusing to allow.*without `workflow` scope")
var missingWorkflowScopeErr = errors.New("Upstream commits contain workflow changes, which require the `workflow` scope to merge. To request it, run: gh auth refresh -s workflow")
var missingWorkflowScopeRE = regexp.MustCompile("refusing to allow.*without `workflow(s)?` (scope|permission)")
var missingWorkflowScopeErr = errors.New("Upstream commits contain workflow changes, which require the `workflow` scope or permission to merge. To request it, run: gh auth refresh -s workflow")
func triggerUpstreamMerge(client *api.Client, repo ghrepo.Interface, branch string) (string, error) {
var payload bytes.Buffer

View file

@ -470,7 +470,7 @@ func Test_SyncRun(t *testing.T) {
errMsg: "trunk branch does not exist on OWNER/REPO-FORK repository",
},
{
name: "sync remote fork with missing workflow scope on token",
name: "sync remote fork with missing workflow scope on OAuth App token",
opts: &SyncOptions{
DestArg: "FORKOWNER/REPO-FORK",
},
@ -485,7 +485,43 @@ func Test_SyncRun(t *testing.T) {
}{Message: "refusing to allow an OAuth App to create or update workflow `.github/workflows/unimportant.yml` without `workflow` scope"}))
},
wantErr: true,
errMsg: "Upstream commits contain workflow changes, which require the `workflow` scope to merge. To request it, run: gh auth refresh -s workflow",
errMsg: "Upstream commits contain workflow changes, which require the `workflow` scope or permission to merge. To request it, run: gh auth refresh -s workflow",
},
{
name: "sync remote fork with missing workflow permission on GitHub App token",
opts: &SyncOptions{
DestArg: "FORKOWNER/REPO-FORK",
},
httpStubs: func(reg *httpmock.Registry) {
reg.Register(
httpmock.GraphQL(`query RepositoryInfo\b`),
httpmock.StringResponse(`{"data":{"repository":{"defaultBranchRef":{"name": "trunk"}}}}`))
reg.Register(
httpmock.REST("POST", "repos/FORKOWNER/REPO-FORK/merge-upstream"),
httpmock.StatusJSONResponse(422, struct {
Message string `json:"message"`
}{Message: "refusing to allow a GitHub App to create or update workflow `.github/workflows/unimportant.yml` without `workflows` permission"}))
},
wantErr: true,
errMsg: "Upstream commits contain workflow changes, which require the `workflow` scope or permission to merge. To request it, run: gh auth refresh -s workflow",
},
{
name: "sync remote fork with missing workflow scope on personal access token",
opts: &SyncOptions{
DestArg: "FORKOWNER/REPO-FORK",
},
httpStubs: func(reg *httpmock.Registry) {
reg.Register(
httpmock.GraphQL(`query RepositoryInfo\b`),
httpmock.StringResponse(`{"data":{"repository":{"defaultBranchRef":{"name": "trunk"}}}}`))
reg.Register(
httpmock.REST("POST", "repos/FORKOWNER/REPO-FORK/merge-upstream"),
httpmock.StatusJSONResponse(422, struct {
Message string `json:"message"`
}{Message: "refusing to allow a Personal Access Token to create or update workflow `.github/workflows/unimportant.yml` without `workflow` scope"}))
},
wantErr: true,
errMsg: "Upstream commits contain workflow changes, which require the `workflow` scope or permission to merge. To request it, run: gh auth refresh -s workflow",
},
}
for _, tt := range tests {