diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0e97de7cad..24c99bc96b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,7 +21,7 @@ jobs: - uses: 'actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491' # ratchet:actions/setup-go@v5 with: - go-version: '1.21' + go-version-file: 'go.mod' - uses: 'docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20' # ratchet:docker/login-action@v3 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0a45e6844a..257ab51d9f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,8 +21,13 @@ jobs: - uses: 'actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491' # ratchet:actions/setup-go@v5 with: - go-version: '1.21' + go-version-file: 'go.mod' - name: 'Run tests' run: |- - go test -count=1 -shuffle=on -timeout=10m -race ./... + go test \ + -count=1 \ + -shuffle=on \ + -timeout=10m \ + -race \ + ./... diff --git a/command/check.go b/command/check.go index 40753f2029..e41f1aa81b 100644 --- a/command/check.go +++ b/command/check.go @@ -62,7 +62,7 @@ func (c *CheckCommand) Run(ctx context.Context, originalArgs []string) error { fsys := os.DirFS(".") - files, err := loadYAMLFiles(fsys, args, false) + files, err := loadYAMLFiles(fsys, args) if err != nil { return err } diff --git a/command/command.go b/command/command.go index 203e33a5af..f09d35a865 100644 --- a/command/command.go +++ b/command/command.go @@ -9,14 +9,13 @@ import ( "fmt" "io/fs" "os" + "slices" + "strconv" "strings" // Using banydonk/yaml instead of the default yaml pkg because the default // pkg incorrectly escapes unicode. https://github.com/go-yaml/yaml/issues/737 "github.com/braydonk/yaml" - "github.com/hexops/gotextdiff" - "github.com/hexops/gotextdiff/myers" - "github.com/hexops/gotextdiff/span" "github.com/sethvargo/ratchet/internal/version" ) @@ -93,24 +92,48 @@ func extractCommandAndArgs(args []string) (string, []string) { } // marshalYAML encodes the yaml node into the given writer. -func marshalYAML(m *yaml.Node) ([]byte, error) { +func marshalYAML(m *yaml.Node) (string, error) { var b bytes.Buffer enc := yaml.NewEncoder(&b) enc.SetIndent(2) + enc.SetAssumeBlockAsLiteral(true) if err := enc.Encode(m); err != nil { - return nil, fmt.Errorf("failed to encode yaml: %w", err) + return "", fmt.Errorf("failed to encode yaml: %w", err) } if err := enc.Close(); err != nil { - return nil, fmt.Errorf("failed to finalize yaml: %w", err) + return "", fmt.Errorf("failed to finalize yaml: %w", err) } - return b.Bytes(), nil + return b.String(), nil } type loadResult struct { path string node *yaml.Node - contents []byte + contents string + newlines []int +} + +func (r *loadResult) marshalYAML() (string, error) { + contents, err := marshalYAML(r.node) + if err != nil { + return "", err + } + + // Restore newlines + lines := strings.Split(contents, "\n") + + for _, v := range r.newlines { + lines = slices.Insert(lines, v, "") + } + + // Handle the edge case where a document starts with "---", which the Go YAML + // parser discards. + if strings.HasPrefix(strings.TrimSpace(r.contents), "---") && !strings.HasPrefix(contents, "---") { + lines = slices.Insert(lines, 0, "---") + } + + return strings.Join(lines, "\n"), nil } type loadResults []*loadResult @@ -123,7 +146,7 @@ func (r loadResults) nodes() []*yaml.Node { return n } -func loadYAMLFiles(fsys fs.FS, paths []string, format bool) (loadResults, error) { +func loadYAMLFiles(fsys fs.FS, paths []string) (loadResults, error) { r := make(loadResults, 0, len(paths)) for _, pth := range paths { @@ -134,94 +157,75 @@ func loadYAMLFiles(fsys fs.FS, paths []string, format bool) (loadResults, error) } var node yaml.Node - if err := yaml.Unmarshal(contents, &node); err != nil { + dec := yaml.NewDecoder(bytes.NewReader(contents)) + dec.SetScanBlockScalarAsLiteral(true) + if err := dec.Decode(&node); err != nil { return nil, fmt.Errorf("failed to parse yaml for %s: %w", pth, err) } - lr := &loadResult{ - path: pth, - node: &node, - contents: contents, - } - if format { - if err := fixIndentation(lr); err != nil { - return nil, fmt.Errorf("failed to format indentation: %w", err) - } + // Remarshal the content before any modification so we can compute the + // places where a newline should be inserted post-rendering. + remarshaled, err := marshalYAML(&node) + if err != nil { + return nil, fmt.Errorf("failed to remarshal yaml for %s: %w", pth, err) } - r = append(r, lr) + newlines := computeNewlineTargets(string(contents), remarshaled) + + r = append(r, &loadResult{ + path: pth, + node: &node, + contents: string(contents), + newlines: newlines, + }) } return r, nil } -// fixIndentation corrects the indentation for the given loadResult and edits it in-place. -func fixIndentation(f *loadResult) error { - updated, err := marshalYAML(f.node) - if err != nil { - return fmt.Errorf("failed to marshal yaml for %s: %w", f.path, err) - } - lines := strings.Split(string(f.contents), "\n") - afterLines := strings.Split(string(updated), "\n") - - editedLines := []string{} - afterIndex := 0 - // Loop through both lists line by line using a two-pointer technique. - for _, l := range lines { - token := strings.TrimSpace(l) - if token == "" { - editedLines = append(editedLines, l) - continue +func computeNewlineTargets(before, after string) []int { + before = strings.TrimPrefix(before, "---\n") + + debug, _ := strconv.ParseBool(os.Getenv("RATCHET_DEBUG_NEWLINE_PARSING")) + if debug { + fmt.Fprintf(os.Stderr, "\n") + fmt.Fprintf(os.Stderr, "Original content:\n") + for i, l := range strings.Split(string(before), "\n") { + fmt.Fprintf(os.Stderr, "%3d: %s\n", i, l) } - currentAfterLine := afterLines[afterIndex] - indexInAfterLine := strings.Index(currentAfterLine, token) - for indexInAfterLine == -1 { - afterIndex++ - currentAfterLine = afterLines[afterIndex] - indexInAfterLine = strings.Index(currentAfterLine, token) + fmt.Fprintf(os.Stderr, "\n") + fmt.Fprintf(os.Stderr, "Rendered content:\n") + for i, l := range strings.Split(after, "\n") { + fmt.Fprintf(os.Stderr, "%3d: %s\n", i, l) } - - lineWithCorrectIndent := currentAfterLine[:indexInAfterLine] + token - editedLines = append(editedLines, lineWithCorrectIndent) - afterIndex++ + fmt.Fprintf(os.Stderr, "\n") } - f.contents = []byte(strings.Join(editedLines, "\n")) - return nil -} + result := make([]int, 0, 8) + afteri, afterLines := 0, strings.Split(after, "\n") + beforeLines := strings.Split(before, "\n") -func removeNewLineChanges(beforeContent, afterContent string) string { - lines := strings.Split(beforeContent, "\n") - edits := myers.ComputeEdits(span.URIFromPath("before.txt"), beforeContent, afterContent) - unified := gotextdiff.ToUnified("before.txt", "after.txt", beforeContent, edits) - - editedLines := make(map[int]string) - // Iterates through all changes and only keep changes to lines that are not empty. - for _, h := range unified.Hunks { - // Changes are in-order of delete line followed by insert line for lines that were modified. - // We want to locate the position of all deletes of non-empty lines and replace - // these in the original content with the modified line. - var deletePositions []int - inserts := 0 - for i, l := range h.Lines { - if l.Kind == gotextdiff.Delete && l.Content != "\n" { - deletePositions = append(deletePositions, h.FromLine+i-1-inserts) - } - if l.Kind == gotextdiff.Insert && l.Content != "" { - pos := deletePositions[0] - deletePositions = deletePositions[1:] - editedLines[pos] = strings.TrimSuffix(l.Content, "\n") - inserts++ - } + for beforei := 0; beforei < len(beforeLines); beforei++ { + if afteri >= len(afterLines) { + result = append(result, beforei) + continue } - } - var formattedLines []string - for i, line := range lines { - if editedLine, ok := editedLines[i]; ok { - formattedLines = append(formattedLines, editedLine) + + beforeLine := strings.TrimSpace(beforeLines[beforei]) + afterLine := strings.TrimSpace(afterLines[afteri]) + + if beforeLine != afterLine && beforeLine == "" { + result = append(result, beforei) } else { - formattedLines = append(formattedLines, line) + afteri++ } } - return strings.Join(formattedLines, "\n") + + if debug { + fmt.Fprintf(os.Stderr, "\n") + fmt.Fprintf(os.Stderr, "newline indicies: %v\n", result) + fmt.Fprintf(os.Stderr, "\n") + } + + return result } diff --git a/command/command_test.go b/command/command_test.go index cb780d2cff..c0aa4f9d02 100644 --- a/command/command_test.go +++ b/command/command_test.go @@ -1,310 +1,115 @@ package command import ( + "io/fs" "os" - "reflect" "testing" + "testing/fstest" "github.com/google/go-cmp/cmp" ) -const ( - yamlA = ` -jobs: - init: - runs-on: 'ubuntu-latest' - outputs: - directories: '${{ steps.dirs.outputs.directories }}' - steps: - - uses: 'actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab' # ratchet:actions/checkout@v3 - - - uses: 'actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab' # ratchet:actions/checkout@v3 - - - name: 'Guardian Directories' - id: 'dirs' - uses: 'abcxyz/guardian/.github/actions/directories@52a8396df1c40bde244947c887d2c5dfbd36e4ce' # ratchet:abcxyz/guardian/.github/actions/directories@main - with: - directories: '${{ inputs.directories }}' -` - yamlAChanges = ` -jobs: - init: - runs-on: 'ubuntu-latest' - outputs: - directories: '${{ steps.dirs.outputs.directories }}' - steps: - - uses: 'actions/checkout@9239842384293848238sfsdf823e234234234sds' # ratchet:actions/checkout@v3 - - uses: 'actions/checkout@9239842384293848238sfsdf823e234234234sds' # ratchet:actions/checkout@v3 - - name: 'Guardian Directories' - id: 'dirs' - uses: 'abcxyz/guardian/.github/actions/directories@sdfswdf23423423423423sdfsdfsdfsdfdsfsdf2' # ratchet:abcxyz/guardian/.github/actions/directories@main - with: - directories: '${{ inputs.directories }}' -` - yamlAChangesFormatted = ` -jobs: - init: - runs-on: 'ubuntu-latest' - outputs: - directories: '${{ steps.dirs.outputs.directories }}' - steps: - - uses: 'actions/checkout@9239842384293848238sfsdf823e234234234sds' # ratchet:actions/checkout@v3 - - - uses: 'actions/checkout@9239842384293848238sfsdf823e234234234sds' # ratchet:actions/checkout@v3 - - - name: 'Guardian Directories' - id: 'dirs' - uses: 'abcxyz/guardian/.github/actions/directories@sdfswdf23423423423423sdfsdfsdfsdfdsfsdf2' # ratchet:abcxyz/guardian/.github/actions/directories@main - with: - directories: '${{ inputs.directories }}' -` - yamlB = ` -jobs: - init: - runs-on: 'ubuntu-latest' - outputs: - directories: '${{ steps.dirs.outputs.directories }}' - steps: - - name: 'Checkout' - uses: 'actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab' # ratchet:actions/checkout@v3 - - - name: 'Guardian Directories' - id: 'dirs' - uses: 'abcxyz/guardian/.github/actions/directories@52a8396df1c40bde244947c887d2c5dfbd36e4ce' # ratchet:abcxyz/guardian/.github/actions/directories@main - with: - directories: '${{ inputs.directories }}' -` - yamlBChanges = ` -jobs: - init: - runs-on: 'ubuntu-latest' - outputs: - directories: '${{ steps.dirs.outputs.directories }}' - steps: - - name: 'Checkout' - uses: 'actions/checkout@9239842384293848238sfsdf823e234234234sds' # ratchet:actions/checkout@v3 - - name: 'Guardian Directories' - id: 'dirs' - uses: 'abcxyz/guardian/.github/actions/directories@sdfswdf23423423423423sdfsdfsdfsdfdsfsdf2' # ratchet:abcxyz/guardian/.github/actions/directories@main - with: - directories: '${{ inputs.directories }}' -` - yamlBChangesFormatted = ` -jobs: - init: - runs-on: 'ubuntu-latest' - outputs: - directories: '${{ steps.dirs.outputs.directories }}' - steps: - - name: 'Checkout' - uses: 'actions/checkout@9239842384293848238sfsdf823e234234234sds' # ratchet:actions/checkout@v3 - - - name: 'Guardian Directories' - id: 'dirs' - uses: 'abcxyz/guardian/.github/actions/directories@sdfswdf23423423423423sdfsdfsdfsdfdsfsdf2' # ratchet:abcxyz/guardian/.github/actions/directories@main - with: - directories: '${{ inputs.directories }}' -` - yamlC = ` -jobs: - init: - runs-on: 'ubuntu-latest' - outputs: - directories: '${{ steps.dirs.outputs.directories }}' - steps: - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - name: 'Checkout' - uses: 'actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab' # ratchet:actions/checkout@v3 +func Test_loadYAMLFiles(t *testing.T) { + t.Parallel() - - name: 'Guardian Directories' - id: 'dirs' - uses: 'abcxyz/guardian/.github/actions/directories@52a8396df1c40bde244947c887d2c5dfbd36e4ce' # ratchet:abcxyz/guardian/.github/actions/directories@main - with: - directories: '${{ inputs.directories }}' -` - yamlCChanges = ` -jobs: - init: - runs-on: 'ubuntu-latest' - outputs: - directories: '${{ steps.dirs.outputs.directories }}' - steps: - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - name: 'Checkout' - uses: 'actions/checkout@9239842384293848238sfsdf823e234234234sds' # ratchet:actions/checkout@v3 - - name: 'Guardian Directories' - id: 'dirs' - uses: 'abcxyz/guardian/.github/actions/directories@sdfswdf23423423423423sdfsdfsdfsdfdsfsdf2' # ratchet:abcxyz/guardian/.github/actions/directories@main - with: - directories: '${{ inputs.directories }}' -` - yamlCChangesFormatted = ` -jobs: - init: - runs-on: 'ubuntu-latest' - outputs: - directories: '${{ steps.dirs.outputs.directories }}' - steps: - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - id : 'print' - runs: 'echo "hello"' - - name: 'Checkout' - uses: 'actions/checkout@9239842384293848238sfsdf823e234234234sds' # ratchet:actions/checkout@v3 + fsys := os.DirFS("../testdata") + + cases := map[string]string{ + "a.yml": "a.golden.yml", + "b.yml": "b.golden.yml", + "c.yml": "", + "circleci.yml": "", + "cloudbuild.yml": "", + "drone.yml": "", + "github-crazy-indent.yml": "github.yml", + "github-issue-80.yml": "", + "github.yml": "", + "gitlabci.yml": "", + "no-trailing-newline.yml": "no-trailing-newline.golden.yml", + "tekton.yml": "", + } - - name: 'Guardian Directories' - id: 'dirs' - uses: 'abcxyz/guardian/.github/actions/directories@sdfswdf23423423423423sdfsdfsdfsdfdsfsdf2' # ratchet:abcxyz/guardian/.github/actions/directories@main - with: - directories: '${{ inputs.directories }}' -` - yamlD = ` -jobs: - init: - runs-on: 'ubuntu-latest' - outputs: - directories: '${{ steps.dirs.outputs.directories }}' - steps: - - name: 'Checkout' - uses: 'actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab' # ratchet:actions/checkout@v3 + for input, expected := range cases { + inputFilename, expectedFilename := input, expected - - name: 'Guardian Directories' - id: 'dirs' - uses: 'abcxyz/guardian/.github/actions/directories@52a8396df1c40bde244947c887d2c5dfbd36e4ce' # ratchet:abcxyz/guardian/.github/actions/directories@main - with: - directories: '${{ inputs.directories }}' - thing: |- - this is my string - it has many lines + t.Run(inputFilename, func(t *testing.T) { + t.Parallel() - some of them even - have new lines -` - yamlDChanges = ` -jobs: - init: - runs-on: 'ubuntu-latest' - outputs: - directories: '${{ steps.dirs.outputs.directories }}' - steps: - - name: 'Checkout' - uses: 'actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab' # ratchet:actions/checkout@v3 - - name: 'Guardian Directories' - id: 'dirs' - uses: 'abcxyz/guardian/.github/actions/directories@52a8396df1c40bde244947c887d2c5dfbd36e4ce' # ratchet:abcxyz/guardian/.github/actions/directories@main - with: - directories: '${{ inputs.directories }}' - thing: |- - this is my string - it has many lines + files, err := loadYAMLFiles(fsys, []string{inputFilename}) + if err != nil { + t.Fatal(err) + } - some of them even - have new lines -` - yamlDChangesFormatted = ` -jobs: - init: - runs-on: 'ubuntu-latest' - outputs: - directories: '${{ steps.dirs.outputs.directories }}' - steps: - - name: 'Checkout' - uses: 'actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab' # ratchet:actions/checkout@v3 + got, err := files[0].marshalYAML() + if err != nil { + t.Fatal(err) + } - - name: 'Guardian Directories' - id: 'dirs' - uses: 'abcxyz/guardian/.github/actions/directories@52a8396df1c40bde244947c887d2c5dfbd36e4ce' # ratchet:abcxyz/guardian/.github/actions/directories@main - with: - directories: '${{ inputs.directories }}' - thing: |- - this is my string - it has many lines + if expectedFilename == "" { + expectedFilename = inputFilename + } + want, err := fsys.(fs.ReadFileFS).ReadFile(expectedFilename) + if err != nil { + t.Fatal(err) + } - some of them even - have new lines -` -) + if got != string(want) { + t.Errorf("expected\n\n%s\n\nto be\n\n%s\n", got, want) + } + }) + } +} -func Test_removeNewLineChanges(t *testing.T) { +func Test_computeNewlineTargets_simple(t *testing.T) { t.Parallel() cases := []struct { - name string - yamlBefore string - yamlAfter string - want string + name string + before string + after string + want []int }{ { - name: "yamlA_multiple_empty_lines", - yamlBefore: yamlA, - yamlAfter: yamlAChanges, - want: yamlAChangesFormatted, + name: "empty", + before: "", + after: "", + want: []int{}, }, { - name: "yamlB_single_empty_line", - yamlBefore: yamlB, - yamlAfter: yamlBChanges, - want: yamlBChangesFormatted, + name: "single_newline", + before: "\n", + after: "\n", + want: []int{}, }, { - name: "yamlC_long_unchanged_section", - yamlBefore: yamlC, - yamlAfter: yamlCChanges, - want: yamlCChangesFormatted, + name: "leading_whitespace", + before: "\n\nfoo", + after: "foo", + want: []int{0, 1}, }, { - name: "yamlD_multiline_string", - yamlBefore: yamlD, - yamlAfter: yamlDChanges, - want: yamlDChangesFormatted, + name: "trailing_whitespace", + before: "foo\nbar\n\n", + after: "foo\nbar", + want: []int{2, 3}, + }, + { + name: "interior_whitespace", + before: "foo\n\nbar\n\n\nbaz", + after: "foo\nbar\nbaz", + want: []int{1, 3, 4}, + }, + { + name: "interior_whitespace_leading_lines", + before: "foo\n\n bar\n\n\nbaz", + after: "foo\nbar\nbaz", + want: []int{1, 3, 4}, + }, + { + name: "interior_whitespace_tailing_lines", + before: "foo\n\nbar \n\n\nbaz", + after: "foo\nbar\nbaz", + want: []int{1, 3, 4}, }, } @@ -314,158 +119,81 @@ func Test_removeNewLineChanges(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Parallel() - got := removeNewLineChanges(tc.yamlBefore, tc.yamlAfter) - - if !reflect.DeepEqual(got, tc.want) { - t.Errorf("expected %s to be %s", got, tc.want) + got := computeNewlineTargets(tc.before, tc.after) + if diff := cmp.Diff(got, tc.want); diff != "" { + t.Errorf("unexpected diff (+got, -want):\n%s", diff) } }) } } -func Test_loadYAMLFiles(t *testing.T) { +func Test_unmarshalMarshal(t *testing.T) { t.Parallel() cases := []struct { - name string - yamlFilenames []string - format bool - fixNewlines bool - want string + name string + yaml string + want []int }{ { - name: "yamlA_multiple_empty_lines", - yamlFilenames: []string{"testdata/github.yml"}, - format: false, - fixNewlines: false, - want: `jobs: - my_job: - runs-on: 'ubuntu-latest' - container: - image: 'ubuntu:20.04' - services: - nginx: - image: 'nginx:1.21' - steps: - - uses: 'actions/checkout@v3' - - uses: 'docker://ubuntu:20.04' - with: - uses: '/path/to/user.png' - image: '/path/to/image.jpg' - - runs: |- - echo "Hello 😀" - if [ "true" == "false" ]; - echo "NOPE" - fi - other_job: - uses: 'my-org/my-repo/.github/workflows/my-workflow.yml@v0' - final_job: - uses: './local/path/to/action' -`, + name: "single", + yaml: "\nAPPARENTLY_THIS_IS_VALID_YAML\n", + want: []int{0}, }, { - name: "handles-leading-dot-slash", - yamlFilenames: []string{"./testdata/github.yml"}, - format: false, - fixNewlines: false, - want: `jobs: - my_job: - runs-on: 'ubuntu-latest' - container: - image: 'ubuntu:20.04' - services: - nginx: - image: 'nginx:1.21' - steps: - - uses: 'actions/checkout@v3' - - uses: 'docker://ubuntu:20.04' - with: - uses: '/path/to/user.png' - image: '/path/to/image.jpg' - - runs: |- - echo "Hello 😀" - if [ "true" == "false" ]; - echo "NOPE" - fi - other_job: - uses: 'my-org/my-repo/.github/workflows/my-workflow.yml@v0' - final_job: - uses: './local/path/to/action' + name: "multiline", + yaml: `--- +stages: + - build + - test + +build-code-job: + stage: build + image: + name: gcr.io/distroless/static-debian11:nonroot + entrypoint: [""] + script: + - echo "Job 1" + +test-code-job1: + stage: test + image: node:12 + script: + - echo "Job 2" `, + want: []int{3, 11}, }, { - name: "yaml_steps_indent_change", - yamlFilenames: []string{"testdata/github.yml"}, - format: true, - fixNewlines: true, - want: `jobs: - my_job: - runs-on: 'ubuntu-latest' - - container: - image: 'ubuntu:20.04' - - services: - nginx: - image: 'nginx:1.21' - - steps: - - uses: 'actions/checkout@v3' - - - uses: 'docker://ubuntu:20.04' - with: - uses: '/path/to/user.png' - image: '/path/to/image.jpg' - - - runs: |- - echo "Hello 😀" - if [ "true" == "false" ]; - echo "NOPE" - fi - - other_job: - uses: 'my-org/my-repo/.github/workflows/my-workflow.yml@v0' - - final_job: - uses: './local/path/to/action' + name: "folded_block_scalar", + yaml: `this: + is: >- + a multiline + + string that + spans lines + + that: + has: >- + other multline + folded scalars `, + want: []int{6}, }, { - name: "yaml_all_indent_change", - yamlFilenames: []string{"testdata/github-crazy-indent.yml"}, - format: true, - fixNewlines: true, - want: `jobs: - my_job: - runs-on: 'ubuntu-latest' - - container: - image: 'ubuntu:20.04' - - services: - nginx: - image: 'nginx:1.21' - - steps: - - uses: 'actions/checkout@v3' - - - uses: 'docker://ubuntu:20.04' - with: - uses: '/path/to/user.png' - image: '/path/to/image.jpg' - - - runs: |- - echo "Hello 😀" - if [ "true" == "false" ]; - echo "NOPE" - fi - - other_job: - uses: 'my-org/my-repo/.github/workflows/my-workflow.yml@v0' - - final_job: - uses: './local/path/to/action' + name: "literal_block_scalar", + yaml: `this: + is: |- + a multiline + + string that + spans lines + + that: + has: |- + other multline + literal scalars `, + want: []int{6}, }, } @@ -475,22 +203,28 @@ func Test_loadYAMLFiles(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Parallel() - files, err := loadYAMLFiles(os.DirFS(".."), tc.yamlFilenames, tc.format) - if err != nil { - t.Fatalf("loadYAMLFiles() returned error: %s", err) + fsys := fstest.MapFS{ + "file.yml": &fstest.MapFile{ + Data: []byte(tc.yaml), + }, } - b, err := marshalYAML(files[0].node) + r, err := loadYAMLFiles(fsys, []string{"file.yml"}) if err != nil { - t.Fatalf("marshalYAML() returned error: %s", err) + t.Fatal(err) } - got := string(b) - if tc.fixNewlines { - got = removeNewLineChanges(string(files[0].contents), got) + + f := r[0] + if diff := cmp.Diff(f.newlines, tc.want); diff != "" { + t.Errorf("unexpected newlines diff (+got, -want):\n%s", diff) } - if diff := cmp.Diff(tc.want, got); diff != "" { - t.Errorf("returned diff (-want, +got):\n%s", diff) + s, err := f.marshalYAML() + if err != nil { + t.Fatal(err) + } + if diff := cmp.Diff(s, tc.yaml); diff != "" { + t.Errorf("unexpected render diff (+got, -want):\n%s", diff) } }) } diff --git a/command/pin.go b/command/pin.go index de9b97cc84..41735f4499 100644 --- a/command/pin.go +++ b/command/pin.go @@ -80,7 +80,7 @@ func (c *PinCommand) Run(ctx context.Context, originalArgs []string) error { fsys := os.DirFS(".") - files, err := loadYAMLFiles(fsys, args, true) + files, err := loadYAMLFiles(fsys, args) if err != nil { return err } @@ -102,12 +102,11 @@ func (c *PinCommand) Run(ctx context.Context, originalArgs []string) error { outFile = f.path } - updated, err := marshalYAML(f.node) + final, err := f.marshalYAML() if err != nil { return fmt.Errorf("failed to marshal yaml for %s: %w", f.path, err) } - final := removeNewLineChanges(string(f.contents), string(updated)) if err := atomic.Write(f.path, outFile, strings.NewReader(final)); err != nil { return fmt.Errorf("failed to save file %s: %w", outFile, err) } diff --git a/command/unpin.go b/command/unpin.go index b007dfd3ee..6f620bc217 100644 --- a/command/unpin.go +++ b/command/unpin.go @@ -64,7 +64,7 @@ func (c *UnpinCommand) Run(ctx context.Context, originalArgs []string) error { fsys := os.DirFS(".") - files, err := loadYAMLFiles(fsys, args, true) + files, err := loadYAMLFiles(fsys, args) if err != nil { return err } @@ -86,12 +86,11 @@ func (c *UnpinCommand) Run(ctx context.Context, originalArgs []string) error { outFile = f.path } - updated, err := marshalYAML(f.node) + final, err := f.marshalYAML() if err != nil { return fmt.Errorf("failed to marshal yaml for %s: %w", f.path, err) } - final := removeNewLineChanges(string(f.contents), string(updated)) if err := atomic.Write(f.path, outFile, strings.NewReader(final)); err != nil { return fmt.Errorf("failed to save file %s: %w", outFile, err) } diff --git a/command/update.go b/command/update.go index e9f3a9060d..002682c875 100644 --- a/command/update.go +++ b/command/update.go @@ -69,7 +69,7 @@ func (c *UpdateCommand) Run(ctx context.Context, originalArgs []string) error { fsys := os.DirFS(".") - files, err := loadYAMLFiles(fsys, args, true) + files, err := loadYAMLFiles(fsys, args) if err != nil { return err } @@ -95,12 +95,11 @@ func (c *UpdateCommand) Run(ctx context.Context, originalArgs []string) error { outFile = f.path } - updated, err := marshalYAML(f.node) + final, err := f.marshalYAML() if err != nil { return fmt.Errorf("failed to marshal yaml for %s: %w", f.path, err) } - final := removeNewLineChanges(string(f.contents), string(updated)) if err := atomic.Write(f.path, outFile, strings.NewReader(final)); err != nil { return fmt.Errorf("failed to save file %s: %w", outFile, err) } diff --git a/command/upgrade.go b/command/upgrade.go index edf308d6a0..17b47dbd27 100644 --- a/command/upgrade.go +++ b/command/upgrade.go @@ -77,7 +77,7 @@ func (c *UpgradeCommand) Run(ctx context.Context, originalArgs []string) error { fsys := os.DirFS(".") - files, err := loadYAMLFiles(fsys, args, true) + files, err := loadYAMLFiles(fsys, args) if err != nil { return err } @@ -107,12 +107,11 @@ func (c *UpgradeCommand) Run(ctx context.Context, originalArgs []string) error { outFile = f.path } - upgraded, err := marshalYAML(f.node) + final, err := f.marshalYAML() if err != nil { return fmt.Errorf("failed to marshal yaml for %s: %w", f.path, err) } - final := removeNewLineChanges(string(f.contents), string(upgraded)) if err := atomic.Write(f.path, outFile, strings.NewReader(final)); err != nil { return fmt.Errorf("failed to save file %s: %w", outFile, err) } diff --git a/go.mod b/go.mod index 43a5fcbb20..9e4aa0f0e3 100644 --- a/go.mod +++ b/go.mod @@ -1,34 +1,32 @@ module github.com/sethvargo/ratchet -go 1.21 +go 1.22 + +toolchain go1.22.2 require ( github.com/braydonk/yaml v0.7.0 github.com/google/go-cmp v0.6.0 - github.com/google/go-containerregistry v0.19.0 + github.com/google/go-containerregistry v0.19.1 github.com/google/go-github/v58 v58.0.0 - github.com/hexops/gotextdiff v1.0.3 - golang.org/x/oauth2 v0.16.0 - golang.org/x/sync v0.6.0 + golang.org/x/oauth2 v0.19.0 + golang.org/x/sync v0.7.0 ) require ( github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect - github.com/docker/cli v25.0.2+incompatible // indirect + github.com/docker/cli v26.0.2+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect - github.com/docker/docker v25.0.5+incompatible // indirect + github.com/docker/docker v26.0.2+incompatible // indirect github.com/docker/docker-credential-helpers v0.8.1 // indirect - github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-querystring v1.1.0 // indirect - github.com/klauspost/compress v1.17.5 // indirect + github.com/klauspost/compress v1.17.8 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc6 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/vbatts/tar-split v0.11.5 // indirect - golang.org/x/sys v0.16.0 // indirect - google.golang.org/appengine v1.6.8 // indirect - google.golang.org/protobuf v1.33.0 // indirect + golang.org/x/sys v0.19.0 // indirect ) diff --git a/go.sum b/go.sum index d0281f1492..d5d4843e2b 100644 --- a/go.sum +++ b/go.sum @@ -6,32 +6,25 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docker/cli v25.0.2+incompatible h1:6GEdvxwEA451/+Y3GtqIGn/MNjujQazUlxC6uGu8Tog= -github.com/docker/cli v25.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v26.0.2+incompatible h1:4C4U8ZqrlNDe/R1U1zFFX+YsCFiVUicJqo4WVdInJas= +github.com/docker/cli v26.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v25.0.5+incompatible h1:UmQydMduGkrD5nQde1mecF/YnSbTOaPeFIeP5C4W+DE= -github.com/docker/docker v25.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v26.0.2+incompatible h1:yGVmKUFGgcxA6PXWAokO0sQL22BrQ67cgVjko8tGdXE= +github.com/docker/docker v26.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo= github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.19.0 h1:uIsMRBV7m/HDkDxE/nXMnv1q+lOOSPlQ/ywc5JbB8Ic= -github.com/google/go-containerregistry v0.19.0/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ= +github.com/google/go-containerregistry v0.19.1 h1:yMQ62Al6/V0Z7CqIrrS1iYoA5/oQCm88DeNujc7C1KY= +github.com/google/go-containerregistry v0.19.1/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI= github.com/google/go-github/v58 v58.0.0 h1:Una7GGERlF/37XfkPwpzYJe0Vp4dt2k1kCjlxwjIvzw= github.com/google/go-github/v58 v58.0.0/go.mod h1:k4hxDKEfoWpSqFlc8LTpGd9fu2KrV1YAa6Hi6FmDNY4= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= -github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= -github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= -github.com/klauspost/compress v1.17.5 h1:d4vBd+7CHydUqpFBgUEKkSdtSugf9YFmSkvUYPquI5E= -github.com/klauspost/compress v1.17.5/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -40,8 +33,8 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc6 h1:XDqvyKsJEbRtATzkgItUqBA7QHk58yxX1Ov9HERHNqU= -github.com/opencontainers/image-spec v1.1.0-rc6/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -56,44 +49,14 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= -golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg= +golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/testdata/a.golden.yml b/testdata/a.golden.yml new file mode 100644 index 0000000000..8f785a8163 --- /dev/null +++ b/testdata/a.golden.yml @@ -0,0 +1,16 @@ +jobs: + init: + runs-on: 'ubuntu-latest' + outputs: + directories: '${{ steps.dirs.outputs.directories }}' + + steps: + - uses: 'actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab' # ratchet:actions/checkout@v3 + + - uses: 'actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab' # ratchet:actions/checkout@v3 + + - name: 'Guardian Directories' + id: 'dirs' + uses: 'abcxyz/guardian/.github/actions/directories@52a8396df1c40bde244947c887d2c5dfbd36e4ce' # ratchet:abcxyz/guardian/.github/actions/directories@main + with: + directories: '${{ inputs.directories }}' diff --git a/testdata/a.yml b/testdata/a.yml new file mode 100644 index 0000000000..1a6451ac27 --- /dev/null +++ b/testdata/a.yml @@ -0,0 +1,16 @@ +jobs: + init: + runs-on: 'ubuntu-latest' + outputs: + directories: '${{ steps.dirs.outputs.directories }}' + + steps: + - uses: 'actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab' # ratchet:actions/checkout@v3 + + - uses: 'actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab' # ratchet:actions/checkout@v3 + + - name: 'Guardian Directories' + id: 'dirs' + uses: 'abcxyz/guardian/.github/actions/directories@52a8396df1c40bde244947c887d2c5dfbd36e4ce' # ratchet:abcxyz/guardian/.github/actions/directories@main + with: + directories: '${{ inputs.directories }}' diff --git a/testdata/b.golden.yml b/testdata/b.golden.yml new file mode 100644 index 0000000000..2d9dc4281d --- /dev/null +++ b/testdata/b.golden.yml @@ -0,0 +1,33 @@ +jobs: + init: + runs-on: 'ubuntu-latest' + outputs: + directories: '${{ steps.dirs.outputs.directories }}' + steps: + - id: 'print' + runs: 'echo "hello"' + - id: 'print' + runs: 'echo "hello"' + - id: 'print' + runs: 'echo "hello"' + - id: 'print' + runs: 'echo "hello"' + + - id: 'print' + runs: 'echo "hello"' + - id: 'print' + runs: 'echo "hello"' + - id: 'print' + runs: 'echo "hello"' + - id: 'print' + runs: 'echo "hello"' + - id: 'print' + runs: 'echo "hello"' + - name: 'Checkout' + uses: 'actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab' # ratchet:actions/checkout@v3 + + - name: 'Guardian Directories' + id: 'dirs' + uses: 'abcxyz/guardian/.github/actions/directories@52a8396df1c40bde244947c887d2c5dfbd36e4ce' # ratchet:abcxyz/guardian/.github/actions/directories@main + with: + directories: '${{ inputs.directories }}' diff --git a/testdata/b.yml b/testdata/b.yml new file mode 100644 index 0000000000..c05854d487 --- /dev/null +++ b/testdata/b.yml @@ -0,0 +1,33 @@ +jobs: + init: + runs-on: 'ubuntu-latest' + outputs: + directories: '${{ steps.dirs.outputs.directories }}' + steps: + - id : 'print' + runs: 'echo "hello"' + - id : 'print' + runs: 'echo "hello"' + - id : 'print' + runs: 'echo "hello"' + - id : 'print' + runs: 'echo "hello"' + + - id : 'print' + runs: 'echo "hello"' + - id : 'print' + runs: 'echo "hello"' + - id : 'print' + runs: 'echo "hello"' + - id : 'print' + runs: 'echo "hello"' + - id : 'print' + runs: 'echo "hello"' + - name: 'Checkout' + uses: 'actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab' # ratchet:actions/checkout@v3 + + - name: 'Guardian Directories' + id: 'dirs' + uses: 'abcxyz/guardian/.github/actions/directories@52a8396df1c40bde244947c887d2c5dfbd36e4ce' # ratchet:abcxyz/guardian/.github/actions/directories@main + with: + directories: '${{ inputs.directories }}' diff --git a/testdata/c.golden.yml b/testdata/c.golden.yml new file mode 100644 index 0000000000..cccd1da9dc --- /dev/null +++ b/testdata/c.golden.yml @@ -0,0 +1,21 @@ +jobs: + init: + runs-on: 'ubuntu-latest' + outputs: + directories: '${{ steps.dirs.outputs.directories }}' + + steps: + - name: 'Checkout' + uses: 'actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab' # ratchet:actions/checkout@v3 + + - name: 'Guardian Directories' + id: 'dirs' + uses: 'abcxyz/guardian/.github/actions/directories@52a8396df1c40bde244947c887d2c5dfbd36e4ce' # ratchet:abcxyz/guardian/.github/actions/directories@main + with: + directories: '${{ inputs.directories }}' + thing: |- + this is my string + it has many lines + + some of them even + have new lines diff --git a/testdata/c.yml b/testdata/c.yml new file mode 100644 index 0000000000..5ac87d84f3 --- /dev/null +++ b/testdata/c.yml @@ -0,0 +1,26 @@ + + + +jobs: + init: + runs-on: 'ubuntu-latest' + outputs: + directories: '${{ steps.dirs.outputs.directories }}' + + steps: + - name: 'Checkout' + uses: 'actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab' # ratchet:actions/checkout@v3 + + - name: 'Guardian Directories' + id: 'dirs' + uses: 'abcxyz/guardian/.github/actions/directories@52a8396df1c40bde244947c887d2c5dfbd36e4ce' # ratchet:abcxyz/guardian/.github/actions/directories@main + with: + directories: '${{ inputs.directories }}' + thing: |- + this is my string + it has many lines + + some of them even + have new lines + + diff --git a/testdata/cloudbuild.yml b/testdata/cloudbuild.yml index 347ad98483..2554d0b4fb 100644 --- a/testdata/cloudbuild.yml +++ b/testdata/cloudbuild.yml @@ -1,4 +1,4 @@ steps: -- name: 'ubuntu:20.04' - args: - - 'name: foo' + - name: 'ubuntu:20.04' + args: + - 'name: foo' diff --git a/testdata/github-issue-80.yml b/testdata/github-issue-80.yml new file mode 100644 index 0000000000..7b3e9145dc --- /dev/null +++ b/testdata/github-issue-80.yml @@ -0,0 +1,46 @@ +--- +name: mega-linter + +on: + workflow_dispatch: + push: + branches-ignore: + - main + +permissions: read-all + +jobs: + mega-linter: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout Code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Restore lychee cache + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + with: + path: .lycheecache + key: cache-lychee-${{ github.sha }} + restore-keys: cache-lychee- + + - name: Extract commands from markdown files + run: | + set -euxo pipefail + echo '#!/usr/bin/env bash' > README.sh + find . -name '*.md' -print0 | while IFS= read -r -d '' FILE; do + # Extract: ... + sed -n "/^\`\`\`\(bash\|shell\)$/,/^\`\`\`$/p" "${FILE}" | sed '/^```*/d' >> README.sh + # Extract: ```bash ... ``` + sed -n "/^ \`\`\`\(bash\|shell\)$/,/^ \`\`\`$/p" "${FILE}" | sed '/^ ```*/d; s/^ //' >> README.sh + done + ls -la README.sh + chmod a+x README.sh + + - name: 💡 MegaLinter + uses: oxsecurity/megalinter@a7a0163b6c8ff7474a283d99a706e27483ddd80f # v7.10.0 + env: + GITHUB_COMMENT_REPORTER: false + # Disabled due to error: [GitHub Status Reporter] Error posting Status for REPOSITORY with ...: 403 + GITHUB_STATUS_REPORTER: false + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/testdata/github.yml b/testdata/github.yml index 2819213e5f..9bdb8dee54 100644 --- a/testdata/github.yml +++ b/testdata/github.yml @@ -10,18 +10,18 @@ jobs: image: 'nginx:1.21' steps: - - uses: 'actions/checkout@v3' + - uses: 'actions/checkout@v3' - - uses: 'docker://ubuntu:20.04' - with: - uses: '/path/to/user.png' - image: '/path/to/image.jpg' + - uses: 'docker://ubuntu:20.04' + with: + uses: '/path/to/user.png' + image: '/path/to/image.jpg' - - runs: |- - echo "Hello 😀" - if [ "true" == "false" ]; - echo "NOPE" - fi + - runs: |- + echo "Hello 😀" + if [ "true" == "false" ]; + echo "NOPE" + fi other_job: uses: 'my-org/my-repo/.github/workflows/my-workflow.yml@v0' diff --git a/testdata/no-trailing-newline.golden.yml b/testdata/no-trailing-newline.golden.yml new file mode 100644 index 0000000000..07f7d83e6b --- /dev/null +++ b/testdata/no-trailing-newline.golden.yml @@ -0,0 +1 @@ +job: 'my-job' diff --git a/testdata/no-trailing-newline.yml b/testdata/no-trailing-newline.yml new file mode 100644 index 0000000000..c1bce0c679 --- /dev/null +++ b/testdata/no-trailing-newline.yml @@ -0,0 +1 @@ +job: 'my-job' \ No newline at end of file diff --git a/testdata/tekton.yml b/testdata/tekton.yml index 5d8664c180..689aab9deb 100644 --- a/testdata/tekton.yml +++ b/testdata/tekton.yml @@ -8,4 +8,4 @@ spec: type: string steps: - name: build - image: golang:1.12 \ No newline at end of file + image: golang:1.12