fix: adjust workflow link for pull_request_target workflow runs (#12734)

Fixes #12660, reported by @mahlzahn.

### Tests for Go changes

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [ ] <s>`make pr-go` before pushing</s> because the OOM killer kills it before it does anything useful

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12734
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
This commit is contained in:
Antonin Delpeuch
2026-06-01 15:03:29 +02:00
committed by Mathieu Fenniak
parent 2e8380025c
commit 19e1f58144
7 changed files with 100 additions and 2 deletions
+10 -1
View File
@@ -63,6 +63,15 @@ func View(ctx *app_context.Context) {
return
}
workflowDefinitionCommitSHA := job.Run.CommitSHA
// if the trigger event is `pull_request_target`, then the definition of the workflow is taken
// from the base branch instead of the commit the workflow is triggered on
if job.Run.TriggerEvent == actions.GithubEventPullRequestTarget {
if pullPayload, err := job.Run.GetPullRequestEventPayload(); err == nil && pullPayload.PullRequest != nil && pullPayload.PullRequest.Base != nil {
workflowDefinitionCommitSHA = pullPayload.PullRequest.Base.Sha
}
}
workflowName := job.Run.WorkflowID
ctx.Data["RunIndex"] = runIndex
@@ -72,7 +81,7 @@ func View(ctx *app_context.Context) {
ctx.Data["AttemptNumber"] = attemptNumber
ctx.Data["WorkflowName"] = workflowName
ctx.Data["WorkflowURL"] = ctx.Repo.RepoLink + "/actions?workflow=" + workflowName
ctx.Data["WorkflowSourceURL"] = ctx.Repo.RepoLink + "/src/commit/" + job.Run.CommitSHA + "/" + job.Run.WorkflowPath()
ctx.Data["WorkflowSourceURL"] = ctx.Repo.RepoLink + "/src/commit/" + workflowDefinitionCommitSHA + "/" + job.Run.WorkflowPath()
viewResponse := getViewResponse(ctx, &ViewRequest{}, runIndex, jobIndex, attemptNumber)
if ctx.Written() {
+15
View File
@@ -139,6 +139,7 @@ func TestActionViewsView(t *testing.T) {
runIndex int64
jobIndex int64
attempt int64
workflowSourceURL string
expectedJSON string
expectedArtifacts string
}{
@@ -148,6 +149,7 @@ func TestActionViewsView(t *testing.T) {
runIndex: 187,
jobIndex: 0,
attempt: 3,
workflowSourceURL: "/user5/repo4/src/commit/c2d72f548424103f01ee1dc02889c1e2bff816b0/.forgejo/workflows/artifact.yaml",
expectedJSON: "{\"state\":{\"run\":{\"preExecutionError\":\"\",\"link\":\"/user5/repo4/actions/runs/187\",\"title\":\"update actions\",\"titleHTML\":\"update actions\",\"status\":\"success\",\"canCancel\":false,\"canDelete\":false,\"canApprove\":false,\"canRerun\":false,\"canDeleteArtifact\":false,\"description\":\"Commit <a href=\\\"/user5/repo4/commit/c2d72f548424103f01ee1dc02889c1e2bff816b0\\\">c2d72f5484</a> pushed by <a href=\\\"/user1\\\">user1</a>\",\"done\":true,\"jobs\":[{\"id\":192,\"name\":\"job_2\",\"status\":\"success\",\"canRerun\":false,\"duration\":\"_duration_\"}],\"commit\":{\"localeWorkflow\":\"Workflow\",\"localeAllRuns\":\"all runs\",\"shortSHA\":\"c2d72f5484\",\"link\":\"/user5/repo4/commit/c2d72f548424103f01ee1dc02889c1e2bff816b0\",\"pusher\":{\"displayName\":\"user1\",\"link\":\"/user1\"},\"branch\":{\"name\":\"master\",\"link\":\"/user5/repo4/src/branch/master\",\"isDeleted\":false}}},\"currentJob\":{\"title\":\"job_2\",\"details\":[\"Success\"],\"steps\":[{\"summary\":\"Set up job\",\"duration\":\"_duration_\",\"status\":\"running\"},{\"summary\":\"Complete job\",\"duration\":\"_duration_\",\"status\":\"waiting\"}],\"allAttempts\":[{\"number\":3,\"time_since_started_html\":\"_time_\",\"status\":\"running\",\"status_diagnostics\":[\"Running\"]},{\"number\":2,\"time_since_started_html\":\"_time_\",\"status\":\"success\",\"status_diagnostics\":[\"Success\"]},{\"number\":1,\"time_since_started_html\":\"_time_\",\"status\":\"success\",\"status_diagnostics\":[\"Success\"]}]}},\"logs\":{\"stepsLog\":[]}}\n",
expectedArtifacts: "{\"artifacts\":[{\"name\":\"multi-file-download\",\"size\":2048,\"status\":\"completed\"}]}\n",
},
@@ -157,6 +159,7 @@ func TestActionViewsView(t *testing.T) {
runIndex: 209,
jobIndex: 0,
attempt: 1,
workflowSourceURL: "/user5/repo4/src/commit/64357baca84bfff631e7dfae5a3433b26d005646/.forgejo/workflows/scheduled.yaml",
expectedJSON: "{\"state\":{\"run\":{\"link\":\"/user5/repo4/actions/runs/209\",\"title\":\"A scheduled workflow\",\"titleHTML\":\"A scheduled workflow\",\"status\":\"waiting\",\"description\":\"Scheduled run of commit \\u003ca href=\\\"/user5/repo4/commit/64357baca84bfff631e7dfae5a3433b26d005646\\\"\\u003e64357baca8\\u003c/a\\u003e\",\"canCancel\":false,\"canDelete\":false,\"canApprove\":false,\"canRerun\":false,\"canDeleteArtifact\":false,\"done\":false,\"jobs\":[{\"id\":2153,\"name\":\"job_2\",\"status\":\"waiting\",\"canRerun\":false,\"duration\":\"_duration_\"}],\"commit\":{\"localeWorkflow\":\"Workflow\",\"localeAllRuns\":\"all runs\",\"shortSHA\":\"64357baca8\",\"link\":\"/user5/repo4/commit/64357baca84bfff631e7dfae5a3433b26d005646\",\"pusher\":{\"displayName\":\"forgejo-actions\",\"link\":\"/forgejo-actions\"},\"branch\":{\"name\":\"master\",\"link\":\"/user5/repo4/src/branch/master\",\"isDeleted\":false}},\"preExecutionError\":\"\"},\"currentJob\":{\"title\":\"job_2\",\"details\":[\"Waiting for a runner with the following labels: debian, gpu\"],\"steps\":[{\"summary\":\"Set up job\",\"duration\":\"_duration_\",\"status\":\"success\"},{\"summary\":\"Complete job\",\"duration\":\"_duration_\",\"status\":\"success\"}],\"allAttempts\":[{\"number\":1,\"time_since_started_html\":\"-\",\"status\":\"success\",\"status_diagnostics\":[\"Success\"]}]}},\"logs\":{\"stepsLog\":[]}}\n",
expectedArtifacts: "{\"artifacts\":[]}\n",
},
@@ -166,9 +169,20 @@ func TestActionViewsView(t *testing.T) {
runIndex: 210,
jobIndex: 0,
attempt: 1,
workflowSourceURL: "/user5/repo4/src/commit/f4100ac14112a3740490afb22b07b69b0b5d4e8b/.forgejo/workflows/dispatch.yaml",
expectedJSON: "{\"state\":{\"run\":{\"link\":\"/user5/repo4/actions/runs/210\",\"title\":\"A triggered run\",\"titleHTML\":\"A triggered run\",\"status\":\"waiting\",\"description\":\"Run of commit \\u003ca href=\\\"/user5/repo4/commit/f4100ac14112a3740490afb22b07b69b0b5d4e8b\\\"\\u003ef4100ac141\\u003c/a\\u003e triggered by \\u003ca href=\\\"/user29\\\"\\u003euser29\\u003c/a\\u003e\",\"canCancel\":false,\"canDelete\":false,\"canApprove\":false,\"canRerun\":false,\"canDeleteArtifact\":false,\"done\":false,\"jobs\":[{\"id\":2154,\"name\":\"mirror\",\"status\":\"waiting\",\"canRerun\":false,\"duration\":\"_duration_\"}],\"commit\":{\"localeWorkflow\":\"Workflow\",\"localeAllRuns\":\"all runs\",\"shortSHA\":\"f4100ac141\",\"link\":\"/user5/repo4/commit/f4100ac14112a3740490afb22b07b69b0b5d4e8b\",\"pusher\":{\"displayName\":\"user29\",\"link\":\"/user29\"},\"branch\":{\"name\":\"master\",\"link\":\"/user5/repo4/src/branch/master\",\"isDeleted\":false}},\"preExecutionError\":\"\"},\"currentJob\":{\"title\":\"mirror\",\"details\":[\"Waiting for a runner with the following label: windows\"],\"steps\":[{\"summary\":\"Set up job\",\"duration\":\"_duration_\",\"status\":\"running\"},{\"summary\":\"Complete job\",\"duration\":\"_duration_\",\"status\":\"waiting\"}],\"allAttempts\":[{\"number\":1,\"time_since_started_html\":\"-\",\"status\":\"waiting\",\"status_diagnostics\":[\"Waiting for a runner with the following label: windows\"]}]}},\"logs\":{\"stepsLog\":[]}}\n",
expectedArtifacts: "{\"artifacts\":[]}\n",
},
{
name: "pull_request_target",
url: "/user5/repo4/actions/runs/211",
runIndex: 211,
jobIndex: 0,
attempt: 1,
workflowSourceURL: "/user5/repo4/src/commit/deadbeef/.forgejo/workflows/pull_request_target.yaml",
expectedJSON: "{\"state\":{\"run\":{\"link\":\"/user5/repo4/actions/runs/211\",\"title\":\"A pull_request_target run\",\"titleHTML\":\"A pull_request_target run\",\"status\":\"waiting\",\"description\":\"Commit \\u003ca href=\\\"/user5/repo4/commit/f4100ac14112a3740490afb22b07b69b0b5d4e8b\\\"\\u003ef4100ac141\\u003c/a\\u003e pushed by \\u003ca href=\\\"/user29\\\"\\u003euser29\\u003c/a\\u003e\",\"canCancel\":false,\"canApprove\":false,\"canRerun\":false,\"canDeleteArtifact\":false,\"canDelete\":false,\"done\":false,\"jobs\":[{\"id\":2155,\"name\":\"target_job\",\"status\":\"waiting\",\"canRerun\":false,\"duration\":\"_duration_\"}],\"commit\":{\"localeWorkflow\":\"Workflow\",\"localeAllRuns\":\"all runs\",\"shortSHA\":\"f4100ac141\",\"link\":\"/user5/repo4/commit/f4100ac14112a3740490afb22b07b69b0b5d4e8b\",\"pusher\":{\"displayName\":\"user29\",\"link\":\"/user29\"},\"branch\":{\"name\":\"master\",\"link\":\"/user5/repo4/src/branch/master\",\"isDeleted\":false}},\"preExecutionError\":\"\"},\"currentJob\":{\"title\":\"target_job\",\"details\":[\"Waiting for a runner with the following label: macos\"],\"steps\":[{\"summary\":\"Set up job\",\"duration\":\"_duration_\",\"status\":\"running\"},{\"summary\":\"Complete job\",\"duration\":\"_duration_\",\"status\":\"waiting\"}],\"allAttempts\":[{\"number\":1,\"time_since_started_html\":\"-\",\"status\":\"waiting\",\"status_diagnostics\":[\"Waiting for a runner with the following label: macos\"]}]}},\"logs\":{\"stepsLog\":[]}}\n",
expectedArtifacts: "{\"artifacts\":[]}\n",
},
}
for _, testCase := range testCases {
@@ -186,6 +200,7 @@ func TestActionViewsView(t *testing.T) {
htmlDoc.AssertAttrEqual(t, selector, "data-run-index", strconv.FormatInt(testCase.runIndex, 10))
htmlDoc.AssertAttrEqual(t, selector, "data-job-index", strconv.FormatInt(testCase.jobIndex, 10))
htmlDoc.AssertAttrEqual(t, selector, "data-attempt-number", strconv.FormatInt(testCase.attempt, 10))
htmlDoc.AssertAttrEqual(t, selector, "data-workflow-source-url", testCase.workflowSourceURL)
htmlDoc.AssertAttrPredicate(t, selector, "data-initial-post-response", func(actual string) {
// Remove dynamic "duration" fields for comparison.
pattern := `"duration":"[^"]*"`
@@ -32,3 +32,22 @@
updated: 0
need_approval: false
approved_by: 0
- id: 1002
title: "A pull_request_target run"
repo_id: 4
owner_id: 5
workflow_id: "pull_request_target.yaml"
index: 211
trigger_user_id: 29
ref: "refs/heads/master"
commit_sha: "f4100ac14112a3740490afb22b07b69b0b5d4e8b"
event: "pull_request"
trigger_event: "pull_request_target"
event_payload: "{\"pull_request\":{\"id\":1,\"base\":{\"sha\":\"deadbeef\"}}}"
is_fork_pull_request: false
status: 5 # waiting
started: 0
created: 1683636108
updated: 0
need_approval: false
approved_by: 0
@@ -26,3 +26,17 @@
status: 5 # StatusWaiting
started: 0
stopped: 0
- id: 2155
run_id: 1002
repo_id: 4
owner_id: 5
runs_on: ["macos"]
commit_sha: f4100ac14112a3740490afb22b07b69b0b5d4e8b
is_fork_pull_request: false
name: target_job
attempt: 1
job_id: target_job
task_id: 8755
status: 5 # StatusWaiting
started: 0
stopped: 0
@@ -26,3 +26,17 @@
token_hash: 9c104fe0db29aa6d737001707e1de2201fdfefb6d2316ec4fb38c44a1820a5948af2f9e1cb5e58ab95cc8fbe589fd4e82f95
token_salt: ffffffffff
token_last_eight: ffffffff
- id: 8755
job_id: 2155
attempt: 1
runner_id: 0
status: 5 # Waiting
started: 0
stopped: 0
repo_id: 4
owner_id: 5
commit_sha: f4100ac14112a3740490afb22b07b69b0b5d4e8b
is_fork_pull_request: false
token_hash: e0db29aa6d737001707e1de2201fdfefb6d2316ec4fb38c44a1820a5948af2f9e1cb5e58ab95cc8fbe589fd4e82f959c104f
token_salt: ffffffffff
token_last_eight: ffffffff
@@ -0,0 +1,15 @@
- id: 26
repo_id: 4
index: 1
poster_id: 2
original_author_id: 0
name: PR
content: 'hello'
milestone_id: 0
priority: 0
is_closed: false
is_pull: true
num_comments: 0
created_unix: 1764879458
updated_unix: 1764879458
is_locked: false
@@ -0,0 +1,12 @@
- id: 13
type: 0
status: 2 # mergeable
issue_id: 26
index: 1
head_repo_id: 4
base_repo_id: 4
head_branch: branch2
base_branch: master
merge_base: deadbeef
has_merged: false