1// SPDX-License-Identifier: MIT
2
3package workflow
4
5import (
6 "bnema.dev/ermite-actions/template"
7)
8
9// Error is a problem found in a workflow file. Its message has the form
10// "file.yml (Line: 3, Col: 5): message".
11type Error = template.Error
12
13// Workflow is a parsed and validated workflow file.
14type Workflow struct {
15 // File is the name given to Parse.
16 File string
17 // Name is the "name" key, or "".
18 Name string
19 // RunName is the "run-name" token (an expression is allowed), or nil.
20 RunName template.Token
21 // On lists the events that trigger the workflow, in file order.
22 On *On
23 // Env is the workflow-level "env" mapping, or nil. Values may hold
24 // expressions.
25 Env *template.Mapping
26 // Defaults holds the workflow-level "defaults", or nil.
27 Defaults *Defaults
28 // Concurrency is the "concurrency" token (a string or a mapping), or nil.
29 Concurrency template.Token
30 // Permissions is the "permissions" key, or nil.
31 Permissions *Permissions
32 // Jobs are the jobs in file order.
33 Jobs []*Job
34}
35
36// Job returns the job with the given id, or nil.
37func (w *Workflow) Job(id string) *Job {
38 for _, j := range w.Jobs {
39 if j.ID == id {
40 return j
41 }
42 }
43 return nil
44}
45
46// Defaults is the "defaults" key.
47type Defaults struct {
48 // Run holds defaults.run; nil when absent.
49 Run *RunDefaults
50}
51
52// RunDefaults is defaults.run: the shell and working directory of run steps.
53type RunDefaults struct {
54 Shell template.Token
55 WorkingDirectory template.Token
56}
57
58// Permissions is the "permissions" key: either all permissions read or
59// write, or a level per scope.
60type Permissions struct {
61 // All is "read-all" or "write-all", or "" when Scopes is used.
62 All string
63 // Scopes lists the scopes in file order ("contents": "read").
64 Scopes []PermissionScope
65}
66
67// PermissionScope is one entry of a permissions mapping.
68type PermissionScope struct {
69 Scope string
70 Level string // "read", "write" or "none"
71}
72
73// Job is a job of a workflow.
74type Job struct {
75 // ID is the key of the job.
76 ID string
77 // IDToken is the key token, with its position.
78 IDToken template.Token
79 // Name is the "name" token; when the file gives none it is the id.
80 Name template.Token
81 // HasName reports whether the file gave a non-empty name.
82 HasName bool
83 // Needs are the ids of the jobs this one depends on, with their tokens.
84 Needs []string
85 NeedTokens []*template.String
86 // If is the condition, always with a status function: a condition
87 // without one is wrapped as "success() && (cond)", and a missing one is
88 // "success()".
89 If *template.BasicExpression
90 // RunsOn is the "runs-on" token (string, sequence, mapping or an
91 // expression); nil for a reusable workflow job.
92 RunsOn template.Token
93 // Strategy is the "strategy" token, or nil.
94 Strategy template.Token
95 // Env is the job's "env" mapping, or nil.
96 Env *template.Mapping
97 // Defaults holds the job-level "defaults", or nil.
98 Defaults *Defaults
99 // Steps are the steps in file order.
100 Steps []*Step
101 // Outputs is the "outputs" mapping, or nil.
102 Outputs *template.Mapping
103 // TimeoutMinutes, CancelTimeoutMinutes and ContinueOnError are tokens
104 // (a literal or an expression), or nil.
105 TimeoutMinutes template.Token
106 CancelTimeoutMinutes template.Token
107 ContinueOnError template.Token
108 // Container, Services, Environment, Concurrency and Snapshot are
109 // the raw tokens, or nil.
110 Container template.Token
111 Services template.Token
112 Environment template.Token
113 Concurrency template.Token
114 Snapshot template.Token
115 // Permissions is the job's "permissions", or nil.
116 Permissions *Permissions
117
118 // Uses is set for a job that calls a reusable workflow ("uses"); such a
119 // job has no steps and no runs-on.
120 Uses *template.String
121 // With and Secrets are the inputs and secrets passed to the called
122 // workflow. InheritSecrets is "secrets: inherit".
123 With *template.Mapping
124 Secrets *template.Mapping
125 InheritSecrets bool
126}
127
128// IsReusable reports whether the job calls a reusable workflow.
129func (j *Job) IsReusable() bool { return j.Uses != nil }
130
131// Step is a step of a job: a run step or a uses step.
132type Step struct {
133 // ID is the id of the step. When the file gives none, one is generated
134 // the way the reference does: "__run", "__run_2", "__actions_checkout".
135 ID string
136 // Explicit reports whether the id came from the file.
137 Explicit bool
138 // Pos is where the step starts.
139 Pos template.Pos
140 // Name is the "name" token, or nil.
141 Name template.Token
142 // If is the condition, with a status function, as for jobs.
143 If *template.BasicExpression
144 // Run is the script of a run step, or nil.
145 Run template.Token
146 // Shell and WorkingDirectory are the run step's options, or nil.
147 Shell template.Token
148 WorkingDirectory template.Token
149 // Uses is the action of a uses step, or nil.
150 Uses *template.String
151 // With holds the inputs of a uses step, or nil.
152 With *template.Mapping
153 // Env is the step's "env" mapping, or nil.
154 Env *template.Mapping
155 // EnvExpression and WithExpression hold "env" and "with" when the whole
156 // value is an expression (env: ${{ fromJSON(...) }}); Env and With are then
157 // nil. Only package action fills them, for the steps of a composite action
158 // (the C# runner accepts such a step there); Parse of a workflow does not.
159 EnvExpression, WithExpression template.Token
160 // ContinueOnError and TimeoutMinutes are tokens, or nil.
161 ContinueOnError template.Token
162 TimeoutMinutes template.Token
163}
164
165// IsRun reports whether the step runs a script.
166func (s *Step) IsRun() bool { return s.Run != nil }