1 Commits

Author SHA1 Message Date
林玮 (Jade Lin)
9661a37003 Make the external url of cache server configurable if necessary
Some checks failed
checks / check and test (push) Failing after 21s
2024-09-06 13:12:58 +02:00
13 changed files with 84 additions and 466 deletions

View File

@@ -20,7 +20,7 @@ import (
func TestHandler(t *testing.T) { func TestHandler(t *testing.T) {
dir := filepath.Join(t.TempDir(), "artifactcache") dir := filepath.Join(t.TempDir(), "artifactcache")
handler, err := StartHandler(dir, "", "", 0, nil) handler, err := StartHandler(dir, "", 0, nil)
require.NoError(t, err) require.NoError(t, err)
base := fmt.Sprintf("%s%s", handler.ExternalURL(), urlBase) base := fmt.Sprintf("%s%s", handler.ExternalURL(), urlBase)
@@ -589,7 +589,7 @@ func uploadCacheNormally(t *testing.T, base, key, version string, content []byte
func TestHandler_gcCache(t *testing.T) { func TestHandler_gcCache(t *testing.T) {
dir := filepath.Join(t.TempDir(), "artifactcache") dir := filepath.Join(t.TempDir(), "artifactcache")
handler, err := StartHandler(dir, "", "", 0, nil) handler, err := StartHandler(dir, "", 0, nil)
require.NoError(t, err) require.NoError(t, err)
defer func() { defer func() {

View File

@@ -16,7 +16,6 @@ func NewInterpeter(
gitCtx *model.GithubContext, gitCtx *model.GithubContext,
results map[string]*JobResult, results map[string]*JobResult,
vars map[string]string, vars map[string]string,
inputs map[string]interface{},
) exprparser.Interpreter { ) exprparser.Interpreter {
strategy := make(map[string]interface{}) strategy := make(map[string]interface{})
if job.Strategy != nil { if job.Strategy != nil {
@@ -63,7 +62,7 @@ func NewInterpeter(
Strategy: strategy, Strategy: strategy,
Matrix: matrix, Matrix: matrix,
Needs: using, Needs: using,
Inputs: inputs, Inputs: nil, // not supported yet
Vars: vars, Vars: vars,
} }

View File

@@ -8,7 +8,6 @@ import (
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"github.com/nektos/act/pkg/exprparser"
"github.com/nektos/act/pkg/model" "github.com/nektos/act/pkg/model"
) )
@@ -41,10 +40,6 @@ func Parse(content []byte, options ...ParseOption) ([]*SingleWorkflow, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("invalid jobs: %w", err) return nil, fmt.Errorf("invalid jobs: %w", err)
} }
evaluator := NewExpressionEvaluator(exprparser.NewInterpeter(&exprparser.EvaluationEnvironment{Github: pc.gitContext, Vars: pc.vars}, exprparser.Config{}))
workflow.RunName = evaluator.Interpolate(workflow.RunName)
for i, id := range ids { for i, id := range ids {
job := jobs[i] job := jobs[i]
matricxes, err := getMatrixes(origin.GetJob(id)) matricxes, err := getMatrixes(origin.GetJob(id))
@@ -57,7 +52,7 @@ func Parse(content []byte, options ...ParseOption) ([]*SingleWorkflow, error) {
job.Name = id job.Name = id
} }
job.Strategy.RawMatrix = encodeMatrix(matrix) job.Strategy.RawMatrix = encodeMatrix(matrix)
evaluator := NewExpressionEvaluator(NewInterpeter(id, origin.GetJob(id), matrix, pc.gitContext, results, pc.vars, nil)) evaluator := NewExpressionEvaluator(NewInterpeter(id, origin.GetJob(id), matrix, pc.gitContext, results, pc.vars))
job.Name = nameWithMatrix(job.Name, matrix, evaluator) job.Name = nameWithMatrix(job.Name, matrix, evaluator)
runsOn := origin.GetJob(id).RunsOn() runsOn := origin.GetJob(id).RunsOn()
for i, v := range runsOn { for i, v := range runsOn {
@@ -69,8 +64,6 @@ func Parse(content []byte, options ...ParseOption) ([]*SingleWorkflow, error) {
RawOn: workflow.RawOn, RawOn: workflow.RawOn,
Env: workflow.Env, Env: workflow.Env,
Defaults: workflow.Defaults, Defaults: workflow.Defaults,
RawPermissions: workflow.RawPermissions,
RunName: workflow.RunName,
} }
if err := swf.SetJob(id, job); err != nil { if err := swf.SetJob(id, job); err != nil {
return nil, fmt.Errorf("SetJob: %w", err) return nil, fmt.Errorf("SetJob: %w", err)

View File

@@ -1,7 +1,6 @@
package jobparser package jobparser
import ( import (
"bytes"
"fmt" "fmt"
"github.com/nektos/act/pkg/model" "github.com/nektos/act/pkg/model"
@@ -15,8 +14,6 @@ type SingleWorkflow struct {
Env map[string]string `yaml:"env,omitempty"` Env map[string]string `yaml:"env,omitempty"`
RawJobs yaml.Node `yaml:"jobs,omitempty"` RawJobs yaml.Node `yaml:"jobs,omitempty"`
Defaults Defaults `yaml:"defaults,omitempty"` Defaults Defaults `yaml:"defaults,omitempty"`
RawPermissions yaml.Node `yaml:"permissions,omitempty"`
RunName string `yaml:"run-name,omitempty"`
} }
func (w *SingleWorkflow) Job() (string, *Job) { func (w *SingleWorkflow) Job() (string, *Job) {
@@ -85,8 +82,6 @@ type Job struct {
Uses string `yaml:"uses,omitempty"` Uses string `yaml:"uses,omitempty"`
With map[string]interface{} `yaml:"with,omitempty"` With map[string]interface{} `yaml:"with,omitempty"`
RawSecrets yaml.Node `yaml:"secrets,omitempty"` RawSecrets yaml.Node `yaml:"secrets,omitempty"`
RawConcurrency *model.RawConcurrency `yaml:"concurrency,omitempty"`
RawPermissions yaml.Node `yaml:"permissions,omitempty"`
} }
func (j *Job) Clone() *Job { func (j *Job) Clone() *Job {
@@ -109,8 +104,6 @@ func (j *Job) Clone() *Job {
Uses: j.Uses, Uses: j.Uses,
With: j.With, With: j.With,
RawSecrets: j.RawSecrets, RawSecrets: j.RawSecrets,
RawConcurrency: j.RawConcurrency,
RawPermissions: j.RawPermissions,
} }
} }
@@ -179,20 +172,10 @@ type RunDefaults struct {
WorkingDirectory string `yaml:"working-directory,omitempty"` WorkingDirectory string `yaml:"working-directory,omitempty"`
} }
type WorkflowDispatchInput struct {
Name string `yaml:"name"`
Description string `yaml:"description"`
Required bool `yaml:"required"`
Default string `yaml:"default"`
Type string `yaml:"type"`
Options []string `yaml:"options"`
}
type Event struct { type Event struct {
Name string Name string
acts map[string][]string acts map[string][]string
schedules []map[string]string schedules []map[string]string
inputs []WorkflowDispatchInput
} }
func (evt *Event) IsSchedule() bool { func (evt *Event) IsSchedule() bool {
@@ -207,114 +190,6 @@ func (evt *Event) Schedules() []map[string]string {
return evt.schedules return evt.schedules
} }
func (evt *Event) Inputs() []WorkflowDispatchInput {
return evt.inputs
}
func parseWorkflowDispatchInputs(inputs map[string]interface{}) ([]WorkflowDispatchInput, error) {
var results []WorkflowDispatchInput
for name, input := range inputs {
inputMap, ok := input.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("invalid input: %v", input)
}
input := WorkflowDispatchInput{
Name: name,
}
if desc, ok := inputMap["description"].(string); ok {
input.Description = desc
}
if required, ok := inputMap["required"].(bool); ok {
input.Required = required
}
if defaultVal, ok := inputMap["default"].(string); ok {
input.Default = defaultVal
}
if inputType, ok := inputMap["type"].(string); ok {
input.Type = inputType
}
if options, ok := inputMap["options"].([]string); ok {
input.Options = options
} else if options, ok := inputMap["options"].([]interface{}); ok {
for _, option := range options {
if opt, ok := option.(string); ok {
input.Options = append(input.Options, opt)
}
}
}
results = append(results, input)
}
return results, nil
}
func ReadWorkflowRawConcurrency(content []byte) (*model.RawConcurrency, error) {
w := new(model.Workflow)
err := yaml.NewDecoder(bytes.NewReader(content)).Decode(w)
return w.RawConcurrency, err
}
func EvaluateConcurrency(rc *model.RawConcurrency, jobID string, job *Job, gitCtx map[string]any, results map[string]*JobResult, vars map[string]string, inputs map[string]any) (string, bool, error) {
actJob := &model.Job{}
if job != nil {
actJob.Strategy = &model.Strategy{
FailFastString: job.Strategy.FailFastString,
MaxParallelString: job.Strategy.MaxParallelString,
RawMatrix: job.Strategy.RawMatrix,
}
actJob.Strategy.FailFast = actJob.Strategy.GetFailFast()
actJob.Strategy.MaxParallel = actJob.Strategy.GetMaxParallel()
}
matrix := make(map[string]any)
matrixes, err := actJob.GetMatrixes()
if err != nil {
return "", false, err
}
if len(matrixes) > 0 {
matrix = matrixes[0]
}
evaluator := NewExpressionEvaluator(NewInterpeter(jobID, actJob, matrix, toGitContext(gitCtx), results, vars, inputs))
group := evaluator.Interpolate(rc.Group)
cancelInProgress := evaluator.Interpolate(rc.CancelInProgress)
return group, cancelInProgress == "true", nil
}
func toGitContext(input map[string]any) *model.GithubContext {
gitContext := &model.GithubContext{
EventPath: asString(input["event_path"]),
Workflow: asString(input["workflow"]),
RunID: asString(input["run_id"]),
RunNumber: asString(input["run_number"]),
Actor: asString(input["actor"]),
Repository: asString(input["repository"]),
EventName: asString(input["event_name"]),
Sha: asString(input["sha"]),
Ref: asString(input["ref"]),
RefName: asString(input["ref_name"]),
RefType: asString(input["ref_type"]),
HeadRef: asString(input["head_ref"]),
BaseRef: asString(input["base_ref"]),
Token: asString(input["token"]),
Workspace: asString(input["workspace"]),
Action: asString(input["action"]),
ActionPath: asString(input["action_path"]),
ActionRef: asString(input["action_ref"]),
ActionRepository: asString(input["action_repository"]),
Job: asString(input["job"]),
RepositoryOwner: asString(input["repository_owner"]),
RetentionDays: asString(input["retention_days"]),
}
event, ok := input["event"].(map[string]any)
if ok {
gitContext.Event = event
}
return gitContext
}
func ParseRawOn(rawOn *yaml.Node) ([]*Event, error) { func ParseRawOn(rawOn *yaml.Node) ([]*Event, error) {
switch rawOn.Kind { switch rawOn.Kind {
case yaml.ScalarNode: case yaml.ScalarNode:
@@ -343,126 +218,79 @@ func ParseRawOn(rawOn *yaml.Node) ([]*Event, error) {
} }
return res, nil return res, nil
case yaml.MappingNode: case yaml.MappingNode:
events, triggers, err := parseMappingNode[yaml.Node](rawOn) events, triggers, err := parseMappingNode[interface{}](rawOn)
if err != nil { if err != nil {
return nil, err return nil, err
} }
res := make([]*Event, 0, len(events)) res := make([]*Event, 0, len(events))
for i, k := range events { for i, k := range events {
v := triggers[i] v := triggers[i]
switch v.Kind { if v == nil {
case yaml.ScalarNode:
res = append(res, &Event{ res = append(res, &Event{
Name: k, Name: k,
acts: map[string][]string{},
}) })
case yaml.SequenceNode: continue
var t []interface{} }
err := v.Decode(&t) switch t := v.(type) {
if err != nil { case string:
return nil, err res = append(res, &Event{
Name: k,
acts: map[string][]string{},
})
case []string:
res = append(res, &Event{
Name: k,
acts: map[string][]string{},
})
case map[string]interface{}:
acts := make(map[string][]string, len(t))
for act, branches := range t {
switch b := branches.(type) {
case string:
acts[act] = []string{b}
case []string:
acts[act] = b
case []interface{}:
acts[act] = make([]string, len(b))
for i, v := range b {
var ok bool
if acts[act][i], ok = v.(string); !ok {
return nil, fmt.Errorf("unknown on type: %#v", branches)
}
}
default:
return nil, fmt.Errorf("unknown on type: %#v", branches)
}
}
res = append(res, &Event{
Name: k,
acts: acts,
})
case []interface{}:
if k != "schedule" {
return nil, fmt.Errorf("unknown on type: %#v", v)
} }
schedules := make([]map[string]string, len(t)) schedules := make([]map[string]string, len(t))
if k == "schedule" {
for i, tt := range t { for i, tt := range t {
vv, ok := tt.(map[string]interface{}) vv, ok := tt.(map[string]interface{})
if !ok { if !ok {
return nil, fmt.Errorf("unknown on type(schedule): %#v", v) return nil, fmt.Errorf("unknown on type: %#v", v)
} }
schedules[i] = make(map[string]string, len(vv)) schedules[i] = make(map[string]string, len(vv))
for k, vvv := range vv { for k, vvv := range vv {
var ok bool var ok bool
if schedules[i][k], ok = vvv.(string); !ok { if schedules[i][k], ok = vvv.(string); !ok {
return nil, fmt.Errorf("unknown on type(schedule): %#v", v) return nil, fmt.Errorf("unknown on type: %#v", v)
} }
} }
} }
}
if len(schedules) == 0 {
schedules = nil
}
res = append(res, &Event{ res = append(res, &Event{
Name: k, Name: k,
schedules: schedules, schedules: schedules,
}) })
case yaml.MappingNode:
acts := make(map[string][]string, len(v.Content)/2)
var inputs []WorkflowDispatchInput
expectedKey := true
var act string
for _, content := range v.Content {
if expectedKey {
if content.Kind != yaml.ScalarNode {
return nil, fmt.Errorf("key type not string: %#v", content)
}
act = ""
err := content.Decode(&act)
if err != nil {
return nil, err
}
} else {
switch content.Kind {
case yaml.SequenceNode:
var t []string
err := content.Decode(&t)
if err != nil {
return nil, err
}
acts[act] = t
case yaml.ScalarNode:
var t string
err := content.Decode(&t)
if err != nil {
return nil, err
}
acts[act] = []string{t}
case yaml.MappingNode:
if k != "workflow_dispatch" || act != "inputs" {
return nil, fmt.Errorf("map should only for workflow_dispatch but %s: %#v", act, content)
}
var key string
for i, vv := range content.Content {
if i%2 == 0 {
if vv.Kind != yaml.ScalarNode {
return nil, fmt.Errorf("key type not string: %#v", vv)
}
key = ""
if err := vv.Decode(&key); err != nil {
return nil, err
}
} else {
if vv.Kind != yaml.MappingNode {
return nil, fmt.Errorf("key type not map(%s): %#v", key, vv)
}
input := WorkflowDispatchInput{}
if err := vv.Decode(&input); err != nil {
return nil, err
}
input.Name = key
inputs = append(inputs, input)
}
}
default: default:
return nil, fmt.Errorf("unknown on type: %#v", content) return nil, fmt.Errorf("unknown on type: %#v", v)
}
}
expectedKey = !expectedKey
}
if len(inputs) == 0 {
inputs = nil
}
if len(acts) == 0 {
acts = nil
}
res = append(res, &Event{
Name: k,
acts: acts,
inputs: inputs,
})
default:
return nil, fmt.Errorf("unknown on type: %v", v.Kind)
} }
} }
return res, nil return res, nil
@@ -503,12 +331,3 @@ func parseMappingNode[T any](node *yaml.Node) ([]string, []T, error) {
return scalars, datas, nil return scalars, datas, nil
} }
func asString(v interface{}) string {
if v == nil {
return ""
} else if s, ok := v.(string); ok {
return s
}
return ""
}

View File

@@ -58,19 +58,6 @@ func TestParseRawOn(t *testing.T) {
}, },
}, },
}, },
{
input: "on:\n push:\n branches: main",
result: []*Event{
{
Name: "push",
acts: map[string][]string{
"branches": {
"main",
},
},
},
},
},
{ {
input: "on:\n branch_protection_rule:\n types: [created, deleted]", input: "on:\n branch_protection_rule:\n types: [created, deleted]",
result: []*Event{ result: []*Event{
@@ -199,60 +186,6 @@ func TestParseRawOn(t *testing.T) {
}, },
}, },
}, },
{
input: `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
environment:
description: 'Environment to run tests against'
type: environment
required: true
push:
`,
result: []*Event{
{
Name: "workflow_dispatch",
inputs: []WorkflowDispatchInput{
{
Name: "logLevel",
Description: "Log level",
Required: true,
Default: "warning",
Type: "choice",
Options: []string{"info", "warning", "debug"},
},
{
Name: "tags",
Description: "Test scenario tags",
Required: false,
Type: "boolean",
},
{
Name: "environment",
Description: "Environment to run tests against",
Type: "environment",
Required: true,
},
},
},
{
Name: "push",
},
},
},
} }
for _, kase := range kases { for _, kase := range kases {
t.Run(kase.input, func(t *testing.T) { t.Run(kase.input, func(t *testing.T) {
@@ -297,7 +230,8 @@ func TestParseMappingNode(t *testing.T) {
{ {
input: "on:\n push:\n branches:\n - master", input: "on:\n push:\n branches:\n - master",
scalars: []string{"push"}, scalars: []string{"push"},
datas: []interface{}{ datas: []interface {
}{
map[string]interface{}{ map[string]interface{}{
"branches": []interface{}{"master"}, "branches": []interface{}{"master"},
}, },

View File

@@ -1,7 +1,6 @@
package model package model
import ( import (
"crypto/sha256"
"fmt" "fmt"
"io" "io"
"reflect" "reflect"
@@ -9,10 +8,9 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/nektos/act/pkg/common"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"github.com/nektos/act/pkg/common"
) )
// Workflow is the structure of the files in .github/workflows // Workflow is the structure of the files in .github/workflows
@@ -23,8 +21,6 @@ type Workflow struct {
Env map[string]string `yaml:"env"` Env map[string]string `yaml:"env"`
Jobs map[string]*Job `yaml:"jobs"` Jobs map[string]*Job `yaml:"jobs"`
Defaults Defaults `yaml:"defaults"` Defaults Defaults `yaml:"defaults"`
RawConcurrency *RawConcurrency `yaml:"concurrency"`
RawPermissions yaml.Node `yaml:"permissions"`
} }
// On events for the workflow // On events for the workflow
@@ -201,7 +197,6 @@ type Job struct {
Uses string `yaml:"uses"` Uses string `yaml:"uses"`
With map[string]interface{} `yaml:"with"` With map[string]interface{} `yaml:"with"`
RawSecrets yaml.Node `yaml:"secrets"` RawSecrets yaml.Node `yaml:"secrets"`
RawPermissions yaml.Node `yaml:"permissions"`
Result string Result string
} }
@@ -721,12 +716,6 @@ func (s *Step) Type() StepType {
return StepTypeUsesActionRemote return StepTypeUsesActionRemote
} }
// UsesHash returns a hash of the uses string.
// For Gitea.
func (s *Step) UsesHash() string {
return fmt.Sprintf("%x", sha256.Sum256([]byte(s.Uses)))
}
// ReadWorkflow returns a list of jobs for a given workflow file reader // ReadWorkflow returns a list of jobs for a given workflow file reader
func ReadWorkflow(in io.Reader) (*Workflow, error) { func ReadWorkflow(in io.Reader) (*Workflow, error) {
w := new(Workflow) w := new(Workflow)
@@ -772,10 +761,3 @@ func decodeNode(node yaml.Node, out interface{}) bool {
} }
return true return true
} }
// For Gitea
// RawConcurrency represents a workflow concurrency or a job concurrency with uninterpolated options
type RawConcurrency struct {
Group string `yaml:"group,omitempty"`
CancelInProgress string `yaml:"cancel-in-progress,omitempty"`
}

View File

@@ -603,37 +603,3 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
Type: "choice", Type: "choice",
}, workflowDispatch.Inputs["logLevel"]) }, workflowDispatch.Inputs["logLevel"])
} }
func TestStep_UsesHash(t *testing.T) {
type fields struct {
Uses string
}
tests := []struct {
name string
fields fields
want string
}{
{
name: "regular",
fields: fields{
Uses: "https://gitea.com/testa/testb@v3",
},
want: "ae437878e9f285bd7518c58664f9fabbb12d05feddd7169c01702a2a14322aa8",
},
{
name: "empty",
fields: fields{
Uses: "",
},
want: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &Step{
Uses: tt.fields.Uses,
}
assert.Equalf(t, tt.want, s.UsesHash(), "UsesHash()")
})
}
}

View File

@@ -535,7 +535,7 @@ func runPreStep(step actionStep) common.Executor {
var actionPath string var actionPath string
if _, ok := step.(*stepActionRemote); ok { if _, ok := step.(*stepActionRemote); ok {
actionPath = newRemoteAction(stepModel.Uses).Path actionPath = newRemoteAction(stepModel.Uses).Path
actionDir = fmt.Sprintf("%s/%s", rc.ActionCacheDir(), stepModel.UsesHash()) actionDir = fmt.Sprintf("%s/%s", rc.ActionCacheDir(), safeFilename(stepModel.Uses))
} else { } else {
actionDir = filepath.Join(rc.Config.Workdir, stepModel.Uses) actionDir = filepath.Join(rc.Config.Workdir, stepModel.Uses)
actionPath = "" actionPath = ""
@@ -579,7 +579,7 @@ func runPreStep(step actionStep) common.Executor {
var actionPath string var actionPath string
if _, ok := step.(*stepActionRemote); ok { if _, ok := step.(*stepActionRemote); ok {
actionPath = newRemoteAction(stepModel.Uses).Path actionPath = newRemoteAction(stepModel.Uses).Path
actionDir = fmt.Sprintf("%s/%s", rc.ActionCacheDir(), stepModel.UsesHash()) actionDir = fmt.Sprintf("%s/%s", rc.ActionCacheDir(), safeFilename(stepModel.Uses))
} else { } else {
actionDir = filepath.Join(rc.Config.Workdir, stepModel.Uses) actionDir = filepath.Join(rc.Config.Workdir, stepModel.Uses)
actionPath = "" actionPath = ""
@@ -665,7 +665,7 @@ func runPostStep(step actionStep) common.Executor {
var actionPath string var actionPath string
if _, ok := step.(*stepActionRemote); ok { if _, ok := step.(*stepActionRemote); ok {
actionPath = newRemoteAction(stepModel.Uses).Path actionPath = newRemoteAction(stepModel.Uses).Path
actionDir = fmt.Sprintf("%s/%s", rc.ActionCacheDir(), stepModel.UsesHash()) actionDir = fmt.Sprintf("%s/%s", rc.ActionCacheDir(), safeFilename(stepModel.Uses))
} else { } else {
actionDir = filepath.Join(rc.Config.Workdir, stepModel.Uses) actionDir = filepath.Join(rc.Config.Workdir, stepModel.Uses)
actionPath = "" actionPath = ""

View File

@@ -185,8 +185,7 @@ func setJobResult(ctx context.Context, info jobInfo, rc *RunContext, success boo
info.result(jobResult) info.result(jobResult)
if rc.caller != nil { if rc.caller != nil {
// set reusable workflow job result // set reusable workflow job result
rc.caller.setReusedWorkflowJobResult(rc.JobName, jobResult) // For Gitea rc.caller.runContext.result(jobResult)
return
} }
jobResultMessage := "succeeded" jobResultMessage := "succeeded"

View File

@@ -175,11 +175,7 @@ func newReusableWorkflowExecutor(rc *RunContext, directory string, workflow stri
return err return err
} }
// return runner.NewPlanExecutor(plan)(ctx) return runner.NewPlanExecutor(plan)(ctx)
return common.NewPipelineExecutor( // For Gitea
runner.NewPlanExecutor(plan),
setReusedWorkflowCallerResult(rc, runner),
)(ctx)
} }
} }
@@ -189,8 +185,6 @@ func NewReusableWorkflowRunner(rc *RunContext) (Runner, error) {
eventJSON: rc.EventJSON, eventJSON: rc.EventJSON,
caller: &caller{ caller: &caller{
runContext: rc, runContext: rc,
reusedWorkflowJobResults: map[string]string{}, // For Gitea
}, },
} }
@@ -275,47 +269,3 @@ func newRemoteReusableWorkflow(uses string) *remoteReusableWorkflow {
URL: "https://github.com", URL: "https://github.com",
} }
} }
// For Gitea
func setReusedWorkflowCallerResult(rc *RunContext, runner Runner) common.Executor {
return func(ctx context.Context) error {
logger := common.Logger(ctx)
runnerImpl, ok := runner.(*runnerImpl)
if !ok {
logger.Warn("Failed to get caller from runner")
return nil
}
caller := runnerImpl.caller
allJobDone := true
hasFailure := false
for _, result := range caller.reusedWorkflowJobResults {
if result == "pending" {
allJobDone = false
break
}
if result == "failure" {
hasFailure = true
}
}
if allJobDone {
reusedWorkflowJobResult := "success"
reusedWorkflowJobResultMessage := "succeeded"
if hasFailure {
reusedWorkflowJobResult = "failure"
reusedWorkflowJobResultMessage = "failed"
}
if rc.caller != nil {
rc.caller.setReusedWorkflowJobResult(rc.JobName, reusedWorkflowJobResult)
} else {
rc.result(reusedWorkflowJobResult)
logger.WithField("jobResult", reusedWorkflowJobResult).Infof("\U0001F3C1 Job %s", reusedWorkflowJobResultMessage)
}
}
return nil
}
}

View File

@@ -92,12 +92,7 @@ func (rc *RunContext) GetEnv() map[string]string {
} }
func (rc *RunContext) jobContainerName() string { func (rc *RunContext) jobContainerName() string {
nameParts := []string{rc.Config.ContainerNamePrefix, "WORKFLOW-" + rc.Run.Workflow.Name, "JOB-" + rc.Name} return createSimpleContainerName(rc.Config.ContainerNamePrefix, "WORKFLOW-"+rc.Run.Workflow.Name, "JOB-"+rc.Name)
if rc.caller != nil {
nameParts = append(nameParts, "CALLED-BY-"+rc.caller.runContext.JobName)
}
// return createSimpleContainerName(rc.Config.ContainerNamePrefix, "WORKFLOW-"+rc.Run.Workflow.Name, "JOB-"+rc.Name)
return createSimpleContainerName(nameParts...) // For Gitea
} }
// Deprecated: use `networkNameForGitea` // Deprecated: use `networkNameForGitea`
@@ -658,7 +653,6 @@ func (rc *RunContext) Executor() (common.Executor, error) {
return func(ctx context.Context) error { return func(ctx context.Context) error {
res, err := rc.isEnabled(ctx) res, err := rc.isEnabled(ctx)
if err != nil { if err != nil {
rc.caller.setReusedWorkflowJobResult(rc.JobName, "failure") // For Gitea
return err return err
} }
if res { if res {
@@ -754,10 +748,6 @@ func (rc *RunContext) isEnabled(ctx context.Context) (bool, error) {
} }
if !runJob { if !runJob {
if rc.caller != nil { // For Gitea
rc.caller.setReusedWorkflowJobResult(rc.JobName, "skipped")
return false, nil
}
l.WithField("jobResult", "skipped").Debugf("Skipping job '%s' due to '%s'", job.Name, job.If.Value) l.WithField("jobResult", "skipped").Debugf("Skipping job '%s' due to '%s'", job.Name, job.If.Value)
return false, nil return false, nil
} }

View File

@@ -6,7 +6,6 @@ import (
"fmt" "fmt"
"os" "os"
"runtime" "runtime"
"sync"
"time" "time"
docker_container "github.com/docker/docker/api/types/container" docker_container "github.com/docker/docker/api/types/container"
@@ -87,9 +86,6 @@ func (c Config) GetToken() string {
type caller struct { type caller struct {
runContext *RunContext runContext *RunContext
updateResultLock sync.Mutex // For Gitea
reusedWorkflowJobResults map[string]string // For Gitea
} }
type runnerImpl struct { type runnerImpl struct {
@@ -210,9 +206,6 @@ func (runner *runnerImpl) NewPlanExecutor(plan *model.Plan) common.Executor {
if len(rc.String()) > maxJobNameLen { if len(rc.String()) > maxJobNameLen {
maxJobNameLen = len(rc.String()) maxJobNameLen = len(rc.String())
} }
if rc.caller != nil { // For Gitea
rc.caller.setReusedWorkflowJobResult(rc.JobName, "pending")
}
stageExecutor = append(stageExecutor, func(ctx context.Context) error { stageExecutor = append(stageExecutor, func(ctx context.Context) error {
jobName := fmt.Sprintf("%-*s", maxJobNameLen, rc.String()) jobName := fmt.Sprintf("%-*s", maxJobNameLen, rc.String())
executor, err := rc.Executor() executor, err := rc.Executor()
@@ -284,10 +277,3 @@ func (runner *runnerImpl) newRunContext(ctx context.Context, run *model.Run, mat
return rc return rc
} }
// For Gitea
func (c *caller) setReusedWorkflowJobResult(jobName string, result string) {
c.updateResultLock.Lock()
defer c.updateResultLock.Unlock()
c.reusedWorkflowJobResults[jobName] = result
}

View File

@@ -108,7 +108,7 @@ func (sar *stepActionRemote) prepareActionExecutor() common.Executor {
return err return err
} }
actionDir := fmt.Sprintf("%s/%s", sar.RunContext.ActionCacheDir(), sar.Step.UsesHash()) actionDir := fmt.Sprintf("%s/%s", sar.RunContext.ActionCacheDir(), safeFilename(sar.Step.Uses))
gitClone := stepActionRemoteNewCloneExecutor(git.NewGitCloneExecutorInput{ gitClone := stepActionRemoteNewCloneExecutor(git.NewGitCloneExecutorInput{
URL: sar.remoteAction.CloneURL(sar.RunContext.Config.DefaultActionInstance), URL: sar.remoteAction.CloneURL(sar.RunContext.Config.DefaultActionInstance),
Ref: sar.remoteAction.Ref, Ref: sar.remoteAction.Ref,
@@ -177,7 +177,7 @@ func (sar *stepActionRemote) main() common.Executor {
return sar.RunContext.JobContainer.CopyDir(copyToPath, sar.RunContext.Config.Workdir+string(filepath.Separator)+".", sar.RunContext.Config.UseGitIgnore)(ctx) return sar.RunContext.JobContainer.CopyDir(copyToPath, sar.RunContext.Config.Workdir+string(filepath.Separator)+".", sar.RunContext.Config.UseGitIgnore)(ctx)
} }
actionDir := fmt.Sprintf("%s/%s", sar.RunContext.ActionCacheDir(), sar.Step.UsesHash()) actionDir := fmt.Sprintf("%s/%s", sar.RunContext.ActionCacheDir(), safeFilename(sar.Step.Uses))
return sar.runAction(sar, actionDir, sar.remoteAction)(ctx) return sar.runAction(sar, actionDir, sar.remoteAction)(ctx)
}), }),
@@ -236,7 +236,7 @@ func (sar *stepActionRemote) getActionModel() *model.Action {
func (sar *stepActionRemote) getCompositeRunContext(ctx context.Context) *RunContext { func (sar *stepActionRemote) getCompositeRunContext(ctx context.Context) *RunContext {
if sar.compositeRunContext == nil { if sar.compositeRunContext == nil {
actionDir := fmt.Sprintf("%s/%s", sar.RunContext.ActionCacheDir(), sar.Step.UsesHash()) actionDir := fmt.Sprintf("%s/%s", sar.RunContext.ActionCacheDir(), safeFilename(sar.Step.Uses))
actionLocation := path.Join(actionDir, sar.remoteAction.Path) actionLocation := path.Join(actionDir, sar.remoteAction.Path)
_, containerActionDir := getContainerActionPaths(sar.getStepModel(), actionLocation, sar.RunContext) _, containerActionDir := getContainerActionPaths(sar.getStepModel(), actionLocation, sar.RunContext)