Skip to content

Commit

Permalink
Merge pull request #54 from getporter/stubLint
Browse files Browse the repository at this point in the history
Stub lint command
  • Loading branch information
kichristensen authored Oct 1, 2024
2 parents a81830c + a9024a0 commit 710f292
Show file tree
Hide file tree
Showing 11 changed files with 181 additions and 10 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/skeletor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
with:
fetch-depth: 0
- name: Install Go
uses: actions/checkout@v4
uses: actions/setup-go@v4
with:
go-version-file: go.mod
cache: true
Expand Down
17 changes: 17 additions & 0 deletions cmd/skeletor/lint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package main

import (
"github.com/getporter/skeletor/pkg/skeletor"
"github.com/spf13/cobra"
)

func buildLintCommand(m *skeletor.Mixin) *cobra.Command {
cmd := &cobra.Command{
Use: "lint",
Short: "Execute the lint functionality of this mixin",
RunE: func(cmd *cobra.Command, args []string) error {
return m.PrintLintResults(cmd.Context())
},
}
return cmd
}
1 change: 1 addition & 0 deletions cmd/skeletor/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ func buildRootCommand(m *skeletor.Mixin, in io.Reader) *cobra.Command {
cmd.AddCommand(buildInvokeCommand(m))
cmd.AddCommand(buildUpgradeCommand(m))
cmd.AddCommand(buildUninstallCommand(m))
cmd.AddCommand(buildLintCommand(m))

return cmd
}
4 changes: 2 additions & 2 deletions pkg/skeletor/action_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package skeletor

import (
"io/ioutil"
"os"
"testing"

"get.porter.sh/porter/pkg/exec/builder"
Expand All @@ -12,7 +12,7 @@ import (
)

func TestMixin_UnmarshalStep(t *testing.T) {
b, err := ioutil.ReadFile("testdata/step-input.yaml")
b, err := os.ReadFile("testdata/step-input.yaml")
require.NoError(t, err)

var action Action
Expand Down
5 changes: 3 additions & 2 deletions pkg/skeletor/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import (
"gopkg.in/yaml.v2"
)

// BuildInput represents stdin passed to the mixin for the build command.
// BuildInput represents stdin passed to the mixin for the build and lint commands.
type BuildInput struct {
Config MixinConfig
Config MixinConfig
Actions Actions `yaml:"actions"`
}

// MixinConfig represents configuration that can be set on the skeletor mixin in porter.yaml
Expand Down
3 changes: 1 addition & 2 deletions pkg/skeletor/execute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package skeletor
import (
"bytes"
"context"
"io/ioutil"
"os"
"path"
"testing"
Expand Down Expand Up @@ -36,7 +35,7 @@ func TestMixin_Execute(t *testing.T) {
m := NewTestMixin(t)

m.Setenv(test.ExpectedCommandEnv, tc.wantCommand)
mixinInputB, err := ioutil.ReadFile(tc.file)
mixinInputB, err := os.ReadFile(tc.file)
require.NoError(t, err)

m.In = bytes.NewBuffer(mixinInputB)
Expand Down
75 changes: 75 additions & 0 deletions pkg/skeletor/lint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package skeletor

import (
"context"
"fmt"

"get.porter.sh/porter/pkg/encoding"
"get.porter.sh/porter/pkg/exec/builder"
"get.porter.sh/porter/pkg/linter"

"gopkg.in/yaml.v2"
)

const mixinName = "skeletor"

const (
// CodeInvalidName is the linter code for when the name of the step is invalid.
CodeInvalidName linter.Code = "skeletor-100"
)

func (m *Mixin) Lint(ctx context.Context) (linter.Results, error) {
var input BuildInput
err := builder.LoadAction(ctx, m.RuntimeConfig, "", func(contents []byte) (interface{}, error) {
err := yaml.Unmarshal(contents, &input)
return &input, err
})
if err != nil {
return nil, err
}

results := make(linter.Results, 0)

for _, action := range input.Actions {
for stepNumber, step := range action.Steps {
// TODO: Replace with your own linting logic
if step.Name != "invalid" {
continue
}

result := linter.Result{
Level: linter.LevelError,
Code: CodeInvalidName,
Location: linter.Location{
Action: action.Name,
Mixin: mixinName,
StepNumber: stepNumber + 1, // We index from 1 for natural counting, 1st, 2nd, etc.
StepDescription: step.Description,
},
Title: "Invalid name",
Message: "The name cannot be 'invalid'",
URL: "",
}
results = append(results, result)
}
}
return results, nil
}

func (m *Mixin) PrintLintResults(ctx context.Context) error {
results, err := m.Lint(ctx)
if err != nil {
return err
}

b, err := encoding.MarshalJson(results)
if err != nil {
return fmt.Errorf("could not marshal lint results %#v: %w", results, err)
}

// Print the results as json to stdout for Porter to read
resultsJson := string(b)
fmt.Fprintln(m.Config.Out, resultsJson)

return nil
}
55 changes: 55 additions & 0 deletions pkg/skeletor/lint_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package skeletor

import (
"bytes"
"context"
"os"
"testing"

"get.porter.sh/porter/pkg/linter"

"github.com/stretchr/testify/require"
)

func TestMixin_Lint(t *testing.T) {
testcases := []struct {
name string // Test case name
file string // Path to the test input yaml
wantResults linter.Results // Indicates the wanted lint result
}{
{"valid file", "testdata/actions-input.yaml", nil},
{"invalid name", "testdata/actions-input-fail-lint.yaml", linter.Results{
linter.Result{
Level: linter.LevelError,
Location: linter.Location{
Action: "install",
Mixin: "skeletor",
StepNumber: 1,
StepDescription: "Summon Minion",
},
Code: CodeInvalidName,
Title: "Invalid name",
Message: "The name cannot be 'invalid'",
},
}},
}

for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
ctx := context.Background()
m := NewTestMixin(t)
mixinInputB, err := os.ReadFile(tc.file)
require.NoError(t, err)

m.In = bytes.NewBuffer(mixinInputB)

results, err := m.Lint(ctx)
require.NoError(t, err, "lint failed")

require.Len(t, results, len(tc.wantResults))
for _, wantResult := range tc.wantResults {
require.Contains(t, results, wantResult)
}
})
}
}
6 changes: 3 additions & 3 deletions pkg/skeletor/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package skeletor

import (
"fmt"
"io/ioutil"
"os"
"testing"

"github.com/ghodss/yaml" // We are not using go-yaml because of serialization problems with jsonschema, don't use this library elsewhere
Expand All @@ -17,7 +17,7 @@ func TestMixin_PrintSchema(t *testing.T) {
m.PrintSchema()
gotSchema := m.TestContext.GetOutput()

wantSchema, err := ioutil.ReadFile("schema/schema.json")
wantSchema, err := os.ReadFile("schema/schema.json")
require.NoError(t, err)

assert.Equal(t, string(wantSchema), gotSchema)
Expand All @@ -41,7 +41,7 @@ func TestMixin_ValidateSchema(t *testing.T) {
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
// Read the mixin input as a go dump
mixinInputB, err := ioutil.ReadFile(tc.file)
mixinInputB, err := os.ReadFile(tc.file)
require.NoError(t, err)
mixinInputMap := make(map[string]interface{})
err = yaml.Unmarshal(mixinInputB, &mixinInputMap)
Expand Down
12 changes: 12 additions & 0 deletions pkg/skeletor/testdata/actions-input-fail-lint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
actions:
install:
- skeletor:
name: "invalid"
description: "Summon Minion"
arguments:
- "man-e-faces"
flags:
species: "human"
outputs:
- name: "VICTORY"
jsonPath: "$Id"
11 changes: 11 additions & 0 deletions pkg/skeletor/testdata/actions-input.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
actions:
install:
- skeletor:
description: "Summon Minion"
arguments:
- "man-e-faces"
flags:
species: "human"
outputs:
- name: "VICTORY"
jsonPath: "$Id"

0 comments on commit 710f292

Please sign in to comment.