Skip to content

idea: AST-based yaml parsing and rewriting #13

Description

@mccutchen

We currently extract actions from workflow definitions via a fairly naive regex

ghavm/scanner.go

Lines 100 to 111 in 769c9e8

var usesPattern = regexp.MustCompile(`^\s*-?\s*uses:\s*([\w\-]+/[\w\-]+)@([\w\-\./]+)(?:\s*#.*)?$`)
func maybeParseAction(line string) Action {
matches := usesPattern.FindStringSubmatch(line)
if matches == nil {
return Action{}
}
return Action{
Name: matches[1],
Ref: matches[2],
}
}

and rewrite workflows by replacing whole lines where we've extracted an action:

ghavm/engine.go

Lines 191 to 207 in 769c9e8

before, _, found := strings.Cut(line, "uses:")
if !found {
return fmt.Errorf("expected `uses:` declaration on line %d, got %q", lineNum, line)
}
// write prefix
out.WriteString(before + "uses: ")
// append pinned action version
fmt.Fprintf(out, "%s@%s", step.Action.Name, pin.CommitHash)
// append version hint in comment
if pin.Version != "" {
fmt.Fprintf(out, " # %s", pin.Version)
} else if step.Action.Ref != pin.CommitHash {
fmt.Fprintf(out, " # ref:%s", step.Action.Ref)
}
// append correct line ending based on original line
fmt.Fprint(out, matchEOL(line))

This works reasonably well with the workflows I've tried it with, but I'd feel a bit better if we were actually parsing and rewriting workflows a bit more robustly, e.g. via goccy/go-yaml's AST manipulation support. I think it offers the functionality we need, but AFAICT rewrites would be somewhat destructive in the sense of forcing a specific YAML serialization style instead of matching the existing style.

I'm not sure how viable this is, and maybe the simplistic approach we have here is good enough.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestquestionFurther information is requested

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions