Merge pull request #1 from blocklayerhq/ci-linter

Fix Go & Cue lint errors, enable CI
This commit is contained in:
Andrea Luzzardi 2021-01-08 17:21:14 +01:00 committed by GitHub
commit 630132fa73
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 123 additions and 104 deletions

34
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,34 @@
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.14.2
uses: actions/setup-go@v1
with:
go-version: 1.14.2
id: go
- name: Insatall Dependencies
run: |
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sudo sh -s -- -b /usr/local/bin v1.23.8
curl -L https://github.com/cuelang/cue/releases/download/v0.3.0-alpha6/cue_0.3.0-alpha6_Linux_x86_64.tar.gz | sudo tar zxf - -C /usr/local/bin
- name: Check out
uses: actions/checkout@v2
- name: Build
run: |
make
- name: Lint
run: |
make lint

34
.golangci.yml Normal file
View File

@ -0,0 +1,34 @@
linters:
disable-all: true
timeout: 30m
enable:
- bodyclose
- deadcode
- depguard
- dogsled
- dupl
- goconst
- gocritic
- gocyclo
- gofmt
- goimports
- golint
- goprintffuncname
- gosec
- gosimple
- govet
- ineffassign
- misspell
- nakedret
- prealloc
- rowserrcheck
- scopelint
- staticcheck
- structcheck
- stylecheck
- typecheck
- unconvert
- unparam
- unused
- varcheck
- whitespace

View File

@ -1,3 +1,19 @@
.PHONY: all
all: dagger
.PHONY: generate
generate:
go generate ./dagger
.PHONY: dagger .PHONY: dagger
dagger: dagger: generate
go generate ./dagger && go build -o ./cmd/dagger/ ./cmd/dagger/ go build -o ./cmd/dagger/ ./cmd/dagger/
.PHONY: cuefmt
cuefmt:
(cd ./dagger && cue fmt -s ./... && cue trim -s ./...)
.PHONY: lint
lint:
golangci-lint run
@test -z "$$(git status -s . | grep -e "^ M" | grep .cue | cut -d ' ' -f3 | tee /dev/stderr)"

View File

@ -1,14 +0,0 @@
package main
import (
"dagger.cloud/go/dagger"
"github.com/moby/buildkit/frontend/gateway/grpcclient"
"github.com/moby/buildkit/util/appcontext"
)
func main() {
r := &dagger.Runtime{}
if err := grpcclient.RunFromEnvironment(appcontext.Context(), r.BKFrontend); err != nil {
panic(err)
}
}

View File

@ -17,7 +17,7 @@ import (
// buildkit // buildkit
bk "github.com/moby/buildkit/client" bk "github.com/moby/buildkit/client"
_ "github.com/moby/buildkit/client/connhelper/dockercontainer" _ "github.com/moby/buildkit/client/connhelper/dockercontainer" // import the container connection driver
// docker output // docker output
"github.com/containerd/console" "github.com/containerd/console"
@ -188,7 +188,7 @@ func (c *Client) buildfn(ctx context.Context, ch chan *bk.SolveStatus, w io.Writ
} }
// Read tar export stream from buildkit Build(), and extract cue output // Read tar export stream from buildkit Build(), and extract cue output
func (c *Client) outputfn(ctx context.Context, r io.Reader, out *Value) func() error { func (c *Client) outputfn(_ context.Context, r io.Reader, out *Value) func() error {
return func() error { return func() error {
defer debugf("outputfn complete") defer debugf("outputfn complete")
tr := tar.NewReader(r) tr := tar.NewReader(r)
@ -230,7 +230,7 @@ type Node struct {
} }
func (n Node) ComponentPath() cue.Path { func (n Node) ComponentPath() cue.Path {
var parts []cue.Selector parts := []cue.Selector{}
for _, sel := range n.Path.Selectors() { for _, sel := range n.Path.Selectors() {
if strings.HasPrefix(sel.String(), "#") { if strings.HasPrefix(sel.String(), "#") {
break break
@ -326,7 +326,6 @@ func (c *Client) printfn(ctx context.Context, ch, ch2 chan *bk.SolveStatus) func
// see proto 67 // see proto 67
} }
} }
return nil
} }
} }

View File

@ -14,10 +14,7 @@ func (c *Component) Value() *Value {
func (c *Component) Exists() bool { func (c *Component) Exists() bool {
// Does #dagger exist? // Does #dagger exist?
if c.Config().Err() != nil { return c.Config().Err() == nil
return false
}
return true
} }
// Return the contents of the "#dagger" annotation. // Return the contents of the "#dagger" annotation.

View File

@ -32,7 +32,7 @@ func TestValidateSimpleComponent(t *testing.T) {
} }
n := 0 n := 0
if err := s.Walk(func(op *Op) error { if err := s.Walk(func(op *Op) error {
n += 1 n++
return nil return nil
}); err != nil { }); err != nil {
t.Fatal(err) t.Fatal(err)

View File

@ -138,7 +138,7 @@ func (op *Op) Local(ctx context.Context, fs FS, out Fillable) (FS, error) {
} }
func (op *Op) Exec(ctx context.Context, fs FS, out Fillable) (FS, error) { func (op *Op) Exec(ctx context.Context, fs FS, out Fillable) (FS, error) {
var opts []llb.RunOption opts := []llb.RunOption{}
var cmd struct { var cmd struct {
Args []string Args []string
Env map[string]string Env map[string]string
@ -151,11 +151,6 @@ func (op *Op) Exec(ctx context.Context, fs FS, out Fillable) (FS, error) {
opts = append(opts, llb.WithCustomName(op.v.Path().String())) opts = append(opts, llb.WithCustomName(op.v.Path().String()))
// args // args
opts = append(opts, llb.Args(cmd.Args)) opts = append(opts, llb.Args(cmd.Args))
// dir
dir := cmd.Dir
if dir == "" {
dir = "/"
}
// env // env
for k, v := range cmd.Env { for k, v := range cmd.Env {
opts = append(opts, llb.AddEnv(k, v)) opts = append(opts, llb.AddEnv(k, v))

View File

@ -17,7 +17,7 @@ func TestLocalMatch(t *testing.T) {
} }
n := 0 n := 0
err = op.Walk(func(op *Op) error { err = op.Walk(func(op *Op) error {
n += 1 n++
return nil return nil
}) })
if err != nil { if err != nil {
@ -44,7 +44,7 @@ func TestCopyMatch(t *testing.T) {
} }
n := 0 n := 0
err = op.Walk(func(op *Op) error { err = op.Walk(func(op *Op) error {
n += 1 n++
return nil return nil
}) })
if err != nil { if err != nil {

View File

@ -18,7 +18,7 @@ func TestLocalScript(t *testing.T) {
} }
n := 0 n := 0
err = s.Walk(func(op *Op) error { err = s.Walk(func(op *Op) error {
n += 1 n++
return nil return nil
}) })
if err != nil { if err != nil {

View File

@ -10,14 +10,14 @@ package dagger
// The DAG architecture has many benefits: // The DAG architecture has many benefits:
// - Because DAGs are made of nodes executing in parallel, they are easy to scale. // - Because DAGs are made of nodes executing in parallel, they are easy to scale.
// - Because all inputs and outputs are snapshotted and content-addressed, DAGs // - Because all inputs and outputs are snapshotted and content-addressed, DAGs
// can easily be made repeatable, can be cached aggressively, and can be replayed // can easily be made repeatable, can be cached aggressively, and can be replayed
// at will. // at will.
// - Because nodes are executed by the same container engine as docker-build, DAGs // - Because nodes are executed by the same container engine as docker-build, DAGs
// can be developed using any language or technology capable of running in a docker. // can be developed using any language or technology capable of running in a docker.
// Dockerfiles and docker images are natively supported for maximum compatibility. // Dockerfiles and docker images are natively supported for maximum compatibility.
// //
// - Because DAGs are programmed declaratively with a powerful configuration language, // - Because DAGs are programmed declaratively with a powerful configuration language,
// they are much easier to test, debug and refactor than traditional programming languages. // they are much easier to test, debug and refactor than traditional programming languages.
// //
// To execute a DAG, the dagger runtime JIT-compiles it to a low-level format called // To execute a DAG, the dagger runtime JIT-compiles it to a low-level format called
// llb, and executes it with buildkit. // llb, and executes it with buildkit.
@ -42,11 +42,9 @@ package dagger
// The contents of a #dagger annotation // The contents of a #dagger annotation
#ComponentConfig: { #ComponentConfig: {
// script to compute the value // script to compute the value
compute?: #Script compute?: #Script
} }
// Any component can be referenced as a directory, since // Any component can be referenced as a directory, since
// every dagger script outputs a filesystem state (aka a directory) // every dagger script outputs a filesystem state (aka a directory)
#Dir: #Component #Dir: #Component
@ -61,19 +59,19 @@ package dagger
do: "export" do: "export"
// Source path in the container // Source path in the container
source: string source: string
format: "json"|"yaml"|*"string"|"number"|"boolean" format: "json" | "yaml" | *"string" | "number" | "boolean"
} }
#Local: { #Local: {
do: "local" do: "local"
dir: string dir: string
include?: [...string] | *[] include?: [...string] | *[]
} }
// FIXME: bring back load (more efficient than copy) // FIXME: bring back load (more efficient than copy)
#Load: { #Load: {
do: "load" do: "load"
from: #Component | #Script from: #Component | #Script
} }
@ -82,40 +80,40 @@ package dagger
args: [...string] args: [...string]
env?: [string]: string env?: [string]: string
always?: true | *false always?: true | *false
dir: string | *"/" dir: string | *"/"
mount?: [string]: #MountTmp | #MountCache | #MountComponent | #MountScript mount?: [string]: #MountTmp | #MountCache | #MountComponent | #MountScript
} }
#MountTmp: "tmpfs" #MountTmp: "tmpfs"
#MountCache: "cache" #MountCache: "cache"
#MountComponent: { #MountComponent: {
input: #Component input: #Component
path: string | *"/" path: string | *"/"
} }
#MountScript: { #MountScript: {
input: #Script input: #Script
path: string | *"/" path: string | *"/"
} }
#FetchContainer: { #FetchContainer: {
do: "fetch-container" do: "fetch-container"
ref: string ref: string
} }
#FetchGit: { #FetchGit: {
do: "fetch-git" do: "fetch-git"
remote: string remote: string
ref: string ref: string
} }
#Copy: { #Copy: {
do: "copy" do: "copy"
from: #Script | #Component from: #Script | #Component
src?: string | *"/" src?: string | *"/"
dest?: string | *"/" dest?: string | *"/"
} }
#TestScript: #Script & [ #TestScript: #Script & [
{ do: "fetch-container", ref: "alpine:latest" }, {do: "fetch-container", ref: "alpine:latest"},
{ do: "exec", args: ["echo", "hello", "world" ] } {do: "exec", args: ["echo", "hello", "world"]},
] ]

View File

@ -81,7 +81,6 @@ func testMatch(t *testing.T, src interface{}, def string) {
t.Errorf("false positive: %s: %q", cmpDef, src) t.Errorf("false positive: %s: %q", cmpDef, src)
} }
} }
return
} }
func compile(t *testing.T, cc *Compiler, src interface{}) *Value { func compile(t *testing.T, cc *Compiler, src interface{}) *Value {

View File

@ -8,7 +8,7 @@ import (
func Fatalf(msg string, args ...interface{}) { func Fatalf(msg string, args ...interface{}) {
if !strings.HasSuffix(msg, "\n") { if !strings.HasSuffix(msg, "\n") {
msg = msg + "\n" msg += "\n"
} }
fmt.Fprintf(os.Stderr, msg, args...) fmt.Fprintf(os.Stderr, msg, args...)
os.Exit(1) os.Exit(1)
@ -20,7 +20,7 @@ func Fatal(msg interface{}) {
func Info(msg string, args ...interface{}) { func Info(msg string, args ...interface{}) {
if !strings.HasSuffix(msg, "\n") { if !strings.HasSuffix(msg, "\n") {
msg = msg + "\n" msg += "\n"
} }
fmt.Fprintf(os.Stderr, "[info] "+msg, args...) fmt.Fprintf(os.Stderr, "[info] "+msg, args...)
} }

View File

@ -2,53 +2,27 @@ package dagger
import ( import (
"crypto/rand" "crypto/rand"
"encoding/json"
"fmt" "fmt"
"os" "os"
"strings" "strings"
"cuelang.org/go/cue" "cuelang.org/go/cue"
cueerrors "cuelang.org/go/cue/errors" cueerrors "cuelang.org/go/cue/errors"
cueformat "cuelang.org/go/cue/format"
"github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/client/llb/imagemetaresolver"
) )
func cuePrint(v cue.Value) (string, error) {
b, err := cueformat.Node(v.Syntax())
if err != nil {
return "", err
}
return string(b), nil
}
func cueErr(err error) error { func cueErr(err error) error {
return fmt.Errorf("%s", cueerrors.Details(err, &cueerrors.Config{})) return fmt.Errorf("%s", cueerrors.Details(err, &cueerrors.Config{}))
} }
func debugJSON(v interface{}) {
if os.Getenv("DEBUG") != "" {
e := json.NewEncoder(os.Stderr)
e.SetIndent("", " ")
e.Encode(v)
}
}
func debugf(msg string, args ...interface{}) { func debugf(msg string, args ...interface{}) {
if !strings.HasSuffix(msg, "\n") { if !strings.HasSuffix(msg, "\n") {
msg = msg + "\n" msg += "\n"
} }
if os.Getenv("DEBUG") != "" { if os.Getenv("DEBUG") != "" {
fmt.Fprintf(os.Stderr, msg, args...) fmt.Fprintf(os.Stderr, msg, args...)
} }
} }
func debug(msg string) {
if os.Getenv("DEBUG") != "" {
fmt.Fprintln(os.Stderr, msg)
}
}
func randomID(size int) (string, error) { func randomID(size int) (string, error) {
b := make([]byte, size) b := make([]byte, size)
_, err := rand.Read(b) _, err := rand.Read(b)
@ -58,14 +32,6 @@ func randomID(size int) (string, error) {
return fmt.Sprintf("%x", b), nil return fmt.Sprintf("%x", b), nil
} }
// LLB Helper to pull a Docker image + all its metadata
func llbDockerImage(ref string) llb.State {
return llb.Image(
ref,
llb.WithMetaResolver(imagemetaresolver.Default()),
)
}
func cueStringsToCuePath(parts ...string) cue.Path { func cueStringsToCuePath(parts ...string) cue.Path {
selectors := make([]cue.Selector, 0, len(parts)) selectors := make([]cue.Selector, 0, len(parts))
for _, part := range parts { for _, part := range parts {
@ -82,9 +48,3 @@ func cuePathToStrings(p cue.Path) []string {
} }
return out return out
} }
// Validate a cue path, and return a canonical version
func cueCleanPath(p string) (string, error) {
cp := cue.ParsePath(p)
return cp.String(), cp.Err()
}

View File

@ -35,7 +35,8 @@ func (v *Value) Unlock() {
func (v *Value) Lookup(path ...string) *Value { func (v *Value) Lookup(path ...string) *Value {
v.Lock() v.Lock()
defer v.Unlock() defer v.Unlock()
return v.Wrap(v.Unwrap().Lookup(path...))
return v.Wrap(v.Unwrap().LookupPath(cueStringsToCuePath(path...)))
} }
func (v *Value) LookupPath(p cue.Path) *Value { func (v *Value) LookupPath(p cue.Path) *Value {
@ -176,7 +177,7 @@ func (v *Value) RangeList(fn func(int, *Value) error) error {
if err := fn(i, v.Wrap(it.Value())); err != nil { if err := fn(i, v.Wrap(it.Value())); err != nil {
return err return err
} }
i += 1 i++
} }
return nil return nil
} }