feat: parse types of reusable workflows (#1414)

This change does parse the different types of workflow jobs.
It is not much by itself but the start to implement reusable
workflows.

Relates to #826

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
Markus Wolf 2022-11-01 16:58:07 +01:00 committed by GitHub
parent a9298d936c
commit 9b95a728d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 75 additions and 0 deletions

View File

@ -380,6 +380,42 @@ func commonKeysMatch2(a map[string]interface{}, b map[string]interface{}, m map[
return true return true
} }
// JobType describes what type of job we are about to run
type JobType int
const (
// StepTypeRun is all steps that have a `run` attribute
JobTypeDefault JobType = iota
// StepTypeReusableWorkflowLocal is all steps that have a `uses` that is a local workflow in the .github/workflows directory
JobTypeReusableWorkflowLocal
// JobTypeReusableWorkflowRemote is all steps that have a `uses` that references a workflow file in a github repo
JobTypeReusableWorkflowRemote
)
func (j JobType) String() string {
switch j {
case JobTypeDefault:
return "default"
case JobTypeReusableWorkflowLocal:
return "local-reusable-workflow"
case JobTypeReusableWorkflowRemote:
return "remote-reusable-workflow"
}
return "unknown"
}
// Type returns the type of the job
func (j *Job) Type() JobType {
if strings.HasPrefix(j.Uses, "./.github/workflows") && (strings.HasSuffix(j.Uses, ".yml") || strings.HasSuffix(j.Uses, ".yaml")) {
return JobTypeReusableWorkflowLocal
} else if !strings.HasPrefix(j.Uses, "./") && strings.Contains(j.Uses, ".github/workflows") && (strings.Contains(j.Uses, ".yml@") || strings.Contains(j.Uses, ".yaml@")) {
return JobTypeReusableWorkflowRemote
}
return JobTypeDefault
}
// ContainerSpec is the specification of the container to use for the job // ContainerSpec is the specification of the container to use for the job
type ContainerSpec struct { type ContainerSpec struct {
Image string `yaml:"image"` Image string `yaml:"image"`
@ -486,6 +522,12 @@ const (
// StepTypeUsesActionRemote is all steps that have a `uses` that is a reference to a github repo // StepTypeUsesActionRemote is all steps that have a `uses` that is a reference to a github repo
StepTypeUsesActionRemote StepTypeUsesActionRemote
// StepTypeReusableWorkflowLocal is all steps that have a `uses` that is a local workflow in the .github/workflows directory
StepTypeReusableWorkflowLocal
// StepTypeReusableWorkflowRemote is all steps that have a `uses` that references a workflow file in a github repo
StepTypeReusableWorkflowRemote
// StepTypeInvalid is for steps that have invalid step action // StepTypeInvalid is for steps that have invalid step action
StepTypeInvalid StepTypeInvalid
) )
@ -502,6 +544,10 @@ func (s StepType) String() string {
return "remote-action" return "remote-action"
case StepTypeUsesDockerURL: case StepTypeUsesDockerURL:
return "docker" return "docker"
case StepTypeReusableWorkflowLocal:
return "local-reusable-workflow"
case StepTypeReusableWorkflowRemote:
return "remote-reusable-workflow"
} }
return "unknown" return "unknown"
} }
@ -519,6 +565,10 @@ func (s *Step) Type() StepType {
return StepTypeRun return StepTypeRun
} else if strings.HasPrefix(s.Uses, "docker://") { } else if strings.HasPrefix(s.Uses, "docker://") {
return StepTypeUsesDockerURL return StepTypeUsesDockerURL
} else if strings.HasPrefix(s.Uses, "./.github/workflows") && (strings.HasSuffix(s.Uses, ".yml") || strings.HasSuffix(s.Uses, ".yaml")) {
return StepTypeReusableWorkflowLocal
} else if !strings.HasPrefix(s.Uses, "./") && strings.Contains(s.Uses, ".github/workflows") && (strings.Contains(s.Uses, ".yml@") || strings.Contains(s.Uses, ".yaml@")) {
return StepTypeReusableWorkflowRemote
} else if strings.HasPrefix(s.Uses, "./") { } else if strings.HasPrefix(s.Uses, "./") {
return StepTypeUsesActionLocal return StepTypeUsesActionLocal
} }

View File

@ -138,6 +138,31 @@ jobs:
}) })
} }
func TestReadWorkflow_JobTypes(t *testing.T) {
yaml := `
name: invalid job definition
jobs:
default-job:
runs-on: ubuntu-latest
steps:
- run: echo
remote-reusable-workflow:
runs-on: ubuntu-latest
uses: remote/repo/.github/workflows/workflow.yml@main
local-reusable-workflow:
runs-on: ubuntu-latest
uses: ./.github/workflows/workflow.yml
`
workflow, err := ReadWorkflow(strings.NewReader(yaml))
assert.NoError(t, err, "read workflow should succeed")
assert.Len(t, workflow.Jobs, 3)
assert.Equal(t, workflow.Jobs["default-job"].Type(), JobTypeDefault)
assert.Equal(t, workflow.Jobs["remote-reusable-workflow"].Type(), JobTypeReusableWorkflowRemote)
assert.Equal(t, workflow.Jobs["local-reusable-workflow"].Type(), JobTypeReusableWorkflowLocal)
}
func TestReadWorkflow_StepsTypes(t *testing.T) { func TestReadWorkflow_StepsTypes(t *testing.T) {
yaml := ` yaml := `
name: invalid step definition name: invalid step definition