Actions support workflow dispatch event (#28163)
fix #23668
My plan:
* In the `actions.list` method, if workflow is selected and IsAdmin,
check whether the on event contains `workflow_dispatch`. If so, display
a `Run workflow` button to allow the user to manually trigger the run.
* Providing a form that allows users to select target brach or tag, and
these parameters can be configured in yaml
* Simple form validation, `required` input cannot be empty
* Add a route `/actions/run`, and an `actions.Run` method to handle
* Add `WorkflowDispatchPayload` struct to pass the Webhook event payload
to the runner when triggered, this payload carries the `inputs` values
and other fields, doc: [workflow_dispatch
payload](https://docs.github.com/en/webhooks/webhook-events-and-payloads#workflow_dispatch)
Other PRs
* the `Workflow.WorkflowDispatchConfig()` method still return non-nil
when workflow_dispatch is not defined. I submitted a PR
https://gitea.com/gitea/act/pulls/85 to fix it. Still waiting for them
to process.
Behavior should be same with github, but may cause confusion. Here's a
quick reminder.
*
[Doc](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch)
Said: This event will `only` trigger a workflow run if the workflow file
is `on the default branch`.
* If the workflow yaml file only exists in a non-default branch, it
cannot be triggered. (It will not even show up in the workflow list)
* If the same workflow yaml file exists in each branch at the same time,
the version of the default branch is used. Even if `Use workflow from`
selects another branch
![image](https://github.com/go-gitea/gitea/assets/3114995/4bf596f3-426b-48e8-9b8f-0f6d18defd79)
```yaml
name: Docker Image CI
on:
workflow_dispatch:
inputs:
logLevel:
description: 'Log level'
required: true
default: 'warning'
type: choice
options:
- info
- warning
- debug
tags:
description: 'Test scenario tags'
required: false
type: boolean
boolean_default_true:
description: 'Test scenario tags'
required: true
type: boolean
default: true
boolean_default_false:
description: 'Test scenario tags'
required: false
type: boolean
default: false
environment:
description: 'Environment to run tests against'
type: environment
required: true
default: 'environment values'
number_required_1:
description: 'number '
type: number
required: true
default: '100'
number_required_2:
description: 'number'
type: number
required: true
default: '100'
number_required_3:
description: 'number'
type: number
required: true
default: '100'
number_1:
description: 'number'
type: number
required: false
number_2:
description: 'number'
type: number
required: false
number_3:
description: 'number'
type: number
required: false
env:
inputs_logLevel: ${{ inputs.logLevel }}
inputs_tags: ${{ inputs.tags }}
inputs_boolean_default_true: ${{ inputs.boolean_default_true }}
inputs_boolean_default_false: ${{ inputs.boolean_default_false }}
inputs_environment: ${{ inputs.environment }}
inputs_number_1: ${{ inputs.number_1 }}
inputs_number_2: ${{ inputs.number_2 }}
inputs_number_3: ${{ inputs.number_3 }}
inputs_number_required_1: ${{ inputs.number_required_1 }}
inputs_number_required_2: ${{ inputs.number_required_2 }}
inputs_number_required_3: ${{ inputs.number_required_3 }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: ls -la
- run: env | grep inputs
- run: echo ${{ inputs.logLevel }}
- run: echo ${{ inputs.boolean_default_false }}
```
![image](https://github.com/go-gitea/gitea/assets/3114995/a58a842d-a0ff-4618-bc6d-83a9596d07c8)
![image](https://github.com/go-gitea/gitea/assets/3114995/44a7cca5-7bd4-42a9-8723-91751a501c88)
---------
Co-authored-by: TKaxv_7S <954067342@qq.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Denys Konovalov <kontakt@denyskon.de>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2024-08-19 04:38:40 +02:00
|
|
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
|
|
|
|
package actions
|
|
|
|
|
|
|
|
import (
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
2024-12-15 22:38:39 +01:00
|
|
|
actions_model "code.gitea.io/gitea/models/actions"
|
|
|
|
"code.gitea.io/gitea/models/db"
|
|
|
|
unittest "code.gitea.io/gitea/models/unittest"
|
|
|
|
|
Actions support workflow dispatch event (#28163)
fix #23668
My plan:
* In the `actions.list` method, if workflow is selected and IsAdmin,
check whether the on event contains `workflow_dispatch`. If so, display
a `Run workflow` button to allow the user to manually trigger the run.
* Providing a form that allows users to select target brach or tag, and
these parameters can be configured in yaml
* Simple form validation, `required` input cannot be empty
* Add a route `/actions/run`, and an `actions.Run` method to handle
* Add `WorkflowDispatchPayload` struct to pass the Webhook event payload
to the runner when triggered, this payload carries the `inputs` values
and other fields, doc: [workflow_dispatch
payload](https://docs.github.com/en/webhooks/webhook-events-and-payloads#workflow_dispatch)
Other PRs
* the `Workflow.WorkflowDispatchConfig()` method still return non-nil
when workflow_dispatch is not defined. I submitted a PR
https://gitea.com/gitea/act/pulls/85 to fix it. Still waiting for them
to process.
Behavior should be same with github, but may cause confusion. Here's a
quick reminder.
*
[Doc](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch)
Said: This event will `only` trigger a workflow run if the workflow file
is `on the default branch`.
* If the workflow yaml file only exists in a non-default branch, it
cannot be triggered. (It will not even show up in the workflow list)
* If the same workflow yaml file exists in each branch at the same time,
the version of the default branch is used. Even if `Use workflow from`
selects another branch
![image](https://github.com/go-gitea/gitea/assets/3114995/4bf596f3-426b-48e8-9b8f-0f6d18defd79)
```yaml
name: Docker Image CI
on:
workflow_dispatch:
inputs:
logLevel:
description: 'Log level'
required: true
default: 'warning'
type: choice
options:
- info
- warning
- debug
tags:
description: 'Test scenario tags'
required: false
type: boolean
boolean_default_true:
description: 'Test scenario tags'
required: true
type: boolean
default: true
boolean_default_false:
description: 'Test scenario tags'
required: false
type: boolean
default: false
environment:
description: 'Environment to run tests against'
type: environment
required: true
default: 'environment values'
number_required_1:
description: 'number '
type: number
required: true
default: '100'
number_required_2:
description: 'number'
type: number
required: true
default: '100'
number_required_3:
description: 'number'
type: number
required: true
default: '100'
number_1:
description: 'number'
type: number
required: false
number_2:
description: 'number'
type: number
required: false
number_3:
description: 'number'
type: number
required: false
env:
inputs_logLevel: ${{ inputs.logLevel }}
inputs_tags: ${{ inputs.tags }}
inputs_boolean_default_true: ${{ inputs.boolean_default_true }}
inputs_boolean_default_false: ${{ inputs.boolean_default_false }}
inputs_environment: ${{ inputs.environment }}
inputs_number_1: ${{ inputs.number_1 }}
inputs_number_2: ${{ inputs.number_2 }}
inputs_number_3: ${{ inputs.number_3 }}
inputs_number_required_1: ${{ inputs.number_required_1 }}
inputs_number_required_2: ${{ inputs.number_required_2 }}
inputs_number_required_3: ${{ inputs.number_required_3 }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: ls -la
- run: env | grep inputs
- run: echo ${{ inputs.logLevel }}
- run: echo ${{ inputs.boolean_default_false }}
```
![image](https://github.com/go-gitea/gitea/assets/3114995/a58a842d-a0ff-4618-bc6d-83a9596d07c8)
![image](https://github.com/go-gitea/gitea/assets/3114995/44a7cca5-7bd4-42a9-8723-91751a501c88)
---------
Co-authored-by: TKaxv_7S <954067342@qq.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Denys Konovalov <kontakt@denyskon.de>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2024-08-19 04:38:40 +02:00
|
|
|
act_model "github.com/nektos/act/pkg/model"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
|
|
|
|
yaml := `
|
|
|
|
name: local-action-docker-url
|
|
|
|
`
|
|
|
|
workflow, err := act_model.ReadWorkflow(strings.NewReader(yaml))
|
|
|
|
assert.NoError(t, err, "read workflow should succeed")
|
|
|
|
workflowDispatch := workflowDispatchConfig(workflow)
|
|
|
|
assert.Nil(t, workflowDispatch)
|
|
|
|
|
|
|
|
yaml = `
|
|
|
|
name: local-action-docker-url
|
|
|
|
on: push
|
|
|
|
`
|
|
|
|
workflow, err = act_model.ReadWorkflow(strings.NewReader(yaml))
|
|
|
|
assert.NoError(t, err, "read workflow should succeed")
|
|
|
|
workflowDispatch = workflowDispatchConfig(workflow)
|
|
|
|
assert.Nil(t, workflowDispatch)
|
|
|
|
|
|
|
|
yaml = `
|
|
|
|
name: local-action-docker-url
|
|
|
|
on: workflow_dispatch
|
|
|
|
`
|
|
|
|
workflow, err = act_model.ReadWorkflow(strings.NewReader(yaml))
|
|
|
|
assert.NoError(t, err, "read workflow should succeed")
|
|
|
|
workflowDispatch = workflowDispatchConfig(workflow)
|
|
|
|
assert.NotNil(t, workflowDispatch)
|
|
|
|
assert.Nil(t, workflowDispatch.Inputs)
|
|
|
|
|
|
|
|
yaml = `
|
|
|
|
name: local-action-docker-url
|
|
|
|
on: [push, pull_request]
|
|
|
|
`
|
|
|
|
workflow, err = act_model.ReadWorkflow(strings.NewReader(yaml))
|
|
|
|
assert.NoError(t, err, "read workflow should succeed")
|
|
|
|
workflowDispatch = workflowDispatchConfig(workflow)
|
|
|
|
assert.Nil(t, workflowDispatch)
|
|
|
|
|
|
|
|
yaml = `
|
|
|
|
name: local-action-docker-url
|
|
|
|
on:
|
|
|
|
push:
|
|
|
|
pull_request:
|
|
|
|
`
|
|
|
|
workflow, err = act_model.ReadWorkflow(strings.NewReader(yaml))
|
|
|
|
assert.NoError(t, err, "read workflow should succeed")
|
|
|
|
workflowDispatch = workflowDispatchConfig(workflow)
|
|
|
|
assert.Nil(t, workflowDispatch)
|
|
|
|
|
|
|
|
yaml = `
|
|
|
|
name: local-action-docker-url
|
|
|
|
on: [push, workflow_dispatch]
|
|
|
|
`
|
|
|
|
workflow, err = act_model.ReadWorkflow(strings.NewReader(yaml))
|
|
|
|
assert.NoError(t, err, "read workflow should succeed")
|
|
|
|
workflowDispatch = workflowDispatchConfig(workflow)
|
|
|
|
assert.NotNil(t, workflowDispatch)
|
|
|
|
assert.Nil(t, workflowDispatch.Inputs)
|
|
|
|
|
|
|
|
yaml = `
|
|
|
|
name: local-action-docker-url
|
|
|
|
on:
|
|
|
|
- push
|
|
|
|
- workflow_dispatch
|
|
|
|
`
|
|
|
|
workflow, err = act_model.ReadWorkflow(strings.NewReader(yaml))
|
|
|
|
assert.NoError(t, err, "read workflow should succeed")
|
|
|
|
workflowDispatch = workflowDispatchConfig(workflow)
|
|
|
|
assert.NotNil(t, workflowDispatch)
|
|
|
|
assert.Nil(t, workflowDispatch.Inputs)
|
|
|
|
|
|
|
|
yaml = `
|
|
|
|
name: local-action-docker-url
|
|
|
|
on:
|
|
|
|
push:
|
|
|
|
pull_request:
|
|
|
|
workflow_dispatch:
|
|
|
|
inputs:
|
|
|
|
`
|
|
|
|
workflow, err = act_model.ReadWorkflow(strings.NewReader(yaml))
|
|
|
|
assert.NoError(t, err, "read workflow should succeed")
|
|
|
|
workflowDispatch = workflowDispatchConfig(workflow)
|
|
|
|
assert.NotNil(t, workflowDispatch)
|
|
|
|
assert.Nil(t, workflowDispatch.Inputs)
|
|
|
|
|
|
|
|
yaml = `
|
|
|
|
name: local-action-docker-url
|
|
|
|
on:
|
|
|
|
push:
|
|
|
|
pull_request:
|
|
|
|
workflow_dispatch:
|
|
|
|
inputs:
|
|
|
|
logLevel:
|
|
|
|
description: 'Log level'
|
|
|
|
required: true
|
|
|
|
default: 'warning'
|
|
|
|
type: choice
|
|
|
|
options:
|
|
|
|
- info
|
|
|
|
- warning
|
|
|
|
- debug
|
|
|
|
boolean_default_true:
|
|
|
|
description: 'Test scenario tags'
|
|
|
|
required: true
|
|
|
|
type: boolean
|
|
|
|
default: true
|
|
|
|
boolean_default_false:
|
|
|
|
description: 'Test scenario tags'
|
|
|
|
required: true
|
|
|
|
type: boolean
|
|
|
|
default: false
|
|
|
|
`
|
|
|
|
|
|
|
|
workflow, err = act_model.ReadWorkflow(strings.NewReader(yaml))
|
|
|
|
assert.NoError(t, err, "read workflow should succeed")
|
|
|
|
workflowDispatch = workflowDispatchConfig(workflow)
|
|
|
|
assert.NotNil(t, workflowDispatch)
|
|
|
|
assert.Equal(t, WorkflowDispatchInput{
|
|
|
|
Name: "logLevel",
|
|
|
|
Default: "warning",
|
|
|
|
Description: "Log level",
|
|
|
|
Options: []string{
|
|
|
|
"info",
|
|
|
|
"warning",
|
|
|
|
"debug",
|
|
|
|
},
|
|
|
|
Required: true,
|
|
|
|
Type: "choice",
|
|
|
|
}, workflowDispatch.Inputs[0])
|
|
|
|
assert.Equal(t, WorkflowDispatchInput{
|
|
|
|
Name: "boolean_default_true",
|
|
|
|
Default: "true",
|
|
|
|
Description: "Test scenario tags",
|
|
|
|
Required: true,
|
|
|
|
Type: "boolean",
|
|
|
|
}, workflowDispatch.Inputs[1])
|
|
|
|
assert.Equal(t, WorkflowDispatchInput{
|
|
|
|
Name: "boolean_default_false",
|
|
|
|
Default: "false",
|
|
|
|
Description: "Test scenario tags",
|
|
|
|
Required: true,
|
|
|
|
Type: "boolean",
|
|
|
|
}, workflowDispatch.Inputs[2])
|
|
|
|
}
|
2024-12-15 22:38:39 +01:00
|
|
|
|
|
|
|
func Test_loadIsRefDeleted(t *testing.T) {
|
|
|
|
unittest.PrepareTestEnv(t)
|
|
|
|
|
|
|
|
runs, total, err := db.FindAndCount[actions_model.ActionRun](db.DefaultContext,
|
|
|
|
actions_model.FindRunOptions{RepoID: 4, Ref: "refs/heads/test"})
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Len(t, runs, 1)
|
|
|
|
assert.EqualValues(t, 1, total)
|
|
|
|
for _, run := range runs {
|
|
|
|
assert.False(t, run.IsRefDeleted)
|
|
|
|
}
|
|
|
|
|
|
|
|
assert.NoError(t, loadIsRefDeleted(db.DefaultContext, 4, runs))
|
|
|
|
for _, run := range runs {
|
|
|
|
assert.True(t, run.IsRefDeleted)
|
|
|
|
}
|
|
|
|
}
|