mirror of
https://github.com/anchore/syft.git
synced 2026-07-05 02:28:25 +02:00
fix: composite action version parsing (#4616)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
This commit is contained in:
parent
e7f1a803e7
commit
deee79411a
@ -73,7 +73,6 @@ func parseStepUsageStatement(use, comment string) (string, string) {
|
|||||||
|
|
||||||
// if version looks like a commit hash and we have a comment, try to extract version from comment
|
// if version looks like a commit hash and we have a comment, try to extract version from comment
|
||||||
if version != "" && regexp.MustCompile(`^[0-9a-f]{7,}$`).MatchString(version) && comment != "" {
|
if version != "" && regexp.MustCompile(`^[0-9a-f]{7,}$`).MatchString(version) && comment != "" {
|
||||||
versionRegex := regexp.MustCompile(`v?\d+\.\d+\.\d+`)
|
|
||||||
matches := versionRegex.FindStringSubmatch(comment)
|
matches := versionRegex.FindStringSubmatch(comment)
|
||||||
|
|
||||||
if len(matches) >= 1 {
|
if len(matches) >= 1 {
|
||||||
|
|||||||
@ -24,12 +24,19 @@ type compositeActionRunsDef struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseCompositeActionForActionUsage(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseCompositeActionForActionUsage(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var ca compositeActionDef
|
|
||||||
var errs error
|
var errs error
|
||||||
if errs = yaml.NewDecoder(reader).Decode(&ca); errs != nil {
|
var node yaml.Node
|
||||||
|
if errs = yaml.NewDecoder(reader).Decode(&node); errs != nil {
|
||||||
|
return nil, nil, fmt.Errorf("unable to parse yaml workflow file: %w", errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
var ca compositeActionDef
|
||||||
|
if errs = node.Decode(&ca); errs != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to parse yaml composite action file: %w", errs)
|
return nil, nil, fmt.Errorf("unable to parse yaml composite action file: %w", errs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
attachCompositeActionUsageComments(&node, ca.Runs.Steps)
|
||||||
|
|
||||||
// we use a collection to help with deduplication before raising to higher level processing
|
// we use a collection to help with deduplication before raising to higher level processing
|
||||||
pkgs := pkg.NewCollection()
|
pkgs := pkg.NewCollection()
|
||||||
|
|
||||||
@ -49,3 +56,62 @@ func parseCompositeActionForActionUsage(_ context.Context, _ file.Resolver, _ *g
|
|||||||
|
|
||||||
return pkgs.Sorted(), nil, errs
|
return pkgs.Sorted(), nil, errs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func attachCompositeActionUsageComments(node *yaml.Node, steps []stepDef) {
|
||||||
|
root := node
|
||||||
|
if root.Kind == yaml.DocumentNode && len(root.Content) > 0 {
|
||||||
|
root = root.Content[0]
|
||||||
|
}
|
||||||
|
if root.Kind != yaml.MappingNode {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the "runs" key
|
||||||
|
for i := 0; i < len(root.Content); i += 2 {
|
||||||
|
key := root.Content[i]
|
||||||
|
value := root.Content[i+1]
|
||||||
|
if key.Value != "runs" || value.Kind != yaml.MappingNode {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// find the "steps" key within runs
|
||||||
|
for j := 0; j < len(value.Content); j += 2 {
|
||||||
|
stepsKey := value.Content[j]
|
||||||
|
stepsValue := value.Content[j+1]
|
||||||
|
if stepsKey.Value != "steps" || stepsValue.Kind != yaml.SequenceNode {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
readSteps(stepsValue, steps)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func readSteps(stepsValue *yaml.Node, steps []stepDef) {
|
||||||
|
// iterate over each step
|
||||||
|
for stepIdx, stepNode := range stepsValue.Content {
|
||||||
|
if stepNode.Kind != yaml.MappingNode {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// find the "uses" key within the step
|
||||||
|
for k := 0; k < len(stepNode.Content); k += 2 {
|
||||||
|
usesKey := stepNode.Content[k]
|
||||||
|
usesValue := stepNode.Content[k+1]
|
||||||
|
if usesKey.Value != "uses" || usesValue.Kind != yaml.ScalarNode {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
comment := usesValue.LineComment
|
||||||
|
if comment == "" {
|
||||||
|
comment = usesValue.HeadComment
|
||||||
|
}
|
||||||
|
if comment == "" {
|
||||||
|
comment = usesValue.FootComment
|
||||||
|
}
|
||||||
|
if comment == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
versionMatch := versionRegex.FindString(comment)
|
||||||
|
if versionMatch != "" && stepIdx < len(steps) {
|
||||||
|
steps[stepIdx].UsesComment = versionMatch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -14,6 +14,28 @@ func Test_parseCompositeActionForActionUsage(t *testing.T) {
|
|||||||
fixtureLocationSet := file.NewLocationSet(file.NewLocation(fixture).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation))
|
fixtureLocationSet := file.NewLocationSet(file.NewLocation(fixture).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation))
|
||||||
|
|
||||||
expected := []pkg.Package{
|
expected := []pkg.Package{
|
||||||
|
{
|
||||||
|
Name: "actions/checkout",
|
||||||
|
Version: "11",
|
||||||
|
Type: pkg.GithubActionPkg,
|
||||||
|
Locations: fixtureLocationSet,
|
||||||
|
PURL: "pkg:github/actions/checkout@11",
|
||||||
|
Metadata: pkg.GitHubActionsUseStatement{
|
||||||
|
Value: "actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683",
|
||||||
|
Comment: "11",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "actions/setup-go",
|
||||||
|
Version: "v5.1.0",
|
||||||
|
Type: pkg.GithubActionPkg,
|
||||||
|
Locations: fixtureLocationSet,
|
||||||
|
PURL: "pkg:github/actions/setup-go@v5.1.0",
|
||||||
|
Metadata: pkg.GitHubActionsUseStatement{
|
||||||
|
Value: "actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed",
|
||||||
|
Comment: "v5.1.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "actions/setup-go",
|
Name: "actions/setup-go",
|
||||||
Version: "v4",
|
Version: "v4",
|
||||||
|
|||||||
@ -19,6 +19,8 @@ var (
|
|||||||
_ generic.Parser = parseWorkflowForWorkflowUsage
|
_ generic.Parser = parseWorkflowForWorkflowUsage
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var versionRegex = regexp.MustCompile(`v?\d+(\.\d+)*`)
|
||||||
|
|
||||||
type workflowDef struct {
|
type workflowDef struct {
|
||||||
Jobs map[string]workflowJobDef `yaml:"jobs"`
|
Jobs map[string]workflowJobDef `yaml:"jobs"`
|
||||||
}
|
}
|
||||||
@ -185,7 +187,6 @@ func processUsesNode(node *yaml.Node, wf *workflowDef, currentJob *string, curre
|
|||||||
}
|
}
|
||||||
|
|
||||||
if comment != "" {
|
if comment != "" {
|
||||||
versionRegex := regexp.MustCompile(`v?\d+(\.\d+)*`)
|
|
||||||
versionMatch := versionRegex.FindString(comment)
|
versionMatch := versionRegex.FindString(comment)
|
||||||
|
|
||||||
if versionMatch != "" {
|
if versionMatch != "" {
|
||||||
|
|||||||
@ -35,6 +35,13 @@ runs:
|
|||||||
path: ${{ github.workspace }}/.tmp
|
path: ${{ github.workspace }}/.tmp
|
||||||
key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-tool-${{ hashFiles('Makefile') }}
|
key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-tool-${{ hashFiles('Makefile') }}
|
||||||
|
|
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v 11
|
||||||
|
|
||||||
|
- name: Setup Go
|
||||||
|
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed #v5.1.0
|
||||||
|
with:
|
||||||
|
go-version: ${{ inputs.go-version }}
|
||||||
|
|
||||||
# note: we need to keep restoring the go mod cache before bootstrapping tools since `go install` is used in
|
# note: we need to keep restoring the go mod cache before bootstrapping tools since `go install` is used in
|
||||||
# some installations of project tools.
|
# some installations of project tools.
|
||||||
- name: Restore go module cache
|
- name: Restore go module cache
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user