mirror of
https://github.com/go-gitea/gitea.git
synced 2025-10-08 17:36:16 +02:00
Backport #35590 by @Zettat123 Depends on [gitea/act#143](https://gitea.com/gitea/act/pulls/143) The [`inputs` context](https://docs.github.com/en/actions/reference/workflows-and-actions/contexts#inputs-context) is used when parsing workflows so that `run-name` like `run-name: Deploy to ${{ inputs.deploy_target }}` can be parsed correctly. Co-authored-by: Zettat123 <zettat123@gmail.com>
This commit is contained in:
parent
8d1c04bda4
commit
a99761d466
2
go.mod
2
go.mod
@ -295,7 +295,7 @@ replace github.com/jaytaylor/html2text => github.com/Necoro/html2text v0.0.0-202
|
|||||||
|
|
||||||
replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1
|
replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1
|
||||||
|
|
||||||
replace github.com/nektos/act => gitea.com/gitea/act v0.261.6
|
replace github.com/nektos/act => gitea.com/gitea/act v0.261.7-0.20251003180512-ac6e4b751763
|
||||||
|
|
||||||
// TODO: the only difference is in `PutObject`: the fork doesn't use `NewVerifyingReader(r, sha256.New(), oid, expectedSize)`, need to figure out why
|
// TODO: the only difference is in `PutObject`: the fork doesn't use `NewVerifyingReader(r, sha256.New(), oid, expectedSize)`, need to figure out why
|
||||||
replace github.com/charmbracelet/git-lfs-transfer => gitea.com/gitea/git-lfs-transfer v0.2.0
|
replace github.com/charmbracelet/git-lfs-transfer => gitea.com/gitea/git-lfs-transfer v0.2.0
|
||||||
|
4
go.sum
4
go.sum
@ -31,8 +31,8 @@ dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
|||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||||
gitea.com/gitea/act v0.261.6 h1:CjZwKOyejonNFDmsXOw3wGm5Vet573hHM6VMLsxtvPY=
|
gitea.com/gitea/act v0.261.7-0.20251003180512-ac6e4b751763 h1:ohdxegvslDEllZmRNDqpKun6L4Oq81jNdEDtGgHEV2c=
|
||||||
gitea.com/gitea/act v0.261.6/go.mod h1:Pg5C9kQY1CEA3QjthjhlrqOC/QOT5NyWNjOjRHw23Ok=
|
gitea.com/gitea/act v0.261.7-0.20251003180512-ac6e4b751763/go.mod h1:Pg5C9kQY1CEA3QjthjhlrqOC/QOT5NyWNjOjRHw23Ok=
|
||||||
gitea.com/gitea/git-lfs-transfer v0.2.0 h1:baHaNoBSRaeq/xKayEXwiDQtlIjps4Ac/Ll4KqLMB40=
|
gitea.com/gitea/git-lfs-transfer v0.2.0 h1:baHaNoBSRaeq/xKayEXwiDQtlIjps4Ac/Ll4KqLMB40=
|
||||||
gitea.com/gitea/git-lfs-transfer v0.2.0/go.mod h1:UrXUCm3xLQkq15fu7qlXHUMlrhdlXHoi13KH2Dfiits=
|
gitea.com/gitea/git-lfs-transfer v0.2.0/go.mod h1:UrXUCm3xLQkq15fu7qlXHUMlrhdlXHoi13KH2Dfiits=
|
||||||
gitea.com/gitea/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:BAFmdZpRW7zMQZQDClaCWobRj9uL1MR3MzpCVJvc5s4=
|
gitea.com/gitea/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:BAFmdZpRW7zMQZQDClaCWobRj9uL1MR3MzpCVJvc5s4=
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
|
|
||||||
"github.com/nektos/act/pkg/jobparser"
|
"github.com/nektos/act/pkg/jobparser"
|
||||||
"github.com/nektos/act/pkg/model"
|
"github.com/nektos/act/pkg/model"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func EnableOrDisableWorkflow(ctx *context.APIContext, workflowID string, isEnable bool) error {
|
func EnableOrDisableWorkflow(ctx *context.APIContext, workflowID string, isEnable bool) error {
|
||||||
@ -136,9 +137,24 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
singleWorkflow := &jobparser.SingleWorkflow{}
|
||||||
|
if err := yaml.Unmarshal(content, singleWorkflow); err != nil {
|
||||||
|
return fmt.Errorf("failed to unmarshal workflow content: %w", err)
|
||||||
|
}
|
||||||
|
// get inputs from post
|
||||||
|
workflow := &model.Workflow{
|
||||||
|
RawOn: singleWorkflow.RawOn,
|
||||||
|
}
|
||||||
|
inputsWithDefaults := make(map[string]any)
|
||||||
|
if workflowDispatch := workflow.WorkflowDispatchConfig(); workflowDispatch != nil {
|
||||||
|
if err = processInputs(workflowDispatch, inputsWithDefaults); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
giteaCtx := GenerateGiteaContext(run, nil)
|
giteaCtx := GenerateGiteaContext(run, nil)
|
||||||
|
|
||||||
workflows, err = jobparser.Parse(content, jobparser.WithGitContext(giteaCtx.ToGitHubContext()))
|
workflows, err = jobparser.Parse(content, jobparser.WithGitContext(giteaCtx.ToGitHubContext()), jobparser.WithInputs(inputsWithDefaults))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -154,17 +170,6 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// get inputs from post
|
|
||||||
workflow := &model.Workflow{
|
|
||||||
RawOn: workflows[0].RawOn,
|
|
||||||
}
|
|
||||||
inputsWithDefaults := make(map[string]any)
|
|
||||||
if workflowDispatch := workflow.WorkflowDispatchConfig(); workflowDispatch != nil {
|
|
||||||
if err = processInputs(workflowDispatch, inputsWithDefaults); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ctx.Req.PostForm -> WorkflowDispatchPayload.Inputs -> ActionRun.EventPayload -> runner: ghc.Event
|
// ctx.Req.PostForm -> WorkflowDispatchPayload.Inputs -> ActionRun.EventPayload -> runner: ghc.Event
|
||||||
// https://docs.github.com/en/actions/learn-github-actions/contexts#github-context
|
// https://docs.github.com/en/actions/learn-github-actions/contexts#github-context
|
||||||
// https://docs.github.com/en/webhooks/webhook-events-and-payloads#workflow_dispatch
|
// https://docs.github.com/en/webhooks/webhook-events-and-payloads#workflow_dispatch
|
||||||
|
85
tests/integration/actions_inputs_test.go
Normal file
85
tests/integration/actions_inputs_test.go
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package integration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
actions_model "code.gitea.io/gitea/models/actions"
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestWorkflowWithInputsContext(t *testing.T) {
|
||||||
|
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
||||||
|
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
session := loginUser(t, user2.Name)
|
||||||
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
|
|
||||||
|
apiRepo := createActionsTestRepo(t, token, "actions-inputs-context", false)
|
||||||
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID})
|
||||||
|
httpContext := NewAPITestContext(t, user2.Name, repo.Name, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
defer doAPIDeleteRepository(httpContext)(t)
|
||||||
|
|
||||||
|
wRunner := newMockRunner()
|
||||||
|
wRunner.registerAsRepoRunner(t, user2.Name, repo.Name, "windows-runner", []string{"windows-runner"}, false)
|
||||||
|
lRunner := newMockRunner()
|
||||||
|
lRunner.registerAsRepoRunner(t, user2.Name, repo.Name, "linux-runner", []string{"linux-runner"}, false)
|
||||||
|
|
||||||
|
wf1TreePath := ".gitea/workflows/test-inputs-context.yml"
|
||||||
|
wf1FileContent := `name: Test Inputs Context
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
os:
|
||||||
|
description: 'OS'
|
||||||
|
required: true
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- linux
|
||||||
|
- windows
|
||||||
|
|
||||||
|
run-name: Build APP on ${{ inputs.os }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ${{ inputs.os }}-runner
|
||||||
|
steps:
|
||||||
|
- run: echo 'Start building APP'
|
||||||
|
`
|
||||||
|
|
||||||
|
opts1 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create %s"+wf1TreePath, wf1FileContent)
|
||||||
|
createWorkflowFile(t, token, user2.Name, repo.Name, wf1TreePath, opts1)
|
||||||
|
|
||||||
|
// run the workflow with os=windows
|
||||||
|
urlStr := fmt.Sprintf("/%s/%s/actions/run?workflow=%s", user2.Name, repo.Name, "test-inputs-context.yml")
|
||||||
|
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
|
||||||
|
"_csrf": GetUserCSRFToken(t, session),
|
||||||
|
"ref": "refs/heads/main",
|
||||||
|
"os": "windows",
|
||||||
|
})
|
||||||
|
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||||
|
|
||||||
|
// linux-runner cannot fetch the task
|
||||||
|
lRunner.fetchNoTask(t)
|
||||||
|
|
||||||
|
task := wRunner.fetchTask(t)
|
||||||
|
_, _, run := getTaskAndJobAndRunByTaskID(t, task.Id)
|
||||||
|
assert.Equal(t, "Build APP on windows", run.Title)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTaskAndJobAndRunByTaskID(t *testing.T, taskID int64) (*actions_model.ActionTask, *actions_model.ActionRunJob, *actions_model.ActionRun) {
|
||||||
|
actionTask := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionTask{ID: taskID})
|
||||||
|
actionRunJob := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunJob{ID: actionTask.JobID})
|
||||||
|
actionRun := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: actionRunJob.RunID})
|
||||||
|
return actionTask, actionRunJob, actionRun
|
||||||
|
}
|
@ -93,7 +93,20 @@ func (r *mockRunner) registerAsRepoRunner(t *testing.T, ownerName, repoName, run
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *mockRunner) fetchTask(t *testing.T, timeout ...time.Duration) *runnerv1.Task {
|
func (r *mockRunner) fetchTask(t *testing.T, timeout ...time.Duration) *runnerv1.Task {
|
||||||
fetchTimeout := 10 * time.Second
|
task := r.tryFetchTask(t, timeout...)
|
||||||
|
assert.NotNil(t, task, "failed to fetch a task")
|
||||||
|
return task
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mockRunner) fetchNoTask(t *testing.T, timeout ...time.Duration) {
|
||||||
|
task := r.tryFetchTask(t, timeout...)
|
||||||
|
assert.Nil(t, task, "a task is fetched")
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultFetchTaskTimeout = 1 * time.Second
|
||||||
|
|
||||||
|
func (r *mockRunner) tryFetchTask(t *testing.T, timeout ...time.Duration) *runnerv1.Task {
|
||||||
|
fetchTimeout := defaultFetchTaskTimeout
|
||||||
if len(timeout) > 0 {
|
if len(timeout) > 0 {
|
||||||
fetchTimeout = timeout[0]
|
fetchTimeout = timeout[0]
|
||||||
}
|
}
|
||||||
@ -108,9 +121,9 @@ func (r *mockRunner) fetchTask(t *testing.T, timeout ...time.Duration) *runnerv1
|
|||||||
task = resp.Msg.Task
|
task = resp.Msg.Task
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
time.Sleep(time.Second)
|
time.Sleep(200 * time.Millisecond)
|
||||||
}
|
}
|
||||||
assert.NotNil(t, task, "failed to fetch a task")
|
|
||||||
return task
|
return task
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user