From 5eea61dbc8f8e82e0dd05addf76751ee517459a0 Mon Sep 17 00:00:00 2001 From: sillyguodong <33891828+sillyguodong@users.noreply.github.com> Date: Tue, 14 Mar 2023 05:05:19 +0800 Subject: [PATCH] Fix missing commit status in PR which from forked repo (#23351) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit close: #23347 ### Reference and Inference According to Github REST API [doc](https://docs.github.com/en/rest/commits/statuses?apiVersion=2022-11-28#list-commit-statuses-for-a-reference): 1. The `Drone CI` that can create some commit status by [API](https://docs.github.com/en/rest/commits/statuses?apiVersion=2022-11-28#create-a-commit-status) is enabled in `go-gitea/gitea`. So I tried to call the API to get a commit status list of a PR which is commited to upstream repo(`go-gitea/gitea`). As a result, the API returned a array of commit status. ![image](https://user-images.githubusercontent.com/33891828/223913371-313d047a-5e2e-484c-b13e-dcd38748703e.png) 2. Then I tried to call the API to get commit status list of the reference which of the `SHA` is the same as step 1 in the repo which is forked from `go-gitea/gitea`. But I got a empty array. ![image](https://user-images.githubusercontent.com/33891828/223930827-17a64d3c-f466-4980-897c-77fe386c4d3b.png) So, I believe it that: 1. The commit status is not shared between upstream repo and forked repo. 2. The coomit status is bound to a repo that performs actions. (Gitea's logic is the same) ### Cause During debugging, I found it that commit status are not stored in the DB as expected. So, I located the following code: https://github.com/go-gitea/gitea/blob/8cadd51bf295e6ff36ac36efed68cc5de34c9382/services/actions/commit_status.go#L18-L26 When I create a PR, the type of `event` is `pull request`, not `push`. So the code return function directly. ### Screenshot ![image](https://user-images.githubusercontent.com/33891828/223939339-dadf539c-1fdd-40c4-96e9-2e4fa733f531.png) ![image](https://user-images.githubusercontent.com/33891828/223939519-edb02bf0-2478-4ea5-9366-be85468f02db.png) ![image](https://user-images.githubusercontent.com/33891828/223939557-ec6f1375-5536-400e-8987-fb7d2fd452fa.png) ### Other In this PR, I also fix the problem of missing icon which represents running in PRs list. ![image](https://user-images.githubusercontent.com/33891828/223939898-2a0339e4-713f-4c7b-9d99-2250a43f3457.png) ![image](https://user-images.githubusercontent.com/33891828/223939979-037a975f-5ced-480c-bac7-0ee00ebfff4b.png) --- models/actions/run.go | 11 +++++ services/actions/commit_status.go | 75 ++++++++++++++++++++----------- templates/repo/commit_status.tmpl | 3 ++ 3 files changed, 64 insertions(+), 25 deletions(-) diff --git a/models/actions/run.go b/models/actions/run.go index d5ab45a519..a711cfee2e 100644 --- a/models/actions/run.go +++ b/models/actions/run.go @@ -128,6 +128,17 @@ func (run *ActionRun) GetPushEventPayload() (*api.PushPayload, error) { return nil, fmt.Errorf("event %s is not a push event", run.Event) } +func (run *ActionRun) GetPullRequestEventPayload() (*api.PullRequestPayload, error) { + if run.Event == webhook_module.HookEventPullRequest { + var payload api.PullRequestPayload + if err := json.Unmarshal([]byte(run.EventPayload), &payload); err != nil { + return nil, err + } + return &payload, nil + } + return nil, fmt.Errorf("event %s is not a pull request event", run.Event) +} + func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) error { _, err := db.GetEngine(ctx).ID(repo.ID). SetExpr("num_action_runs", diff --git a/services/actions/commit_status.go b/services/actions/commit_status.go index 4f31349352..84de106eec 100644 --- a/services/actions/commit_status.go +++ b/services/actions/commit_status.go @@ -21,35 +21,60 @@ func CreateCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) er } run := job.Run - if run.Event != webhook_module.HookEventPush { + var ( + sha string + creatorID int64 + ) + + switch run.Event { + case webhook_module.HookEventPush: + payload, err := run.GetPushEventPayload() + if err != nil { + return fmt.Errorf("GetPushEventPayload: %w", err) + } + + // Since the payload comes from json data, we should check if it's broken, or it will cause panic + switch { + case payload.Repo == nil: + return fmt.Errorf("repo is missing in event payload") + case payload.Pusher == nil: + return fmt.Errorf("pusher is missing in event payload") + case payload.HeadCommit == nil: + return fmt.Errorf("head commit is missing in event payload") + } + + sha = payload.HeadCommit.ID + creatorID = payload.Pusher.ID + case webhook_module.HookEventPullRequest: + payload, err := run.GetPullRequestEventPayload() + if err != nil { + return fmt.Errorf("GetPullRequestEventPayload: %w", err) + } + + switch { + case payload.PullRequest == nil: + return fmt.Errorf("pull request is missing in event payload") + case payload.PullRequest.Head == nil: + return fmt.Errorf("head of pull request is missing in event payload") + case payload.PullRequest.Head.Repository == nil: + return fmt.Errorf("head repository of pull request is missing in event payload") + case payload.PullRequest.Head.Repository.Owner == nil: + return fmt.Errorf("owner of head repository of pull request is missing in evnt payload") + } + + sha = payload.PullRequest.Head.Sha + creatorID = payload.PullRequest.Head.Repository.Owner.ID + default: return nil } - payload, err := run.GetPushEventPayload() - if err != nil { - return fmt.Errorf("GetPushEventPayload: %w", err) - } - - // Since the payload comes from json data, we should check if it's broken, or it will cause panic - switch { - case payload.Repo == nil: - return fmt.Errorf("repo is missing in event payload") - case payload.Pusher == nil: - return fmt.Errorf("pusher is missing in event payload") - case payload.HeadCommit == nil: - return fmt.Errorf("head commit is missing in event payload") - } - - creator, err := user_model.GetUserByID(ctx, payload.Pusher.ID) + repo := run.Repo + ctxname := job.Name + state := toCommitStatus(job.Status) + creator, err := user_model.GetUserByID(ctx, creatorID) if err != nil { return fmt.Errorf("GetUserByID: %w", err) } - - repo := run.Repo - sha := payload.HeadCommit.ID - ctxname := job.Name - state := toCommitStatus(job.Status) - if statuses, _, err := git_model.GetLatestCommitStatus(ctx, repo.ID, sha, db.ListOptions{}); err == nil { for _, v := range statuses { if v.Context == ctxname { @@ -65,14 +90,14 @@ func CreateCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) er if err := git_model.NewCommitStatus(ctx, git_model.NewCommitStatusOptions{ Repo: repo, - SHA: payload.HeadCommit.ID, + SHA: sha, Creator: creator, CommitStatus: &git_model.CommitStatus{ SHA: sha, TargetURL: run.Link(), Description: "", Context: ctxname, - CreatorID: payload.Pusher.ID, + CreatorID: creatorID, State: state, }, }); err != nil { diff --git a/templates/repo/commit_status.tmpl b/templates/repo/commit_status.tmpl index fbf064527d..470869b381 100644 --- a/templates/repo/commit_status.tmpl +++ b/templates/repo/commit_status.tmpl @@ -1,6 +1,9 @@ {{if eq .State "pending"}} {{svg "octicon-dot-fill" 18 "commit-status icon text yellow"}} {{end}} +{{if eq .State "running"}} + {{svg "octicon-dot-fill" 18 "commit-status icon text yellow"}} +{{end}} {{if eq .State "success"}} {{svg "octicon-check" 18 "commit-status icon text green"}} {{end}}