mirror of
https://github.com/go-gitea/gitea.git
synced 2026-08-16 05:15:03 +00:00
Backport #38886 For a `pull_request_target` (PRT) run, Gitea loads the top-level workflow from the trusted base branch, but any local reusable workflow it calls (`uses: ./...`) was read from the PR **head** commit, which the fork author controls. **Record the source commit where the content is read.** `DetectedWorkflow` now carries a `SourceCommitSHA` filled in next to `Content`, so the PRT detection pass at the base commit records the base SHA automatically. **Defense in depth.** `loadReusableWorkflowSource` pins the PR base commit for a PRT run's local `uses: ./...` rather than trusting the stored SHA. This also covers runs recorded before this change, whose rows still hold the head SHA and would otherwise resolve from the fork on rerun. Existing run rows are not migrated. Co-authored-by: bircni <bircni@icloud.com>
This commit is contained in:
@@ -10,9 +10,13 @@ import (
|
||||
actions_model "gitea.dev/models/actions"
|
||||
"gitea.dev/models/db"
|
||||
"gitea.dev/models/unittest"
|
||||
actions_module "gitea.dev/modules/actions"
|
||||
"gitea.dev/modules/actions/jobparser"
|
||||
"gitea.dev/modules/json"
|
||||
"gitea.dev/modules/setting"
|
||||
api "gitea.dev/modules/structs"
|
||||
"gitea.dev/modules/test"
|
||||
webhook_module "gitea.dev/modules/webhook"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -278,3 +282,74 @@ func TestUndoExpansion(t *testing.T) {
|
||||
assert.False(t, refreshed.IsExpanded)
|
||||
unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunJob{ID: sibling.ID})
|
||||
}
|
||||
|
||||
func TestResolveSameRepoWorkflowSourceCommit(t *testing.T) {
|
||||
prtRun := func(baseSHA string) *actions_model.ActionRun {
|
||||
payload, err := json.Marshal(api.PullRequestPayload{
|
||||
PullRequest: &api.PullRequest{
|
||||
Base: &api.PRBranchInfo{Sha: baseSHA},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
// a run recorded before the fix points at the PR head commit
|
||||
return &actions_model.ActionRun{
|
||||
ID: 42,
|
||||
RepoID: 1,
|
||||
Event: webhook_module.HookEventPullRequest,
|
||||
TriggerEvent: actions_module.GithubEventPullRequestTarget,
|
||||
EventPayload: string(payload),
|
||||
WorkflowCommitSHA: "head-sha",
|
||||
}
|
||||
}
|
||||
pushRun := &actions_model.ActionRun{
|
||||
RepoID: 1,
|
||||
TriggerEvent: "push",
|
||||
WorkflowCommitSHA: "head-sha",
|
||||
}
|
||||
caller := func(sourceRepoID int64, sourceCommitSHA string) *actions_model.ActionRunJob {
|
||||
return &actions_model.ActionRunJob{WorkflowSourceRepoID: sourceRepoID, WorkflowSourceCommitSHA: sourceCommitSHA}
|
||||
}
|
||||
|
||||
t.Run("pull_request_target pins to base commit", func(t *testing.T) {
|
||||
got := resolveSameRepoWorkflowSourceCommit(prtRun("base-sha"), caller(1, "head-sha"))
|
||||
assert.Equal(t, "base-sha", got)
|
||||
})
|
||||
|
||||
t.Run("legacy nested caller (with head-sha) pins to base commit", func(t *testing.T) {
|
||||
nested := caller(1, "head-sha")
|
||||
nested.ParentJobID = 99
|
||||
got := resolveSameRepoWorkflowSourceCommit(prtRun("base-sha"), nested)
|
||||
assert.Equal(t, "base-sha", got)
|
||||
})
|
||||
|
||||
t.Run("pull_request_target keeps stored SHA when already base", func(t *testing.T) {
|
||||
run := prtRun("base-sha")
|
||||
run.WorkflowCommitSHA = "base-sha"
|
||||
got := resolveSameRepoWorkflowSourceCommit(run, caller(1, "base-sha"))
|
||||
assert.Equal(t, "base-sha", got)
|
||||
})
|
||||
|
||||
t.Run("non pull_request_target keeps stored SHA", func(t *testing.T) {
|
||||
got := resolveSameRepoWorkflowSourceCommit(pushRun, caller(1, "head-sha"))
|
||||
assert.Equal(t, "head-sha", got)
|
||||
})
|
||||
|
||||
t.Run("scoped run keeps stored SHA", func(t *testing.T) {
|
||||
run := prtRun("base-sha")
|
||||
run.IsScopedRun = true
|
||||
got := resolveSameRepoWorkflowSourceCommit(run, caller(1, "head-sha"))
|
||||
assert.Equal(t, "head-sha", got)
|
||||
})
|
||||
|
||||
t.Run("cross-repo caller keeps stored SHA", func(t *testing.T) {
|
||||
got := resolveSameRepoWorkflowSourceCommit(prtRun("base-sha"), caller(2, "head-sha"))
|
||||
assert.Equal(t, "head-sha", got)
|
||||
})
|
||||
|
||||
t.Run("caller resolved from a uses: ref keeps its own SHA", func(t *testing.T) {
|
||||
nested := caller(1, "tag-v1-sha")
|
||||
nested.ParentJobID = 99
|
||||
got := resolveSameRepoWorkflowSourceCommit(prtRun("base-sha"), nested)
|
||||
assert.Equal(t, "tag-v1-sha", got)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user