-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparse.go
135 lines (112 loc) · 3.65 KB
/
parse.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Copyright (C) 2023-2024 Eric Cornelissen
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package ades
import (
"errors"
"fmt"
"strings"
"gopkg.in/yaml.v3"
)
// Workflow is a (simplified) representation of a GitHub Actions workflow.
type Workflow struct {
Jobs map[string]WorkflowJob `yaml:"jobs"`
}
// WorkflowJob is a (simplified) representation of a workflow job.
type WorkflowJob struct {
Name string `yaml:"name"`
Steps []JobStep `yaml:"steps"`
}
// JobStep is a (simplified) representation of a workflow job step object.
type JobStep struct {
With map[string]string `yaml:"with"`
Env map[string]string `yaml:"env"`
Name string `yaml:"name"`
Run string `yaml:"run"`
Uses string `yaml:"uses"`
UsesComment string `yaml:"-"`
}
func (step *JobStep) UnmarshalYAML(node *yaml.Node) error {
for i := range node.Content {
if i%2 == 1 {
continue
}
key := node.Content[i].Value
value := node.Content[i+1]
var err error
switch key {
case "env":
err = value.Decode(&step.Env)
case "name":
step.Name = value.Value
case "run":
step.Run = value.Value
case "uses":
step.Uses = value.Value
step.UsesComment = strings.TrimLeft(value.LineComment, "# ")
case "with":
err = value.Decode(&step.With)
}
if err != nil {
return err
}
}
return nil
}
// ParseWorkflow parses a GitHub Actions workflow file into a Workflow struct.
func ParseWorkflow(data []byte) (Workflow, error) {
var workflow Workflow
if err := yaml.Unmarshal(data, &workflow); err != nil {
return workflow, fmt.Errorf("could not parse workflow: %v", err)
}
return workflow, nil
}
// Manifest is a (simplified) representation of a GitHub Actions Action manifest.
type Manifest struct {
Runs ManifestRuns `yaml:"runs"`
}
// ManifestRuns is a (simplified) representation of an Action manifest's `runs:` object.
type ManifestRuns struct {
Using string `yaml:"using"`
Steps []JobStep `yaml:"steps"`
}
// ParseManifest parses a GitHub Actions Action manifest file into a Manifest struct.
func ParseManifest(data []byte) (Manifest, error) {
var manifest Manifest
if err := yaml.Unmarshal(data, &manifest); err != nil {
return manifest, fmt.Errorf("could not parse manifest: %v", err)
}
return manifest, nil
}
// StepUses is a structured representation of a workflow job step `uses:` value.
type StepUses struct {
// Name is the name of the Action that is used. Typically <owner>/<repository>.
Name string
// Ref is the git reference used for the Action. Typically a tag ref, branch ref, or commit SHA.
Ref string
// Annotation is the comment after the `uses:` value, if any.
Annotation string
}
// ParseUses parses a Github Actions workflow job step's `uses:` value.
func ParseUses(step *JobStep) (StepUses, error) {
var uses StepUses
i := strings.LastIndex(step.Uses, "@")
if i <= 0 || i >= len(step.Uses)-1 {
return uses, errors.New("step has no or invalid `uses` value")
}
uses.Name = step.Uses[:i]
uses.Ref = step.Uses[i+1:]
uses.Annotation = step.UsesComment
return uses, nil
}