mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-25 19:31:05 +00:00
Pull in cncd/* for simpler workflow
This commit is contained in:
parent
f9f0998cd2
commit
a4541ac901
141 changed files with 6341 additions and 217 deletions
|
@ -29,11 +29,11 @@ import (
|
|||
"google.golang.org/grpc/keepalive"
|
||||
"google.golang.org/grpc/metadata"
|
||||
|
||||
"github.com/cncd/pipeline/pipeline"
|
||||
"github.com/cncd/pipeline/pipeline/backend"
|
||||
"github.com/cncd/pipeline/pipeline/backend/docker"
|
||||
"github.com/cncd/pipeline/pipeline/multipart"
|
||||
"github.com/cncd/pipeline/pipeline/rpc"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/backend"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/backend/docker"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/multipart"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/rpc"
|
||||
|
||||
"github.com/drone/signal"
|
||||
"github.com/rs/zerolog"
|
||||
|
|
|
@ -33,9 +33,9 @@ import (
|
|||
"golang.org/x/crypto/acme/autocert"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/cncd/logging"
|
||||
"github.com/cncd/pipeline/pipeline/rpc/proto"
|
||||
"github.com/cncd/pubsub"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/logging"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/rpc/proto"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pubsub"
|
||||
"github.com/laszlocph/drone-oss-08/plugins/sender"
|
||||
"github.com/laszlocph/drone-oss-08/remote"
|
||||
"github.com/laszlocph/drone-oss-08/router"
|
||||
|
|
|
@ -18,7 +18,7 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/cncd/queue"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/queue"
|
||||
"github.com/dimfeld/httptreemux"
|
||||
"github.com/laszlocph/drone-oss-08/model"
|
||||
"github.com/laszlocph/drone-oss-08/plugins/registry"
|
||||
|
|
6
cncd/logging/README
Normal file
6
cncd/logging/README
Normal file
|
@ -0,0 +1,6 @@
|
|||
Go package provides a common interface for storing and streaming logs.
|
||||
|
||||
Documentation:
|
||||
|
||||
http://godoc.org/github.com/laszlocph/drone-oss-08/cncd/logging
|
||||
http://godoc.org/github.com/laszlocph/drone-oss-08/cncd/logging/gcp
|
52
cncd/logging/log_test.go
Normal file
52
cncd/logging/log_test.go
Normal file
|
@ -0,0 +1,52 @@
|
|||
package logging
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestLogging(t *testing.T) {
|
||||
var (
|
||||
wg sync.WaitGroup
|
||||
|
||||
testPath = "test"
|
||||
testEntry = &Entry{
|
||||
Data: []byte("test"),
|
||||
}
|
||||
)
|
||||
|
||||
ctx, cancel := context.WithCancel(
|
||||
context.Background(),
|
||||
)
|
||||
|
||||
logger := New()
|
||||
logger.Open(ctx, testPath)
|
||||
go func() {
|
||||
logger.Tail(ctx, testPath, func(entry ...*Entry) { wg.Done() })
|
||||
}()
|
||||
go func() {
|
||||
logger.Tail(ctx, testPath, func(entry ...*Entry) { wg.Done() })
|
||||
}()
|
||||
|
||||
<-time.After(time.Millisecond)
|
||||
|
||||
wg.Add(4)
|
||||
go func() {
|
||||
logger.Write(ctx, testPath, testEntry)
|
||||
logger.Write(ctx, testPath, testEntry)
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
logger.Tail(ctx, testPath, func(entry ...*Entry) { wg.Done() })
|
||||
}()
|
||||
|
||||
<-time.After(time.Millisecond)
|
||||
|
||||
wg.Wait()
|
||||
cancel()
|
||||
}
|
15
cncd/pipeline/.drone.yml
Normal file
15
cncd/pipeline/.drone.yml
Normal file
|
@ -0,0 +1,15 @@
|
|||
workspace:
|
||||
base: /go
|
||||
path: src/github.com/laszlocph/drone-oss-08/cncd/pipeline
|
||||
|
||||
pipeline:
|
||||
install:
|
||||
image: golang:1.8
|
||||
commands:
|
||||
- go install github.com/laszlocph/drone-oss-08/cncd/pipeline/pipec
|
||||
- go install github.com/laszlocph/drone-oss-08/cncd/pipeline/piped
|
||||
|
||||
test:
|
||||
image: golang:1.8
|
||||
commands:
|
||||
- go test -cover github.com/laszlocph/drone-oss-08/cncd/pipeline/...
|
2
cncd/pipeline/.gitignore
vendored
Normal file
2
cncd/pipeline/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*.txt
|
||||
*.out
|
1
cncd/pipeline/doc.go
Normal file
1
cncd/pipeline/doc.go
Normal file
|
@ -0,0 +1 @@
|
|||
package pipeline
|
507
cncd/pipeline/pipec/compile.go
Normal file
507
cncd/pipeline/pipec/compile.go
Normal file
|
@ -0,0 +1,507 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/frontend"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/frontend/yaml"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/frontend/yaml/compiler"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var compileCommand = cli.Command{
|
||||
Name: "compile",
|
||||
Usage: "compile the yaml file",
|
||||
Action: compileAction,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "in",
|
||||
Value: "pipeline.yml",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "out",
|
||||
Value: "pipeline.json",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "volumes",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "privileged",
|
||||
Value: &cli.StringSlice{
|
||||
"plugins/docker",
|
||||
"plugins/gcr",
|
||||
"plugins/ecr",
|
||||
},
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "prefix",
|
||||
Value: "pipeline",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "local",
|
||||
},
|
||||
//
|
||||
// volume caching
|
||||
//
|
||||
cli.BoolFlag{
|
||||
Name: "volume-cache",
|
||||
EnvVar: "CI_VOLUME_CACHE",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "volume-cache-base",
|
||||
Value: "/var/lib/drone",
|
||||
EnvVar: "CI_VOLUME_CACHE_BASE",
|
||||
},
|
||||
//
|
||||
// s3 caching
|
||||
//
|
||||
cli.BoolFlag{
|
||||
Name: "aws-cache",
|
||||
EnvVar: "CI_AWS_CACHE",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "aws-region",
|
||||
EnvVar: "AWS_REGION",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "aws-bucket",
|
||||
EnvVar: "AWS_BUCKET",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "aws-access-key-id",
|
||||
EnvVar: "AWS_ACCESS_KEY_ID",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "aws-secret-access-key",
|
||||
EnvVar: "AWS_SECRET_ACCESS_KEY",
|
||||
},
|
||||
//
|
||||
// registry credentials
|
||||
//
|
||||
cli.StringFlag{
|
||||
Name: "registry-hostname",
|
||||
EnvVar: "CI_REGISTRY_HOSTNAME",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "registry-username",
|
||||
EnvVar: "CI_REGISTRY_USERNAME",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "registry-password",
|
||||
EnvVar: "CI_REGISTRY_PASSWORD",
|
||||
},
|
||||
//
|
||||
// workspace default
|
||||
//
|
||||
cli.StringFlag{
|
||||
Name: "workspace-base",
|
||||
Value: "/pipeline",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "workspace-path",
|
||||
Value: "src",
|
||||
},
|
||||
//
|
||||
// netrc parameters
|
||||
//
|
||||
cli.StringFlag{
|
||||
Name: "netrc-username",
|
||||
EnvVar: "CI_NETRC_USERNAME",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "netrc-password",
|
||||
EnvVar: "CI_NETRC_PASSWORD",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "netrc-machine",
|
||||
EnvVar: "CI_NETRC_MACHINE",
|
||||
},
|
||||
//
|
||||
// resource limit parameters
|
||||
//
|
||||
cli.Int64Flag{
|
||||
Name: "limit-mem-swap",
|
||||
EnvVar: "CI_LIMIT_MEM_SWAP",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "limit-mem",
|
||||
EnvVar: "CI_LIMIT_MEM",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "limit-shm-size",
|
||||
EnvVar: "CI_LIMIT_SHM_SIZE",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "limit-cpu-quota",
|
||||
EnvVar: "CI_LIMIT_CPU_QUOTA",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "limit-cpu-shares",
|
||||
EnvVar: "CI_LIMIT_CPU_SHARES",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "limit-cpu-set",
|
||||
EnvVar: "CI_LIMIT_CPU_SET",
|
||||
},
|
||||
//
|
||||
// metadata parameters
|
||||
//
|
||||
cli.StringFlag{
|
||||
Name: "system-arch",
|
||||
Value: "linux/amd64",
|
||||
EnvVar: "CI_SYSTEM_ARCH",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "system-name",
|
||||
Value: "pipec",
|
||||
EnvVar: "CI_SYSTEM_NAME",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "system-link",
|
||||
Value: "https://github.com/cncd/pipec",
|
||||
EnvVar: "CI_SYSTEM_LINK",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "repo-name",
|
||||
EnvVar: "CI_REPO_NAME",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "repo-link",
|
||||
EnvVar: "CI_REPO_LINK",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "repo-remote-url",
|
||||
EnvVar: "CI_REPO_REMOTE",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "repo-private",
|
||||
EnvVar: "CI_REPO_PRIVATE",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "build-number",
|
||||
EnvVar: "CI_BUILD_NUMBER",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "build-created",
|
||||
EnvVar: "CI_BUILD_CREATED",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "build-started",
|
||||
EnvVar: "CI_BUILD_STARTED",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "build-finished",
|
||||
EnvVar: "CI_BUILD_FINISHED",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "build-status",
|
||||
EnvVar: "CI_BUILD_STATUS",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "build-event",
|
||||
EnvVar: "CI_BUILD_EVENT",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "build-link",
|
||||
EnvVar: "CI_BUILD_LINK",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "build-target",
|
||||
EnvVar: "CI_BUILD_TARGET",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "commit-sha",
|
||||
EnvVar: "CI_COMMIT_SHA",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "commit-ref",
|
||||
EnvVar: "CI_COMMIT_REF",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "commit-refspec",
|
||||
EnvVar: "CI_COMMIT_REFSPEC",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "commit-branch",
|
||||
EnvVar: "CI_COMMIT_BRANCH",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "commit-message",
|
||||
EnvVar: "CI_COMMIT_MESSAGE",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "commit-author-name",
|
||||
EnvVar: "CI_COMMIT_AUTHOR_NAME",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "commit-author-avatar",
|
||||
EnvVar: "CI_COMMIT_AUTHOR_AVATAR",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "commit-author-email",
|
||||
EnvVar: "CI_COMMIT_AUTHOR_EMAIL",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "prev-build-number",
|
||||
EnvVar: "CI_PREV_BUILD_NUMBER",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "prev-build-created",
|
||||
EnvVar: "CI_PREV_BUILD_CREATED",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "prev-build-started",
|
||||
EnvVar: "CI_PREV_BUILD_STARTED",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "prev-build-finished",
|
||||
EnvVar: "CI_PREV_BUILD_FINISHED",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "prev-build-status",
|
||||
EnvVar: "CI_PREV_BUILD_STATUS",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "prev-build-event",
|
||||
EnvVar: "CI_PREV_BUILD_EVENT",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "prev-build-link",
|
||||
EnvVar: "CI_PREV_BUILD_LINK",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "prev-commit-sha",
|
||||
EnvVar: "CI_PREV_COMMIT_SHA",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "prev-commit-ref",
|
||||
EnvVar: "CI_PREV_COMMIT_REF",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "prev-commit-refspec",
|
||||
EnvVar: "CI_PREV_COMMIT_REFSPEC",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "prev-commit-branch",
|
||||
EnvVar: "CI_PREV_COMMIT_BRANCH",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "prev-commit-message",
|
||||
EnvVar: "CI_PREV_COMMIT_MESSAGE",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "prev-commit-author-name",
|
||||
EnvVar: "CI_PREV_COMMIT_AUTHOR_NAME",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "prev-commit-author-avatar",
|
||||
EnvVar: "CI_PREV_COMMIT_AUTHOR_AVATAR",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "prev-commit-author-email",
|
||||
EnvVar: "CI_PREV_COMMIT_AUTHOR_EMAIL",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "job-number",
|
||||
EnvVar: "CI_JOB_NUMBER",
|
||||
},
|
||||
// cli.StringFlag{
|
||||
// Name: "job-matrix",
|
||||
// EnvVar: "CI_JOB_MATRIX",
|
||||
// },
|
||||
},
|
||||
}
|
||||
|
||||
func compileAction(c *cli.Context) (err error) {
|
||||
file := c.Args().First()
|
||||
if file == "" {
|
||||
file = c.String("in")
|
||||
}
|
||||
|
||||
conf, err := yaml.ParseFile(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// configure volumes for local execution
|
||||
volumes := c.StringSlice("volumes")
|
||||
if c.Bool("local") {
|
||||
var (
|
||||
workspaceBase = conf.Workspace.Base
|
||||
workspacePath = conf.Workspace.Path
|
||||
)
|
||||
if workspaceBase == "" {
|
||||
workspaceBase = c.String("workspace-base")
|
||||
}
|
||||
if workspacePath == "" {
|
||||
workspacePath = c.String("workspace-path")
|
||||
}
|
||||
dir, _ := filepath.Abs(filepath.Dir(file))
|
||||
volumes = append(volumes, dir+":"+path.Join(workspaceBase, workspacePath))
|
||||
}
|
||||
|
||||
// secrets from environment variable
|
||||
var secrets []compiler.Secret
|
||||
for _, env := range os.Environ() {
|
||||
parts := strings.Split(env, "=")
|
||||
secrets = append(secrets, compiler.Secret{
|
||||
Name: parts[0],
|
||||
Value: parts[1],
|
||||
})
|
||||
}
|
||||
|
||||
// compiles the yaml file
|
||||
compiled := compiler.New(
|
||||
compiler.WithResourceLimit(
|
||||
c.Int64("limit-mem-swap"),
|
||||
c.Int64("limit-mem"),
|
||||
c.Int64("limit-shm-size"),
|
||||
c.Int64("limit-cpu-quota"),
|
||||
c.Int64("limit-cpu-shares"),
|
||||
c.String("limit-cpu-set"),
|
||||
),
|
||||
compiler.WithRegistry(
|
||||
compiler.Registry{
|
||||
Hostname: c.String("registry-hostname"),
|
||||
Username: c.String("registry-username"),
|
||||
Password: c.String("registry-password"),
|
||||
},
|
||||
),
|
||||
compiler.WithEscalated(
|
||||
c.StringSlice("privileged")...,
|
||||
),
|
||||
compiler.WithSecret(secrets...),
|
||||
compiler.WithVolumes(volumes...),
|
||||
compiler.WithWorkspace(
|
||||
c.String("workspace-base"),
|
||||
c.String("workspace-path"),
|
||||
),
|
||||
compiler.WithPrefix(
|
||||
c.String("prefix"),
|
||||
),
|
||||
compiler.WithProxy(),
|
||||
compiler.WithLocal(
|
||||
c.Bool("local"),
|
||||
),
|
||||
compiler.WithNetrc(
|
||||
c.String("netrc-username"),
|
||||
c.String("netrc-password"),
|
||||
c.String("netrc-machine"),
|
||||
),
|
||||
compiler.WithMetadata(
|
||||
metadataFromContext(c),
|
||||
),
|
||||
compiler.WithOption(
|
||||
compiler.WithVolumeCacher(
|
||||
c.String("volume-cache-base"),
|
||||
),
|
||||
c.Bool("volume-cache"),
|
||||
),
|
||||
compiler.WithOption(
|
||||
compiler.WithS3Cacher(
|
||||
c.String("aws-access-key-id"),
|
||||
c.String("aws-secret-access-key"),
|
||||
c.String("aws-region"),
|
||||
c.String("aws-bucket"),
|
||||
),
|
||||
c.Bool("aws-cache"),
|
||||
),
|
||||
).Compile(conf)
|
||||
|
||||
// marshal the compiled spec to formatted yaml
|
||||
out, err := json.MarshalIndent(compiled, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create output file with option to dump to stdout
|
||||
var writer = os.Stdout
|
||||
output := c.String("out")
|
||||
if output != "-" {
|
||||
writer, err = os.Create(output)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
defer writer.Close()
|
||||
|
||||
_, err = writer.Write(out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if writer != os.Stdout {
|
||||
fmt.Fprintf(os.Stdout, "Successfully compiled %s to %s\n", file, output)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// return the metadata from the cli context.
|
||||
func metadataFromContext(c *cli.Context) frontend.Metadata {
|
||||
return frontend.Metadata{
|
||||
Repo: frontend.Repo{
|
||||
Name: c.String("repo-name"),
|
||||
Link: c.String("repo-link"),
|
||||
Remote: c.String("repo-remote-url"),
|
||||
Private: c.Bool("repo-private"),
|
||||
},
|
||||
Curr: frontend.Build{
|
||||
Number: c.Int("build-number"),
|
||||
Created: c.Int64("build-created"),
|
||||
Started: c.Int64("build-started"),
|
||||
Finished: c.Int64("build-finished"),
|
||||
Status: c.String("build-status"),
|
||||
Event: c.String("build-event"),
|
||||
Link: c.String("build-link"),
|
||||
Target: c.String("build-target"),
|
||||
Commit: frontend.Commit{
|
||||
Sha: c.String("commit-sha"),
|
||||
Ref: c.String("commit-ref"),
|
||||
Refspec: c.String("commit-refspec"),
|
||||
Branch: c.String("commit-branch"),
|
||||
Message: c.String("commit-message"),
|
||||
Author: frontend.Author{
|
||||
Name: c.String("commit-author-name"),
|
||||
Email: c.String("commit-author-email"),
|
||||
Avatar: c.String("commit-author-avatar"),
|
||||
},
|
||||
},
|
||||
},
|
||||
Prev: frontend.Build{
|
||||
Number: c.Int("prev-build-number"),
|
||||
Created: c.Int64("prev-build-created"),
|
||||
Started: c.Int64("prev-build-started"),
|
||||
Finished: c.Int64("prev-build-finished"),
|
||||
Status: c.String("prev-build-status"),
|
||||
Event: c.String("prev-build-event"),
|
||||
Link: c.String("prev-build-link"),
|
||||
Commit: frontend.Commit{
|
||||
Sha: c.String("prev-commit-sha"),
|
||||
Ref: c.String("prev-commit-ref"),
|
||||
Refspec: c.String("prev-commit-refspec"),
|
||||
Branch: c.String("prev-commit-branch"),
|
||||
Message: c.String("prev-commit-message"),
|
||||
Author: frontend.Author{
|
||||
Name: c.String("prev-commit-author-name"),
|
||||
Email: c.String("prev-commit-author-email"),
|
||||
Avatar: c.String("prev-commit-author-avatar"),
|
||||
},
|
||||
},
|
||||
},
|
||||
Job: frontend.Job{
|
||||
Number: c.Int("job-number"),
|
||||
// Matrix: ,
|
||||
},
|
||||
Sys: frontend.System{
|
||||
Name: c.String("system-name"),
|
||||
Link: c.String("system-link"),
|
||||
Arch: c.String("system-arch"),
|
||||
},
|
||||
}
|
||||
}
|
123
cncd/pipeline/pipec/exec.go
Normal file
123
cncd/pipeline/pipec/exec.go
Normal file
|
@ -0,0 +1,123 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/backend"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/backend/docker"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/backend/kubernetes"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/interrupt"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/multipart"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var executeCommand = cli.Command{
|
||||
Name: "exec",
|
||||
Usage: "execute the compiled file",
|
||||
Action: executeAction,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "in",
|
||||
Value: "pipeline.json",
|
||||
},
|
||||
cli.DurationFlag{
|
||||
Name: "timeout",
|
||||
EnvVar: "CI_TIMEOUT",
|
||||
Value: time.Hour,
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "kubernetes",
|
||||
EnvVar: "CI_KUBERNETES",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "kubernetes-namepsace",
|
||||
EnvVar: "CI_KUBERNETES_NAMESPACE",
|
||||
Value: "default",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "kubernetes-endpoint",
|
||||
EnvVar: "CI_KUBERNETES_ENDPOINT",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "kubernetes-token",
|
||||
EnvVar: "CI_KUBERNETES_TOKEN",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func executeAction(c *cli.Context) (err error) {
|
||||
path := c.Args().First()
|
||||
if path == "" {
|
||||
path = c.String("in")
|
||||
}
|
||||
|
||||
var reader io.ReadCloser
|
||||
if path == "-" {
|
||||
reader = os.Stdin
|
||||
} else {
|
||||
reader, err = os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
config, err := pipeline.Parse(reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var engine backend.Engine
|
||||
if c.Bool("kubernetes") {
|
||||
engine = kubernetes.New(
|
||||
c.String("kubernetes-namepsace"),
|
||||
c.String("kubernetes-endpoint"),
|
||||
c.String("kubernetes-token"),
|
||||
)
|
||||
} else {
|
||||
engine, err = docker.NewEnv()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), c.Duration("timeout"))
|
||||
defer cancel()
|
||||
ctx = interrupt.WithContext(ctx)
|
||||
|
||||
return pipeline.New(config,
|
||||
pipeline.WithContext(ctx),
|
||||
pipeline.WithLogger(defaultLogger),
|
||||
pipeline.WithTracer(defaultTracer),
|
||||
pipeline.WithEngine(engine),
|
||||
).Run()
|
||||
}
|
||||
|
||||
var defaultLogger = pipeline.LogFunc(func(proc *backend.Step, rc multipart.Reader) error {
|
||||
part, err := rc.NextPart()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
io.Copy(os.Stderr, part)
|
||||
return nil
|
||||
})
|
||||
|
||||
var defaultTracer = pipeline.TraceFunc(func(state *pipeline.State) error {
|
||||
if state.Process.Exited {
|
||||
fmt.Printf("proc %q exited with status %d\n", state.Pipeline.Step.Name, state.Process.ExitCode)
|
||||
} else {
|
||||
fmt.Printf("proc %q started\n", state.Pipeline.Step.Name)
|
||||
state.Pipeline.Step.Environment["CI_BUILD_STATUS"] = "success"
|
||||
state.Pipeline.Step.Environment["CI_BUILD_FINISHED"] = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
if state.Pipeline.Error != nil {
|
||||
state.Pipeline.Step.Environment["CI_BUILD_STATUS"] = "failure"
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
54
cncd/pipeline/pipec/lint.go
Normal file
54
cncd/pipeline/pipec/lint.go
Normal file
|
@ -0,0 +1,54 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/frontend/yaml"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/frontend/yaml/linter"
|
||||
|
||||
"github.com/kr/pretty"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var lintCommand = cli.Command{
|
||||
Name: "lint",
|
||||
Usage: "lints the yaml file",
|
||||
Action: lintAction,
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "trusted",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "pretty",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func lintAction(c *cli.Context) error {
|
||||
file := c.Args().First()
|
||||
if file == "" {
|
||||
return fmt.Errorf("Error: please provide a path the configuration file")
|
||||
}
|
||||
|
||||
conf, err := yaml.ParseFile(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = linter.New(
|
||||
linter.WithTrusted(
|
||||
c.Bool("trusted"),
|
||||
),
|
||||
).Lint(conf)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.Bool("pretty") {
|
||||
pretty.Println(conf)
|
||||
}
|
||||
|
||||
fmt.Println("Lint complete. Yaml file is valid")
|
||||
return nil
|
||||
}
|
26
cncd/pipeline/pipec/main.go
Normal file
26
cncd/pipeline/pipec/main.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "pipec"
|
||||
app.Usage = "pipec provides command line tools for the cncd runtime"
|
||||
app.Commands = []cli.Command{
|
||||
compileCommand,
|
||||
executeCommand,
|
||||
lintCommand,
|
||||
}
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
314
cncd/pipeline/piped/main.go
Normal file
314
cncd/pipeline/piped/main.go
Normal file
|
@ -0,0 +1,314 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/backend"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/backend/docker"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/interrupt"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/multipart"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/rpc"
|
||||
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/tevino/abool"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
const (
|
||||
maxFileUpload = 5000000
|
||||
maxLogsUpload = 5000000
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "piped"
|
||||
app.Usage = "piped stars a pipeline execution daemon"
|
||||
app.Action = start
|
||||
app.Flags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "endpoint",
|
||||
EnvVar: "PIPED_ENDPOINT,PIPED_SERVER",
|
||||
Value: "ws://localhost:9999",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "token",
|
||||
EnvVar: "PIPED_TOKEN,PIPED_SECRET",
|
||||
},
|
||||
cli.DurationFlag{
|
||||
Name: "backoff",
|
||||
EnvVar: "PIPED_BACKOFF",
|
||||
Value: time.Second * 15,
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "retry-limit",
|
||||
EnvVar: "PIPED_RETRY_LIMIT",
|
||||
Value: math.MaxInt32,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "platform",
|
||||
EnvVar: "PIPED_PLATFORM",
|
||||
Value: "linux/amd64",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "upload-limit",
|
||||
EnvVar: "PIPED_UPLOAD_LIMIT",
|
||||
Value: math.MaxInt32,
|
||||
},
|
||||
}
|
||||
app.Commands = []cli.Command{
|
||||
onceCommand,
|
||||
}
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
|
||||
func start(c *cli.Context) error {
|
||||
endpoint, err := url.Parse(
|
||||
c.String("endpoint"),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
filter := rpc.Filter{
|
||||
Labels: map[string]string{
|
||||
"platform": c.String("platform"),
|
||||
},
|
||||
}
|
||||
|
||||
client, err := rpc.NewClient(
|
||||
endpoint.String(),
|
||||
rpc.WithRetryLimit(
|
||||
c.Int("retry-limit"),
|
||||
),
|
||||
rpc.WithBackoff(
|
||||
c.Duration("backoff"),
|
||||
),
|
||||
rpc.WithToken(
|
||||
c.String("token"),
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
sigterm := abool.New()
|
||||
ctx := context.Background()
|
||||
ctx = interrupt.WithContextFunc(ctx, func() {
|
||||
println("ctrl+c received, terminating process")
|
||||
sigterm.Set()
|
||||
})
|
||||
|
||||
for {
|
||||
if sigterm.IsSet() {
|
||||
return nil
|
||||
}
|
||||
if err := run(ctx, client, filter); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func run(ctx context.Context, client rpc.Peer, filter rpc.Filter) error {
|
||||
log.Println("pipeline: request next execution")
|
||||
|
||||
// get the next job from the queue
|
||||
work, err := client.Next(ctx, filter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if work == nil {
|
||||
return nil
|
||||
}
|
||||
log.Printf("pipeline: received next execution: %s", work.ID)
|
||||
if os.Getenv("SUICIDE_MODE") != "" {
|
||||
os.Exit(1)
|
||||
}
|
||||
// new docker engine
|
||||
engine, err := docker.NewEnv()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
timeout := time.Hour
|
||||
if minutes := work.Timeout; minutes != 0 {
|
||||
timeout = time.Duration(minutes) * time.Minute
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
|
||||
cancelled := abool.New()
|
||||
go func() {
|
||||
werr := client.Wait(ctx, work.ID)
|
||||
if werr != nil {
|
||||
cancelled.SetTo(true) // TODO verify error is really an error
|
||||
log.Printf("pipeline: cancel signal received: %s: %s", work.ID, werr)
|
||||
cancel()
|
||||
} else {
|
||||
log.Printf("pipeline: cancel channel closed: %s", work.ID)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
log.Printf("pipeline: cancel ping loop: %s", work.ID)
|
||||
return
|
||||
case <-time.After(time.Minute):
|
||||
log.Printf("pipeline: ping queue: %s", work.ID)
|
||||
client.Extend(ctx, work.ID)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
state := rpc.State{}
|
||||
state.Started = time.Now().Unix()
|
||||
err = client.Init(context.Background(), work.ID, state)
|
||||
if err != nil {
|
||||
log.Printf("pipeline: error signaling pipeline init: %s: %s", work.ID, err)
|
||||
}
|
||||
|
||||
var uploads sync.WaitGroup
|
||||
defaultLogger := pipeline.LogFunc(func(proc *backend.Step, rc multipart.Reader) error {
|
||||
part, rerr := rc.NextPart()
|
||||
if rerr != nil {
|
||||
return rerr
|
||||
}
|
||||
uploads.Add(1)
|
||||
|
||||
var secrets []string
|
||||
for _, secret := range work.Config.Secrets {
|
||||
if secret.Mask {
|
||||
secrets = append(secrets, secret.Value)
|
||||
}
|
||||
}
|
||||
|
||||
limitedPart := io.LimitReader(part, maxLogsUpload)
|
||||
logstream := rpc.NewLineWriter(client, work.ID, proc.Alias, secrets...)
|
||||
io.Copy(logstream, limitedPart)
|
||||
|
||||
file := &rpc.File{}
|
||||
file.Mime = "application/json+logs"
|
||||
file.Proc = proc.Alias
|
||||
file.Name = "logs.json"
|
||||
file.Data, _ = json.Marshal(logstream.Lines())
|
||||
file.Size = len(file.Data)
|
||||
file.Time = time.Now().Unix()
|
||||
|
||||
if serr := client.Upload(context.Background(), work.ID, file); serr != nil {
|
||||
log.Printf("pipeline: cannot upload logs: %s: %s: %s", work.ID, file.Mime, serr)
|
||||
} else {
|
||||
log.Printf("pipeline: finish uploading logs: %s: step %s: %s", file.Mime, work.ID, proc.Alias)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
log.Printf("pipeline: finish uploading logs: %s: step %s", work.ID, proc.Alias)
|
||||
uploads.Done()
|
||||
}()
|
||||
|
||||
part, rerr = rc.NextPart()
|
||||
if rerr != nil {
|
||||
return nil
|
||||
}
|
||||
// TODO should be configurable
|
||||
limitedPart = io.LimitReader(part, maxFileUpload)
|
||||
file = &rpc.File{}
|
||||
file.Mime = part.Header().Get("Content-Type")
|
||||
file.Proc = proc.Alias
|
||||
file.Name = part.FileName()
|
||||
file.Data, _ = ioutil.ReadAll(limitedPart)
|
||||
file.Size = len(file.Data)
|
||||
file.Time = time.Now().Unix()
|
||||
|
||||
if serr := client.Upload(context.Background(), work.ID, file); serr != nil {
|
||||
log.Printf("pipeline: cannot upload artifact: %s: %s: %s", work.ID, file.Mime, serr)
|
||||
} else {
|
||||
log.Printf("pipeline: finish uploading artifact: %s: step %s: %s", file.Mime, work.ID, proc.Alias)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
defaultTracer := pipeline.TraceFunc(func(state *pipeline.State) error {
|
||||
procState := rpc.State{
|
||||
Proc: state.Pipeline.Step.Alias,
|
||||
Exited: state.Process.Exited,
|
||||
ExitCode: state.Process.ExitCode,
|
||||
Started: time.Now().Unix(), // TODO do not do this
|
||||
Finished: time.Now().Unix(),
|
||||
}
|
||||
defer func() {
|
||||
if uerr := client.Update(context.Background(), work.ID, procState); uerr != nil {
|
||||
log.Printf("Pipeine: error updating pipeline step status: %s: %s: %s", work.ID, procState.Proc, uerr)
|
||||
}
|
||||
}()
|
||||
if state.Process.Exited {
|
||||
return nil
|
||||
}
|
||||
if state.Pipeline.Step.Environment == nil {
|
||||
state.Pipeline.Step.Environment = map[string]string{}
|
||||
}
|
||||
state.Pipeline.Step.Environment["CI_BUILD_STATUS"] = "success"
|
||||
state.Pipeline.Step.Environment["CI_BUILD_STARTED"] = strconv.FormatInt(state.Pipeline.Time, 10)
|
||||
state.Pipeline.Step.Environment["CI_BUILD_FINISHED"] = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
|
||||
state.Pipeline.Step.Environment["CI_JOB_STATUS"] = "success"
|
||||
state.Pipeline.Step.Environment["CI_JOB_STARTED"] = strconv.FormatInt(state.Pipeline.Time, 10)
|
||||
state.Pipeline.Step.Environment["CI_JOB_FINISHED"] = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
|
||||
if state.Pipeline.Error != nil {
|
||||
state.Pipeline.Step.Environment["CI_BUILD_STATUS"] = "failure"
|
||||
state.Pipeline.Step.Environment["CI_JOB_STATUS"] = "failure"
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
err = pipeline.New(work.Config,
|
||||
pipeline.WithContext(ctx),
|
||||
pipeline.WithLogger(defaultLogger),
|
||||
pipeline.WithTracer(defaultTracer),
|
||||
pipeline.WithEngine(engine),
|
||||
).Run()
|
||||
|
||||
state.Finished = time.Now().Unix()
|
||||
state.Exited = true
|
||||
if err != nil {
|
||||
state.Error = err.Error()
|
||||
if xerr, ok := err.(*pipeline.ExitError); ok {
|
||||
state.ExitCode = xerr.Code
|
||||
}
|
||||
if xerr, ok := err.(*pipeline.OomError); ok {
|
||||
state.ExitCode = xerr.Code
|
||||
}
|
||||
if cancelled.IsSet() {
|
||||
state.ExitCode = 130
|
||||
} else if state.ExitCode == 0 {
|
||||
state.ExitCode = 1
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("pipeline: execution complete: %s", work.ID)
|
||||
|
||||
uploads.Wait()
|
||||
|
||||
err = client.Done(context.Background(), work.ID, state)
|
||||
if err != nil {
|
||||
log.Printf("Pipeine: error signaling pipeline done: %s: %s", work.ID, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
97
cncd/pipeline/piped/once.go
Normal file
97
cncd/pipeline/piped/once.go
Normal file
|
@ -0,0 +1,97 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"math"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/interrupt"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/rpc"
|
||||
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var onceCommand = cli.Command{
|
||||
Name: "once",
|
||||
Usage: "execute one build",
|
||||
Hidden: false,
|
||||
Action: once,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "endpoint",
|
||||
EnvVar: "PIPED_ENDPOINT,PIPED_SERVER",
|
||||
Value: "ws://localhost:9999",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "token",
|
||||
EnvVar: "PIPED_TOKEN,PIPED_SECRET",
|
||||
},
|
||||
cli.DurationFlag{
|
||||
Name: "backoff",
|
||||
EnvVar: "PIPED_BACKOFF",
|
||||
Value: time.Second * 15,
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "retry-limit",
|
||||
EnvVar: "PIPED_RETRY_LIMIT",
|
||||
Value: math.MaxInt32,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "platform",
|
||||
EnvVar: "PIPED_PLATFORM",
|
||||
Value: "linux/amd64",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "json",
|
||||
EnvVar: "PIPED_JSON",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func once(c *cli.Context) error {
|
||||
endpoint, err := url.Parse(
|
||||
c.String("endpoint"),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := rpc.NewClient(
|
||||
endpoint.String(),
|
||||
rpc.WithRetryLimit(
|
||||
c.Int("retry-limit"),
|
||||
),
|
||||
rpc.WithBackoff(
|
||||
c.Duration("backoff"),
|
||||
),
|
||||
rpc.WithToken(
|
||||
c.String("token"),
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
ctx = interrupt.WithContextFunc(ctx, func() {
|
||||
println("ctrl+c received, terminating process")
|
||||
})
|
||||
|
||||
return run(ctx, &onceClient{client, c.String("json")}, rpc.NoFilter)
|
||||
}
|
||||
|
||||
type onceClient struct {
|
||||
*rpc.Client
|
||||
json string
|
||||
}
|
||||
|
||||
func (c *onceClient) Next(ctx context.Context, filter rpc.Filter) (*rpc.Pipeline, error) {
|
||||
in := []byte(c.json)
|
||||
out := new(rpc.Pipeline)
|
||||
err := json.Unmarshal(in, out)
|
||||
return out, err
|
||||
}
|
|
@ -3,9 +3,10 @@ package docker
|
|||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/cncd/pipeline/pipeline/backend"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/backend"
|
||||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
)
|
||||
|
@ -82,7 +83,10 @@ func toHostConfig(proc *backend.Step) *container.HostConfig {
|
|||
config.Tmpfs[path] = ""
|
||||
continue
|
||||
}
|
||||
parts := strings.Split(path, ":")
|
||||
parts, err := splitVolumeParts(path)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
config.Tmpfs[parts[0]] = parts[1]
|
||||
}
|
||||
// if proc.OomKillDisable {
|
||||
|
@ -97,7 +101,10 @@ func toHostConfig(proc *backend.Step) *container.HostConfig {
|
|||
func toVol(paths []string) map[string]struct{} {
|
||||
set := map[string]struct{}{}
|
||||
for _, path := range paths {
|
||||
parts := strings.Split(path, ":")
|
||||
parts, err := splitVolumeParts(path)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if len(parts) < 2 {
|
||||
continue
|
||||
}
|
||||
|
@ -121,10 +128,16 @@ func toEnv(env map[string]string) []string {
|
|||
func toDev(paths []string) []container.DeviceMapping {
|
||||
var devices []container.DeviceMapping
|
||||
for _, path := range paths {
|
||||
parts := strings.Split(path, ":")
|
||||
parts, err := splitVolumeParts(path)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if len(parts) < 2 {
|
||||
continue
|
||||
}
|
||||
if strings.HasSuffix(parts[1], ":ro") || strings.HasSuffix(parts[1], ":rw") {
|
||||
parts[1] = parts[1][:len(parts[1])-1]
|
||||
}
|
||||
devices = append(devices, container.DeviceMapping{
|
||||
PathOnHost: parts[0],
|
||||
PathInContainer: parts[1],
|
||||
|
@ -143,3 +156,24 @@ func encodeAuthToBase64(authConfig backend.Auth) (string, error) {
|
|||
}
|
||||
return base64.URLEncoding.EncodeToString(buf), nil
|
||||
}
|
||||
|
||||
// helper function that split volume path
|
||||
func splitVolumeParts(volumeParts string) ([]string, error) {
|
||||
pattern := `^((?:[\w]\:)?[^\:]*)\:((?:[\w]\:)?[^\:]*)(?:\:([rwom]*))?`
|
||||
r, err := regexp.Compile(pattern)
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
if r.MatchString(volumeParts) {
|
||||
results := r.FindStringSubmatch(volumeParts)[1:]
|
||||
cleanResults := []string{}
|
||||
for _, item := range results {
|
||||
if item != "" {
|
||||
cleanResults = append(cleanResults, item)
|
||||
}
|
||||
}
|
||||
return cleanResults, nil
|
||||
} else {
|
||||
return strings.Split(volumeParts, ":"), nil
|
||||
}
|
||||
}
|
74
cncd/pipeline/pipeline/backend/docker/convert_test.go
Normal file
74
cncd/pipeline/pipeline/backend/docker/convert_test.go
Normal file
|
@ -0,0 +1,74 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSplitVolumeParts(t *testing.T) {
|
||||
testdata := []struct {
|
||||
from string
|
||||
to []string
|
||||
success bool
|
||||
}{
|
||||
{
|
||||
from: `Z::Z::rw`,
|
||||
to: []string{`Z:`, `Z:`, `rw`},
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
from: `Z:\:Z:\:rw`,
|
||||
to: []string{`Z:\`, `Z:\`, `rw`},
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
from: `Z:\git\refs:Z:\git\refs:rw`,
|
||||
to: []string{`Z:\git\refs`, `Z:\git\refs`, `rw`},
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
from: `Z:\git\refs:Z:\git\refs`,
|
||||
to: []string{`Z:\git\refs`, `Z:\git\refs`},
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
from: `Z:/:Z:/:rw`,
|
||||
to: []string{`Z:/`, `Z:/`, `rw`},
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
from: `Z:/git/refs:Z:/git/refs:rw`,
|
||||
to: []string{`Z:/git/refs`, `Z:/git/refs`, `rw`},
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
from: `Z:/git/refs:Z:/git/refs`,
|
||||
to: []string{`Z:/git/refs`, `Z:/git/refs`},
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
from: `/test:/test`,
|
||||
to: []string{`/test`, `/test`},
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
from: `test:/test`,
|
||||
to: []string{`test`, `/test`},
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
from: `test:test`,
|
||||
to: []string{`test`, `test`},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
for _, test := range testdata {
|
||||
results, err := splitVolumeParts(test.from)
|
||||
if test.success == (err != nil) {
|
||||
} else {
|
||||
if reflect.DeepEqual(results, test.to) != test.success {
|
||||
t.Errorf("Expect %q matches %q is %v", test.from, results, test.to)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ import (
|
|||
"io"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/cncd/pipeline/pipeline/backend"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/backend"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/network"
|
|
@ -3,7 +3,7 @@ package docker
|
|||
// import (
|
||||
// "context"
|
||||
//
|
||||
// "github.com/cncd/pipeline/pipeline/backend"
|
||||
// "github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/backend"
|
||||
// )
|
||||
//
|
||||
// // Pool manages a pool of Docker clients.
|
61
cncd/pipeline/pipeline/backend/kubernetes/kubernetes.go
Normal file
61
cncd/pipeline/pipeline/backend/kubernetes/kubernetes.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
package kubernetes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/backend"
|
||||
)
|
||||
|
||||
type engine struct {
|
||||
namespace string
|
||||
endpoint string
|
||||
token string
|
||||
}
|
||||
|
||||
// New returns a new Kubernetes Engine.
|
||||
func New(namespace, endpoint, token string) backend.Engine {
|
||||
return &engine{
|
||||
namespace: namespace,
|
||||
endpoint: endpoint,
|
||||
token: token,
|
||||
}
|
||||
}
|
||||
|
||||
// Setup the pipeline environment.
|
||||
func (e *engine) Setup(context.Context, *backend.Config) error {
|
||||
// POST /api/v1/namespaces
|
||||
return nil
|
||||
}
|
||||
|
||||
// Start the pipeline step.
|
||||
func (e *engine) Exec(context.Context, *backend.Step) error {
|
||||
// POST /api/v1/namespaces/{namespace}/pods
|
||||
return nil
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
// Kill the pipeline step.
|
||||
func (e *engine) Kill(context.Context, *backend.Step) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Wait for the pipeline step to complete and returns
|
||||
// the completion results.
|
||||
func (e *engine) Wait(context.Context, *backend.Step) (*backend.State, error) {
|
||||
// GET /api/v1/watch/namespaces/{namespace}/pods
|
||||
// GET /api/v1/watch/namespaces/{namespace}/pods/{name}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Tail the pipeline step logs.
|
||||
func (e *engine) Tail(context.Context, *backend.Step) (io.ReadCloser, error) {
|
||||
// GET /api/v1/namespaces/{namespace}/pods/{name}/log
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Destroy the pipeline environment.
|
||||
func (e *engine) Destroy(context.Context, *backend.Config) error {
|
||||
// DELETE /api/v1/namespaces/{name}
|
||||
return nil
|
||||
}
|
26
cncd/pipeline/pipeline/error_test.go
Normal file
26
cncd/pipeline/pipeline/error_test.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
package pipeline
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestExitError(t *testing.T) {
|
||||
err := ExitError{
|
||||
Name: "build",
|
||||
Code: 255,
|
||||
}
|
||||
got, want := err.Error(), "build : exit code 255"
|
||||
if got != want {
|
||||
t.Errorf("Want error message %q, got %q", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOomError(t *testing.T) {
|
||||
err := OomError{
|
||||
Name: "build",
|
||||
}
|
||||
got, want := err.Error(), "build : received oom kill"
|
||||
if got != want {
|
||||
t.Errorf("Want error message %q, got %q", want, got)
|
||||
}
|
||||
}
|
|
@ -176,7 +176,7 @@ func (m *Metadata) EnvironDrone() map[string]string {
|
|||
params := map[string]string{
|
||||
"CI": "drone",
|
||||
"DRONE": "true",
|
||||
"DRONE_ARCH": "linux/amd64",
|
||||
"DRONE_ARCH": m.Sys.Arch,
|
||||
"DRONE_REPO": m.Repo.Name,
|
||||
"DRONE_REPO_SCM": "git",
|
||||
"DRONE_REPO_OWNER": owner,
|
1
cncd/pipeline/pipeline/frontend/metadata_test.go
Normal file
1
cncd/pipeline/pipeline/frontend/metadata_test.go
Normal file
|
@ -0,0 +1 @@
|
|||
package frontend
|
|
@ -4,7 +4,7 @@ import (
|
|||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/cncd/pipeline/pipeline/frontend/yaml"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/frontend/yaml"
|
||||
|
||||
libcompose "github.com/docker/libcompose/yaml"
|
||||
)
|
|
@ -3,9 +3,9 @@ package compiler
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cncd/pipeline/pipeline/backend"
|
||||
"github.com/cncd/pipeline/pipeline/frontend"
|
||||
"github.com/cncd/pipeline/pipeline/frontend/yaml"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/backend"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/frontend"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/frontend/yaml"
|
||||
)
|
||||
|
||||
// TODO(bradrydzewski) compiler should handle user-defined volumes from YAML
|
||||
|
@ -75,10 +75,17 @@ func (c *Compiler) Compile(conf *yaml.Config) *backend.Config {
|
|||
})
|
||||
|
||||
// create a default network
|
||||
config.Networks = append(config.Networks, &backend.Network{
|
||||
Name: fmt.Sprintf("%s_default", c.prefix),
|
||||
Driver: "bridge",
|
||||
})
|
||||
if c.metadata.Sys.Arch == "windows/amd64" {
|
||||
config.Networks = append(config.Networks, &backend.Network{
|
||||
Name: fmt.Sprintf("%s_default", c.prefix),
|
||||
Driver: "nat",
|
||||
})
|
||||
} else {
|
||||
config.Networks = append(config.Networks, &backend.Network{
|
||||
Name: fmt.Sprintf("%s_default", c.prefix),
|
||||
Driver: "bridge",
|
||||
})
|
||||
}
|
||||
|
||||
// overrides the default workspace paths when specified
|
||||
// in the YAML file.
|
|
@ -0,0 +1 @@
|
|||
package compiler
|
|
@ -5,8 +5,8 @@ import (
|
|||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/cncd/pipeline/pipeline/backend"
|
||||
"github.com/cncd/pipeline/pipeline/frontend/yaml"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/backend"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/frontend/yaml"
|
||||
)
|
||||
|
||||
func (c *Compiler) createProcess(name string, container *yaml.Container, section string) *backend.Step {
|
||||
|
@ -77,12 +77,11 @@ func (c *Compiler) createProcess(name string, container *yaml.Container, section
|
|||
|
||||
if len(container.Commands) != 0 {
|
||||
if c.metadata.Sys.Arch == "windows/amd64" {
|
||||
// TODO provide windows implementation
|
||||
entrypoint = []string{"/bin/sh", "-c"}
|
||||
command = []string{"echo $CI_SCRIPT | base64 -d | /bin/sh -e"}
|
||||
entrypoint = []string{"powershell", "-noprofile", "-noninteractive", "-command"}
|
||||
command = []string{"[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Env:CI_SCRIPT)) | iex"}
|
||||
environment["CI_SCRIPT"] = generateScriptWindows(container.Commands)
|
||||
environment["HOME"] = "/root"
|
||||
environment["SHELL"] = "/bin/sh"
|
||||
environment["HOME"] = "c:\\root"
|
||||
environment["SHELL"] = "powershell.exe"
|
||||
} else {
|
||||
entrypoint = []string{"/bin/sh", "-c"}
|
||||
command = []string{"echo $CI_SCRIPT | base64 -d | /bin/sh -e"}
|
|
@ -0,0 +1 @@
|
|||
package compiler
|
244
cncd/pipeline/pipeline/frontend/yaml/compiler/image_test.go
Normal file
244
cncd/pipeline/pipeline/frontend/yaml/compiler/image_test.go
Normal file
|
@ -0,0 +1,244 @@
|
|||
package compiler
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTrimImage(t *testing.T) {
|
||||
testdata := []struct {
|
||||
from string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
from: "golang",
|
||||
want: "golang",
|
||||
},
|
||||
{
|
||||
from: "golang:latest",
|
||||
want: "golang",
|
||||
},
|
||||
{
|
||||
from: "golang:1.0.0",
|
||||
want: "golang",
|
||||
},
|
||||
{
|
||||
from: "library/golang",
|
||||
want: "golang",
|
||||
},
|
||||
{
|
||||
from: "library/golang:latest",
|
||||
want: "golang",
|
||||
},
|
||||
{
|
||||
from: "library/golang:1.0.0",
|
||||
want: "golang",
|
||||
},
|
||||
{
|
||||
from: "index.docker.io/library/golang:1.0.0",
|
||||
want: "golang",
|
||||
},
|
||||
{
|
||||
from: "gcr.io/library/golang:1.0.0",
|
||||
want: "gcr.io/library/golang",
|
||||
},
|
||||
// error cases, return input unmodified
|
||||
{
|
||||
from: "foo/bar?baz:boo",
|
||||
want: "foo/bar?baz:boo",
|
||||
},
|
||||
}
|
||||
for _, test := range testdata {
|
||||
got, want := trimImage(test.from), test.want
|
||||
if got != want {
|
||||
t.Errorf("Want image %q trimmed to %q, got %q", test.from, want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestExpandImage(t *testing.T) {
|
||||
testdata := []struct {
|
||||
from string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
from: "golang",
|
||||
want: "golang:latest",
|
||||
},
|
||||
{
|
||||
from: "golang:latest",
|
||||
want: "golang:latest",
|
||||
},
|
||||
{
|
||||
from: "golang:1.0.0",
|
||||
want: "golang:1.0.0",
|
||||
},
|
||||
{
|
||||
from: "library/golang",
|
||||
want: "golang:latest",
|
||||
},
|
||||
{
|
||||
from: "library/golang:latest",
|
||||
want: "golang:latest",
|
||||
},
|
||||
{
|
||||
from: "library/golang:1.0.0",
|
||||
want: "golang:1.0.0",
|
||||
},
|
||||
{
|
||||
from: "index.docker.io/library/golang:1.0.0",
|
||||
want: "golang:1.0.0",
|
||||
},
|
||||
{
|
||||
from: "gcr.io/golang",
|
||||
want: "gcr.io/golang:latest",
|
||||
},
|
||||
{
|
||||
from: "gcr.io/golang:1.0.0",
|
||||
want: "gcr.io/golang:1.0.0",
|
||||
},
|
||||
// error cases, return input unmodified
|
||||
{
|
||||
from: "foo/bar?baz:boo",
|
||||
want: "foo/bar?baz:boo",
|
||||
},
|
||||
}
|
||||
for _, test := range testdata {
|
||||
got, want := expandImage(test.from), test.want
|
||||
if got != want {
|
||||
t.Errorf("Want image %q expanded to %q, got %q", test.from, want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatchImage(t *testing.T) {
|
||||
testdata := []struct {
|
||||
from, to string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
from: "golang",
|
||||
to: "golang",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
from: "golang:latest",
|
||||
to: "golang",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
from: "library/golang:latest",
|
||||
to: "golang",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
from: "index.docker.io/library/golang:1.0.0",
|
||||
to: "golang",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
from: "golang",
|
||||
to: "golang:latest",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
from: "library/golang:latest",
|
||||
to: "library/golang",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
from: "gcr.io/golang",
|
||||
to: "gcr.io/golang",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
from: "gcr.io/golang:1.0.0",
|
||||
to: "gcr.io/golang",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
from: "gcr.io/golang:latest",
|
||||
to: "gcr.io/golang",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
from: "gcr.io/golang",
|
||||
to: "gcr.io/golang:latest",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
from: "golang",
|
||||
to: "library/golang",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
from: "golang",
|
||||
to: "gcr.io/project/golang",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
from: "golang",
|
||||
to: "gcr.io/library/golang",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
from: "golang",
|
||||
to: "gcr.io/golang",
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
for _, test := range testdata {
|
||||
got, want := matchImage(test.from, test.to), test.want
|
||||
if got != want {
|
||||
t.Errorf("Want image %q matching %q is %v", test.from, test.to, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatchHostname(t *testing.T) {
|
||||
testdata := []struct {
|
||||
image, hostname string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
image: "golang",
|
||||
hostname: "docker.io",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
image: "golang:latest",
|
||||
hostname: "docker.io",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
image: "library/golang:latest",
|
||||
hostname: "docker.io",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
image: "docker.io/library/golang:1.0.0",
|
||||
hostname: "docker.io",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
image: "gcr.io/golang",
|
||||
hostname: "docker.io",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
image: "gcr.io/golang:1.0.0",
|
||||
hostname: "gcr.io",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
image: "1.2.3.4:8000/golang:1.0.0",
|
||||
hostname: "1.2.3.4:8000",
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, test := range testdata {
|
||||
got, want := matchHostname(test.image, test.hostname), test.want
|
||||
if got != want {
|
||||
t.Errorf("Want image %q matching hostname %q is %v", test.image, test.hostname, want)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ import (
|
|||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/cncd/pipeline/pipeline/frontend"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/frontend"
|
||||
)
|
||||
|
||||
// Option configures a compiler option.
|
261
cncd/pipeline/pipeline/frontend/yaml/compiler/option_test.go
Normal file
261
cncd/pipeline/pipeline/frontend/yaml/compiler/option_test.go
Normal file
|
@ -0,0 +1,261 @@
|
|||
package compiler
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/frontend"
|
||||
)
|
||||
|
||||
func TestWithWorkspace(t *testing.T) {
|
||||
compiler := New(
|
||||
WithWorkspace(
|
||||
"/pipeline",
|
||||
"src/github.com/octocat/hello-world",
|
||||
),
|
||||
)
|
||||
if compiler.base != "/pipeline" {
|
||||
t.Errorf("WithWorkspace must set the base directory")
|
||||
}
|
||||
if compiler.path != "src/github.com/octocat/hello-world" {
|
||||
t.Errorf("WithWorkspace must set the path directory")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithEscalated(t *testing.T) {
|
||||
compiler := New(
|
||||
WithEscalated(
|
||||
"docker",
|
||||
"docker-dev",
|
||||
),
|
||||
)
|
||||
if compiler.escalated[0] != "docker" || compiler.escalated[1] != "docker-dev" {
|
||||
t.Errorf("WithEscalated must whitelist privileged images")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithVolumes(t *testing.T) {
|
||||
compiler := New(
|
||||
WithVolumes(
|
||||
"/tmp:/tmp",
|
||||
"/foo:/foo",
|
||||
),
|
||||
)
|
||||
if compiler.volumes[0] != "/tmp:/tmp" || compiler.volumes[1] != "/foo:/foo" {
|
||||
t.Errorf("TestWithVolumes must set default volumes")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithNetworks(t *testing.T) {
|
||||
compiler := New(
|
||||
WithNetworks(
|
||||
"overlay_1",
|
||||
"overlay_bar",
|
||||
),
|
||||
)
|
||||
if compiler.networks[0] != "overlay_1" || compiler.networks[1] != "overlay_bar" {
|
||||
t.Errorf("TestWithNetworks must set networks from parameters")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithResourceLimit(t *testing.T) {
|
||||
compiler := New(
|
||||
WithResourceLimit(
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
"0,2-5",
|
||||
),
|
||||
)
|
||||
if compiler.reslimit.MemSwapLimit != 1 {
|
||||
t.Errorf("TestWithResourceLimit must set MemSwapLimit from parameters")
|
||||
}
|
||||
if compiler.reslimit.MemLimit != 2 {
|
||||
t.Errorf("TestWithResourceLimit must set MemLimit from parameters")
|
||||
}
|
||||
if compiler.reslimit.ShmSize != 3 {
|
||||
t.Errorf("TestWithResourceLimit must set ShmSize from parameters")
|
||||
}
|
||||
if compiler.reslimit.CPUQuota != 4 {
|
||||
t.Errorf("TestWithResourceLimit must set CPUQuota from parameters")
|
||||
}
|
||||
if compiler.reslimit.CPUShares != 5 {
|
||||
t.Errorf("TestWithResourceLimit must set CPUShares from parameters")
|
||||
}
|
||||
if compiler.reslimit.CPUSet != "0,2-5" {
|
||||
t.Errorf("TestWithResourceLimit must set CPUSet from parameters")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithPrefix(t *testing.T) {
|
||||
if New(WithPrefix("drone_")).prefix != "drone_" {
|
||||
t.Errorf("WithPrefix must set the prefix")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithMetadata(t *testing.T) {
|
||||
metadata := frontend.Metadata{
|
||||
Repo: frontend.Repo{
|
||||
Name: "octocat/hello-world",
|
||||
Private: true,
|
||||
Link: "https://github.com/octocat/hello-world",
|
||||
Remote: "https://github.com/octocat/hello-world.git",
|
||||
},
|
||||
}
|
||||
compiler := New(
|
||||
WithMetadata(metadata),
|
||||
)
|
||||
if !reflect.DeepEqual(compiler.metadata, metadata) {
|
||||
t.Errorf("WithMetadata must set compiler the metadata")
|
||||
}
|
||||
if compiler.env["CI_REPO_NAME"] != metadata.Repo.Name {
|
||||
t.Errorf("WithMetadata must set CI_REPO_NAME")
|
||||
}
|
||||
if compiler.env["CI_REPO_LINK"] != metadata.Repo.Link {
|
||||
t.Errorf("WithMetadata must set CI_REPO_LINK")
|
||||
}
|
||||
if compiler.env["CI_REPO_REMOTE"] != metadata.Repo.Remote {
|
||||
t.Errorf("WithMetadata must set CI_REPO_REMOTE")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithLocal(t *testing.T) {
|
||||
if New(WithLocal(true)).local == false {
|
||||
t.Errorf("WithLocal true must enable the local flag")
|
||||
}
|
||||
if New(WithLocal(false)).local == true {
|
||||
t.Errorf("WithLocal false must disable the local flag")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithNetrc(t *testing.T) {
|
||||
compiler := New(
|
||||
WithNetrc(
|
||||
"octocat",
|
||||
"password",
|
||||
"github.com",
|
||||
),
|
||||
)
|
||||
if compiler.env["CI_NETRC_USERNAME"] != "octocat" {
|
||||
t.Errorf("WithNetrc should set CI_NETRC_USERNAME")
|
||||
}
|
||||
if compiler.env["CI_NETRC_PASSWORD"] != "password" {
|
||||
t.Errorf("WithNetrc should set CI_NETRC_PASSWORD")
|
||||
}
|
||||
if compiler.env["CI_NETRC_MACHINE"] != "github.com" {
|
||||
t.Errorf("WithNetrc should set CI_NETRC_MACHINE")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithProxy(t *testing.T) {
|
||||
// do not execute the test if the host machine sets http proxy
|
||||
// environment variables to avoid interference with other tests.
|
||||
if noProxy != "" || httpProxy != "" || httpsProxy != "" {
|
||||
t.SkipNow()
|
||||
return
|
||||
}
|
||||
|
||||
// alter the default values
|
||||
noProxy = "foo.com"
|
||||
httpProxy = "bar.com"
|
||||
httpsProxy = "baz.com"
|
||||
|
||||
// reset the default values
|
||||
defer func() {
|
||||
noProxy = ""
|
||||
httpProxy = ""
|
||||
httpsProxy = ""
|
||||
}()
|
||||
|
||||
testdata := map[string]string{
|
||||
"no_proxy": noProxy,
|
||||
"NO_PROXY": noProxy,
|
||||
"http_proxy": httpProxy,
|
||||
"HTTP_PROXY": httpProxy,
|
||||
"https_proxy": httpsProxy,
|
||||
"HTTPS_PROXY": httpsProxy,
|
||||
}
|
||||
compiler := New(
|
||||
WithProxy(),
|
||||
)
|
||||
for key, value := range testdata {
|
||||
if compiler.env[key] != value {
|
||||
t.Errorf("WithProxy should set %s=%s", key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithEnviron(t *testing.T) {
|
||||
compiler := New(
|
||||
WithEnviron(
|
||||
map[string]string{
|
||||
"RACK_ENV": "development",
|
||||
"SHOW": "true",
|
||||
},
|
||||
),
|
||||
)
|
||||
if compiler.env["RACK_ENV"] != "development" {
|
||||
t.Errorf("WithEnviron should set RACK_ENV")
|
||||
}
|
||||
if compiler.env["SHOW"] != "true" {
|
||||
t.Errorf("WithEnviron should set SHOW")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetenv(t *testing.T) {
|
||||
defer func() {
|
||||
os.Unsetenv("X_TEST_FOO")
|
||||
os.Unsetenv("x_test_bar")
|
||||
os.Unsetenv("x_test_baz")
|
||||
}()
|
||||
os.Setenv("X_TEST_FOO", "foo")
|
||||
os.Setenv("x_test_bar", "bar")
|
||||
os.Setenv("x_test_baz", "")
|
||||
if getenv("x_test_foo") != "foo" {
|
||||
t.Errorf("Expect X_TEST_FOO=foo")
|
||||
}
|
||||
if getenv("X_TEST_BAR") != "bar" {
|
||||
t.Errorf("Expect x_test_bar=bar")
|
||||
}
|
||||
if getenv("x_test_baz") != "" {
|
||||
t.Errorf("Expect x_test_bar=bar is empty")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithVolumeCacher(t *testing.T) {
|
||||
compiler := New(
|
||||
WithVolumeCacher("/cache"),
|
||||
)
|
||||
cacher, ok := compiler.cacher.(*volumeCacher)
|
||||
if !ok {
|
||||
t.Errorf("Expected volume cacher configured")
|
||||
}
|
||||
if got, want := cacher.base, "/cache"; got != want {
|
||||
t.Errorf("Expected volume cacher with base %s, got %s", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithS3Cacher(t *testing.T) {
|
||||
compiler := New(
|
||||
WithS3Cacher("some-access-key", "some-secret-key", "some-region", "some-bucket"),
|
||||
)
|
||||
cacher, ok := compiler.cacher.(*s3Cacher)
|
||||
if !ok {
|
||||
t.Errorf("Expected s3 cacher configured")
|
||||
}
|
||||
if got, want := cacher.bucket, "some-bucket"; got != want {
|
||||
t.Errorf("Expected s3 cacher with bucket %s, got %s", want, got)
|
||||
}
|
||||
if got, want := cacher.access, "some-access-key"; got != want {
|
||||
t.Errorf("Expected s3 cacher with access key %s, got %s", want, got)
|
||||
}
|
||||
if got, want := cacher.region, "some-region"; got != want {
|
||||
t.Errorf("Expected s3 cacher with region %s, got %s", want, got)
|
||||
}
|
||||
if got, want := cacher.secret, "some-secret-key"; got != want {
|
||||
t.Errorf("Expected s3 cacher with secret key %s, got %s", want, got)
|
||||
}
|
||||
}
|
37
cncd/pipeline/pipeline/frontend/yaml/compiler/params_test.go
Normal file
37
cncd/pipeline/pipeline/frontend/yaml/compiler/params_test.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package compiler
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/kr/pretty"
|
||||
)
|
||||
|
||||
func TestParamsToEnv(t *testing.T) {
|
||||
from := map[string]interface{}{
|
||||
"skip": nil,
|
||||
"string": "stringz",
|
||||
"int": 1,
|
||||
"float": 1.2,
|
||||
"bool": true,
|
||||
"map": map[string]string{"hello": "world"},
|
||||
"slice": []int{1, 2, 3},
|
||||
"complex": []struct{ Name string }{{"Jack"}, {"Jill"}},
|
||||
}
|
||||
want := map[string]string{
|
||||
"PLUGIN_STRING": "stringz",
|
||||
"PLUGIN_INT": "1",
|
||||
"PLUGIN_FLOAT": "1.2",
|
||||
"PLUGIN_BOOL": "true",
|
||||
"PLUGIN_MAP": `{"hello":"world"}`,
|
||||
"PLUGIN_SLICE": "1,2,3",
|
||||
"PLUGIN_COMPLEX": `[{"name":"Jack"},{"name":"Jill"}]`,
|
||||
}
|
||||
got := map[string]string{}
|
||||
paramsToEnv(from, got)
|
||||
|
||||
if !reflect.DeepEqual(want, got) {
|
||||
t.Errorf("Problem converting plugin parameters to environment variables")
|
||||
pretty.Ldiff(t, want, got)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package compiler
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"testing"
|
||||
|
||||
"github.com/kr/pretty"
|
||||
)
|
||||
|
||||
func TestGenerateScriptPosix(t *testing.T) {
|
||||
testdata := []struct {
|
||||
from []string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
from: []string{"echo ${PATH}", "go build", "go test"},
|
||||
want: `
|
||||
if [ -n "$CI_NETRC_MACHINE" ]; then
|
||||
cat <<EOF > $HOME/.netrc
|
||||
machine $CI_NETRC_MACHINE
|
||||
login $CI_NETRC_USERNAME
|
||||
password $CI_NETRC_PASSWORD
|
||||
EOF
|
||||
chmod 0600 $HOME/.netrc
|
||||
fi
|
||||
unset CI_NETRC_USERNAME
|
||||
unset CI_NETRC_PASSWORD
|
||||
unset CI_SCRIPT
|
||||
unset DRONE_NETRC_USERNAME
|
||||
unset DRONE_NETRC_PASSWORD
|
||||
|
||||
echo + "echo \${PATH}"
|
||||
echo ${PATH}
|
||||
|
||||
echo + "go build"
|
||||
go build
|
||||
|
||||
echo + "go test"
|
||||
go test
|
||||
|
||||
`,
|
||||
},
|
||||
}
|
||||
for _, test := range testdata {
|
||||
script := generateScriptPosix(test.from)
|
||||
decoded, _ := base64.StdEncoding.DecodeString(script)
|
||||
got := string(decoded)
|
||||
|
||||
if got != test.want {
|
||||
t.Errorf("Want encoded script for %s", test.from)
|
||||
pretty.Ldiff(t, got, test.want)
|
||||
}
|
||||
}
|
||||
}
|
49
cncd/pipeline/pipeline/frontend/yaml/compiler/script_win.go
Normal file
49
cncd/pipeline/pipeline/frontend/yaml/compiler/script_win.go
Normal file
|
@ -0,0 +1,49 @@
|
|||
package compiler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func generateScriptWindows(commands []string) string {
|
||||
var buf bytes.Buffer
|
||||
for _, command := range commands {
|
||||
escaped := fmt.Sprintf("%q", command)
|
||||
escaped = strings.Replace(escaped, "$", `\$`, -1)
|
||||
buf.WriteString(fmt.Sprintf(
|
||||
traceScriptWin,
|
||||
escaped,
|
||||
command,
|
||||
))
|
||||
}
|
||||
script := fmt.Sprintf(
|
||||
setupScriptWin,
|
||||
buf.String(),
|
||||
)
|
||||
return base64.StdEncoding.EncodeToString([]byte(script))
|
||||
}
|
||||
|
||||
const setupScriptWin = `
|
||||
$ErrorActionPreference = 'Stop';
|
||||
&cmd /c "mkdir c:\root";
|
||||
if ($Env:CI_NETRC_MACHINE) {
|
||||
$netrc=[string]::Format("{0}\_netrc",$Env:HOME);
|
||||
"machine $Env:CI_NETRC_MACHINE" >> $netrc;
|
||||
"login $Env:CI_NETRC_USERNAME" >> $netrc;
|
||||
"password $Env:CI_NETRC_PASSWORD" >> $netrc;
|
||||
};
|
||||
[Environment]::SetEnvironmentVariable("CI_NETRC_PASSWORD",$null);
|
||||
[Environment]::SetEnvironmentVariable("CI_SCRIPT",$null);
|
||||
[Environment]::SetEnvironmentVariable("DRONE_NETRC_USERNAME",$null);
|
||||
[Environment]::SetEnvironmentVariable("DRONE_NETRC_PASSWORD",$null);
|
||||
%s
|
||||
`
|
||||
|
||||
// traceScript is a helper script that is added to the build script
|
||||
// to trace a command.
|
||||
const traceScriptWin = `
|
||||
Write-Output ('+ %s');
|
||||
& %s; if ($LASTEXITCODE -ne 0) {exit $LASTEXITCODE}
|
||||
`
|
|
@ -0,0 +1 @@
|
|||
package compiler
|
108
cncd/pipeline/pipeline/frontend/yaml/config_test.go
Normal file
108
cncd/pipeline/pipeline/frontend/yaml/config_test.go
Normal file
|
@ -0,0 +1,108 @@
|
|||
package yaml
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/libcompose/yaml"
|
||||
"github.com/franela/goblin"
|
||||
)
|
||||
|
||||
func xTestParse(t *testing.T) {
|
||||
g := goblin.Goblin(t)
|
||||
|
||||
g.Describe("Parser", func() {
|
||||
g.Describe("Given a yaml file", func() {
|
||||
|
||||
g.It("Should unmarshal a string", func() {
|
||||
out, err := ParseString(sampleYaml)
|
||||
if err != nil {
|
||||
g.Fail(err)
|
||||
}
|
||||
|
||||
g.Assert(out.Workspace.Base).Equal("/go")
|
||||
g.Assert(out.Workspace.Path).Equal("src/github.com/octocat/hello-world")
|
||||
g.Assert(out.Volumes.Volumes[0].Name).Equal("custom")
|
||||
g.Assert(out.Volumes.Volumes[0].Driver).Equal("blockbridge")
|
||||
g.Assert(out.Networks.Networks[0].Name).Equal("custom")
|
||||
g.Assert(out.Networks.Networks[0].Driver).Equal("overlay")
|
||||
g.Assert(out.Services.Containers[0].Name).Equal("database")
|
||||
g.Assert(out.Services.Containers[0].Image).Equal("mysql")
|
||||
g.Assert(out.Pipeline.Containers[0].Name).Equal("test")
|
||||
g.Assert(out.Pipeline.Containers[0].Image).Equal("golang")
|
||||
g.Assert(out.Pipeline.Containers[0].Commands).Equal(yaml.Stringorslice{"go install", "go test"})
|
||||
g.Assert(out.Pipeline.Containers[1].Name).Equal("build")
|
||||
g.Assert(out.Pipeline.Containers[1].Image).Equal("golang")
|
||||
g.Assert(out.Pipeline.Containers[1].Commands).Equal(yaml.Stringorslice{"go build"})
|
||||
g.Assert(out.Pipeline.Containers[2].Name).Equal("notify")
|
||||
g.Assert(out.Pipeline.Containers[2].Image).Equal("slack")
|
||||
g.Assert(out.Pipeline.Containers[2].NetworkMode).Equal("container:name")
|
||||
g.Assert(out.Labels["com.example.team"]).Equal("frontend")
|
||||
g.Assert(out.Labels["com.example.type"]).Equal("build")
|
||||
})
|
||||
// Check to make sure variable expansion works in yaml.MapSlice
|
||||
// g.It("Should unmarshal variables", func() {
|
||||
// out, err := ParseString(sampleVarYaml)
|
||||
// if err != nil {
|
||||
// g.Fail(err)
|
||||
// }
|
||||
// g.Assert(out.Pipeline[0].Name).Equal("notify_fail")
|
||||
// g.Assert(out.Pipeline[0].Image).Equal("plugins/slack")
|
||||
// g.Assert(len(out.Pipeline[0].Constraints.Event.Include)).Equal(0)
|
||||
// g.Assert(out.Pipeline[1].Name).Equal("notify_success")
|
||||
// g.Assert(out.Pipeline[1].Image).Equal("plugins/slack")
|
||||
// g.Assert(out.Pipeline[1].Constraints.Event.Include).Equal([]string{"success"})
|
||||
// })
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
var sampleYaml = `
|
||||
image: hello-world
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
workspace:
|
||||
path: src/github.com/octocat/hello-world
|
||||
base: /go
|
||||
pipeline:
|
||||
test:
|
||||
image: golang
|
||||
commands:
|
||||
- go install
|
||||
- go test
|
||||
build:
|
||||
image: golang
|
||||
network_mode: container:name
|
||||
commands:
|
||||
- go build
|
||||
when:
|
||||
event: push
|
||||
notify:
|
||||
image: slack
|
||||
channel: dev
|
||||
when:
|
||||
event: failure
|
||||
services:
|
||||
database:
|
||||
image: mysql
|
||||
networks:
|
||||
custom:
|
||||
driver: overlay
|
||||
volumes:
|
||||
custom:
|
||||
driver: blockbridge
|
||||
labels:
|
||||
com.example.type: "build"
|
||||
com.example.team: "frontend"
|
||||
`
|
||||
|
||||
var sampleVarYaml = `
|
||||
_slack: &SLACK
|
||||
image: plugins/slack
|
||||
pipeline:
|
||||
notify_fail: *SLACK
|
||||
notify_success:
|
||||
<< : *SLACK
|
||||
when:
|
||||
event: success
|
||||
`
|
|
@ -3,8 +3,8 @@ package yaml
|
|||
import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/cncd/pipeline/pipeline/frontend"
|
||||
"github.com/cncd/pipeline/pipeline/frontend/yaml/types"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/frontend"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/frontend/yaml/types"
|
||||
libcompose "github.com/docker/libcompose/yaml"
|
||||
)
|
||||
|
373
cncd/pipeline/pipeline/frontend/yaml/constraint_test.go
Normal file
373
cncd/pipeline/pipeline/frontend/yaml/constraint_test.go
Normal file
|
@ -0,0 +1,373 @@
|
|||
package yaml
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/frontend"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func TestConstraint(t *testing.T) {
|
||||
testdata := []struct {
|
||||
conf string
|
||||
with string
|
||||
want bool
|
||||
}{
|
||||
// string value
|
||||
{
|
||||
conf: "master",
|
||||
with: "develop",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
conf: "master",
|
||||
with: "master",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
conf: "feature/*",
|
||||
with: "feature/foo",
|
||||
want: true,
|
||||
},
|
||||
// slice value
|
||||
{
|
||||
conf: "[ master, feature/* ]",
|
||||
with: "develop",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
conf: "[ master, feature/* ]",
|
||||
with: "master",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
conf: "[ master, feature/* ]",
|
||||
with: "feature/foo",
|
||||
want: true,
|
||||
},
|
||||
// includes block
|
||||
{
|
||||
conf: "include: master",
|
||||
with: "develop",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
conf: "include: master",
|
||||
with: "master",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
conf: "include: feature/*",
|
||||
with: "master",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
conf: "include: feature/*",
|
||||
with: "feature/foo",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
conf: "include: [ master, feature/* ]",
|
||||
with: "develop",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
conf: "include: [ master, feature/* ]",
|
||||
with: "master",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
conf: "include: [ master, feature/* ]",
|
||||
with: "feature/foo",
|
||||
want: true,
|
||||
},
|
||||
// excludes block
|
||||
{
|
||||
conf: "exclude: master",
|
||||
with: "develop",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
conf: "exclude: master",
|
||||
with: "master",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
conf: "exclude: feature/*",
|
||||
with: "master",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
conf: "exclude: feature/*",
|
||||
with: "feature/foo",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
conf: "exclude: [ master, develop ]",
|
||||
with: "master",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
conf: "exclude: [ feature/*, bar ]",
|
||||
with: "master",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
conf: "exclude: [ feature/*, bar ]",
|
||||
with: "feature/foo",
|
||||
want: false,
|
||||
},
|
||||
// include and exclude blocks
|
||||
{
|
||||
conf: "{ include: [ master, feature/* ], exclude: [ develop ] }",
|
||||
with: "master",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
conf: "{ include: [ master, feature/* ], exclude: [ feature/bar ] }",
|
||||
with: "feature/bar",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
conf: "{ include: [ master, feature/* ], exclude: [ master, develop ] }",
|
||||
with: "master",
|
||||
want: false,
|
||||
},
|
||||
// empty blocks
|
||||
{
|
||||
conf: "",
|
||||
with: "master",
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, test := range testdata {
|
||||
c := parseConstraint(test.conf)
|
||||
got, want := c.Match(test.with), test.want
|
||||
if got != want {
|
||||
t.Errorf("Expect %q matches %q is %v", test.with, test.conf, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestConstraintMap(t *testing.T) {
|
||||
testdata := []struct {
|
||||
conf string
|
||||
with map[string]string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
conf: "GOLANG: 1.7",
|
||||
with: map[string]string{"GOLANG": "1.7"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
conf: "GOLANG: tip",
|
||||
with: map[string]string{"GOLANG": "1.7"},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
conf: "{ GOLANG: 1.7, REDIS: 3.1 }",
|
||||
with: map[string]string{"GOLANG": "1.7", "REDIS": "3.1", "MYSQL": "5.6"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
conf: "{ GOLANG: 1.7, REDIS: 3.1 }",
|
||||
with: map[string]string{"GOLANG": "1.7", "REDIS": "3.0"},
|
||||
want: false,
|
||||
},
|
||||
// TODO(bradrydzewski) eventually we should enable wildcard matching
|
||||
{
|
||||
conf: "{ GOLANG: 1.7, REDIS: 3.* }",
|
||||
with: map[string]string{"GOLANG": "1.7", "REDIS": "3.0"},
|
||||
want: false,
|
||||
},
|
||||
// include syntax
|
||||
{
|
||||
conf: "include: { GOLANG: 1.7 }",
|
||||
with: map[string]string{"GOLANG": "1.7"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
conf: "include: { GOLANG: tip }",
|
||||
with: map[string]string{"GOLANG": "1.7"},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
conf: "include: { GOLANG: 1.7, REDIS: 3.1 }",
|
||||
with: map[string]string{"GOLANG": "1.7", "REDIS": "3.1", "MYSQL": "5.6"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
conf: "include: { GOLANG: 1.7, REDIS: 3.1 }",
|
||||
with: map[string]string{"GOLANG": "1.7", "REDIS": "3.0"},
|
||||
want: false,
|
||||
},
|
||||
// exclude syntax
|
||||
{
|
||||
conf: "exclude: { GOLANG: 1.7 }",
|
||||
with: map[string]string{"GOLANG": "1.7"},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
conf: "exclude: { GOLANG: tip }",
|
||||
with: map[string]string{"GOLANG": "1.7"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
conf: "exclude: { GOLANG: 1.7, REDIS: 3.1 }",
|
||||
with: map[string]string{"GOLANG": "1.7", "REDIS": "3.1", "MYSQL": "5.6"},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
conf: "exclude: { GOLANG: 1.7, REDIS: 3.1 }",
|
||||
with: map[string]string{"GOLANG": "1.7", "REDIS": "3.0"},
|
||||
want: true,
|
||||
},
|
||||
// exclude AND include values
|
||||
{
|
||||
conf: "{ include: { GOLANG: 1.7 }, exclude: { GOLANG: 1.7 } }",
|
||||
with: map[string]string{"GOLANG": "1.7"},
|
||||
want: false,
|
||||
},
|
||||
// blanks
|
||||
{
|
||||
conf: "",
|
||||
with: map[string]string{"GOLANG": "1.7", "REDIS": "3.0"},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
conf: "GOLANG: 1.7",
|
||||
with: map[string]string{},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
conf: "{ GOLANG: 1.7, REDIS: 3.0 }",
|
||||
with: map[string]string{},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
conf: "include: { GOLANG: 1.7, REDIS: 3.1 }",
|
||||
with: map[string]string{},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
conf: "exclude: { GOLANG: 1.7, REDIS: 3.1 }",
|
||||
with: map[string]string{},
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, test := range testdata {
|
||||
c := parseConstraintMap(test.conf)
|
||||
got, want := c.Match(test.with), test.want
|
||||
if got != want {
|
||||
t.Errorf("Expect %q matches %q is %v", test.with, test.conf, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestConstraints(t *testing.T) {
|
||||
testdata := []struct {
|
||||
conf string
|
||||
with frontend.Metadata
|
||||
want bool
|
||||
}{
|
||||
// no constraints, must match
|
||||
{
|
||||
conf: "",
|
||||
with: frontend.Metadata{},
|
||||
want: true,
|
||||
},
|
||||
// branch constraint
|
||||
{
|
||||
conf: "{ branch: develop }",
|
||||
with: frontend.Metadata{Curr: frontend.Build{Commit: frontend.Commit{Branch: "master"}}},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
conf: "{ branch: master }",
|
||||
with: frontend.Metadata{Curr: frontend.Build{Commit: frontend.Commit{Branch: "master"}}},
|
||||
want: true,
|
||||
},
|
||||
// environment constraint
|
||||
// {
|
||||
// conf: "{ branch: develop }",
|
||||
// with: frontend.Metadata{Curr: frontend.Build{Commit: frontend.Commit{Branch: "master"}}},
|
||||
// want: false,
|
||||
// },
|
||||
// {
|
||||
// conf: "{ branch: master }",
|
||||
// with: frontend.Metadata{Curr: frontend.Build{Commit: frontend.Commit{Branch: "master"}}},
|
||||
// want: true,
|
||||
// },
|
||||
// repo constraint
|
||||
{
|
||||
conf: "{ repo: drone/* }",
|
||||
with: frontend.Metadata{Repo: frontend.Repo{Name: "drone/drone"}},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
conf: "{ repo: octocat/* }",
|
||||
with: frontend.Metadata{Repo: frontend.Repo{Name: "drone/drone"}},
|
||||
want: false,
|
||||
},
|
||||
// ref constraint
|
||||
{
|
||||
conf: "{ ref: refs/tags/* }",
|
||||
with: frontend.Metadata{Curr: frontend.Build{Commit: frontend.Commit{Ref: "refs/tags/v1.0.0"}}},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
conf: "{ ref: refs/tags/* }",
|
||||
with: frontend.Metadata{Curr: frontend.Build{Commit: frontend.Commit{Ref: "refs/heads/master"}}},
|
||||
want: false,
|
||||
},
|
||||
// platform constraint
|
||||
{
|
||||
conf: "{ platform: linux/amd64 }",
|
||||
with: frontend.Metadata{Sys: frontend.System{Arch: "linux/amd64"}},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
conf: "{ repo: linux/amd64 }",
|
||||
with: frontend.Metadata{Sys: frontend.System{Arch: "windows/amd64"}},
|
||||
want: false,
|
||||
},
|
||||
// instance constraint
|
||||
{
|
||||
conf: "{ instance: drone.io }",
|
||||
with: frontend.Metadata{Sys: frontend.System{Host: "drone.io"}},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
conf: "{ instance: drone.io }",
|
||||
with: frontend.Metadata{Sys: frontend.System{Host: "beta.drone.io"}},
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
for _, test := range testdata {
|
||||
c := parseConstraints(test.conf)
|
||||
got, want := c.Match(test.with), test.want
|
||||
if got != want {
|
||||
t.Errorf("Expect %+v matches %q is %v", test.with, test.conf, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func parseConstraints(s string) *Constraints {
|
||||
c := &Constraints{}
|
||||
yaml.Unmarshal([]byte(s), c)
|
||||
return c
|
||||
}
|
||||
|
||||
func parseConstraint(s string) *Constraint {
|
||||
c := &Constraint{}
|
||||
yaml.Unmarshal([]byte(s), c)
|
||||
return c
|
||||
}
|
||||
|
||||
func parseConstraintMap(s string) *ConstraintMap {
|
||||
c := &ConstraintMap{}
|
||||
yaml.Unmarshal([]byte(s), c)
|
||||
return c
|
||||
}
|
187
cncd/pipeline/pipeline/frontend/yaml/container_test.go
Normal file
187
cncd/pipeline/pipeline/frontend/yaml/container_test.go
Normal file
|
@ -0,0 +1,187 @@
|
|||
package yaml
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
libcompose "github.com/docker/libcompose/yaml"
|
||||
"github.com/kr/pretty"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var containerYaml = []byte(`
|
||||
image: golang:latest
|
||||
auth_config:
|
||||
username: janedoe
|
||||
password: password
|
||||
cap_add: [ ALL ]
|
||||
cap_drop: [ NET_ADMIN, SYS_ADMIN ]
|
||||
command: bundle exec thin -p 3000
|
||||
commands:
|
||||
- go build
|
||||
- go test
|
||||
cpu_quota: 11
|
||||
cpuset: 1,2
|
||||
cpu_shares: 99
|
||||
detach: true
|
||||
devices:
|
||||
- /dev/ttyUSB0:/dev/ttyUSB0
|
||||
dns: 8.8.8.8
|
||||
dns_search: example.com
|
||||
entrypoint: /code/entrypoint.sh
|
||||
environment:
|
||||
- RACK_ENV=development
|
||||
- SHOW=true
|
||||
extra_hosts:
|
||||
- somehost:162.242.195.82
|
||||
- otherhost:50.31.209.229
|
||||
isolation: hyperv
|
||||
name: my-build-container
|
||||
network_mode: bridge
|
||||
networks:
|
||||
- some-network
|
||||
- other-network
|
||||
pull: true
|
||||
privileged: true
|
||||
labels:
|
||||
com.example.type: build
|
||||
com.example.team: frontend
|
||||
shm_size: 1kb
|
||||
mem_limit: 1kb
|
||||
memswap_limit: 1kb
|
||||
mem_swappiness: 1kb
|
||||
volumes:
|
||||
- /var/lib/mysql
|
||||
- /opt/data:/var/lib/mysql
|
||||
- /etc/configs:/etc/configs/:ro
|
||||
ulimits:
|
||||
nofile:
|
||||
soft: 20000
|
||||
hard: 40000
|
||||
tmpfs:
|
||||
- /var/lib/test
|
||||
when:
|
||||
branch: master
|
||||
`)
|
||||
|
||||
func TestUnmarshalContainer(t *testing.T) {
|
||||
want := Container{
|
||||
AuthConfig: AuthConfig{
|
||||
Username: "janedoe",
|
||||
Password: "password",
|
||||
},
|
||||
CapAdd: []string{"ALL"},
|
||||
CapDrop: []string{"NET_ADMIN", "SYS_ADMIN"},
|
||||
Command: libcompose.Command{"bundle", "exec", "thin", "-p", "3000"},
|
||||
Commands: libcompose.Stringorslice{"go build", "go test"},
|
||||
CPUQuota: libcompose.StringorInt(11),
|
||||
CPUSet: "1,2",
|
||||
CPUShares: libcompose.StringorInt(99),
|
||||
Detached: true,
|
||||
Devices: []string{"/dev/ttyUSB0:/dev/ttyUSB0"},
|
||||
DNS: libcompose.Stringorslice{"8.8.8.8"},
|
||||
DNSSearch: libcompose.Stringorslice{"example.com"},
|
||||
Entrypoint: libcompose.Command{"/code/entrypoint.sh"},
|
||||
Environment: libcompose.SliceorMap{"RACK_ENV": "development", "SHOW": "true"},
|
||||
ExtraHosts: []string{"somehost:162.242.195.82", "otherhost:50.31.209.229"},
|
||||
Image: "golang:latest",
|
||||
Isolation: "hyperv",
|
||||
Labels: libcompose.SliceorMap{"com.example.type": "build", "com.example.team": "frontend"},
|
||||
MemLimit: libcompose.MemStringorInt(1024),
|
||||
MemSwapLimit: libcompose.MemStringorInt(1024),
|
||||
MemSwappiness: libcompose.MemStringorInt(1024),
|
||||
Name: "my-build-container",
|
||||
Networks: libcompose.Networks{
|
||||
Networks: []*libcompose.Network{
|
||||
{Name: "some-network"},
|
||||
{Name: "other-network"},
|
||||
},
|
||||
},
|
||||
NetworkMode: "bridge",
|
||||
Pull: true,
|
||||
Privileged: true,
|
||||
ShmSize: libcompose.MemStringorInt(1024),
|
||||
Tmpfs: libcompose.Stringorslice{"/var/lib/test"},
|
||||
Ulimits: libcompose.Ulimits{
|
||||
Elements: []libcompose.Ulimit{
|
||||
libcompose.NewUlimit("nofile", 20000, 40000),
|
||||
},
|
||||
},
|
||||
Volumes: libcompose.Volumes{
|
||||
Volumes: []*libcompose.Volume{
|
||||
{Source: "", Destination: "/var/lib/mysql"},
|
||||
{Source: "/opt/data", Destination: "/var/lib/mysql"},
|
||||
{Source: "/etc/configs", Destination: "/etc/configs/", AccessMode: "ro"},
|
||||
},
|
||||
},
|
||||
Constraints: Constraints{
|
||||
Branch: Constraint{
|
||||
Include: []string{"master"},
|
||||
},
|
||||
},
|
||||
}
|
||||
got := Container{}
|
||||
err := yaml.Unmarshal(containerYaml, &got)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(want, got) {
|
||||
t.Errorf("problem parsing container")
|
||||
pretty.Ldiff(t, want, got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestUnmarshalContainersErr unmarshals a map of containers. The order is
|
||||
// retained and the container key may be used as the container name if a
|
||||
// name is not explicitly provided.
|
||||
func TestUnmarshalContainers(t *testing.T) {
|
||||
testdata := []struct {
|
||||
from string
|
||||
want []*Container
|
||||
}{
|
||||
{
|
||||
from: "build: { image: golang }",
|
||||
want: []*Container{
|
||||
{
|
||||
Name: "build",
|
||||
Image: "golang",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
from: "test: { name: unit_test, image: node }",
|
||||
want: []*Container{
|
||||
{
|
||||
Name: "unit_test",
|
||||
Image: "node",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range testdata {
|
||||
in := []byte(test.from)
|
||||
got := Containers{}
|
||||
err := yaml.Unmarshal(in, &got)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(test.want, got.Containers) {
|
||||
t.Errorf("problem parsing containers %q", test.from)
|
||||
pretty.Ldiff(t, test.want, got.Containers)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestUnmarshalContainersErr unmarshals a container map where invalid inputs
|
||||
// are provided to verify error messages are returned.
|
||||
func TestUnmarshalContainersErr(t *testing.T) {
|
||||
testdata := []string{
|
||||
"foo: { name: [ foo, bar] }",
|
||||
"- foo",
|
||||
}
|
||||
for _, test := range testdata {
|
||||
in := []byte(test)
|
||||
err := yaml.Unmarshal(in, new(Containers))
|
||||
if err == nil {
|
||||
t.Errorf("wanted error for containers %q", test)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@ package linter
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cncd/pipeline/pipeline/frontend/yaml"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/frontend/yaml"
|
||||
)
|
||||
|
||||
const (
|
131
cncd/pipeline/pipeline/frontend/yaml/linter/linter_test.go
Normal file
131
cncd/pipeline/pipeline/frontend/yaml/linter/linter_test.go
Normal file
|
@ -0,0 +1,131 @@
|
|||
package linter
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/frontend/yaml"
|
||||
)
|
||||
|
||||
func TestLint(t *testing.T) {
|
||||
testdata := `
|
||||
pipeline:
|
||||
build:
|
||||
image: docker
|
||||
privileged: true
|
||||
network_mode: host
|
||||
volumes:
|
||||
- /tmp:/tmp
|
||||
commands:
|
||||
- go build
|
||||
- go test
|
||||
publish:
|
||||
image: plugins/docker
|
||||
repo: foo/bar
|
||||
services:
|
||||
redis:
|
||||
image: redis
|
||||
entrypoint: [ /bin/redis-server ]
|
||||
command: [ -v ]
|
||||
`
|
||||
|
||||
conf, err := yaml.ParseString(testdata)
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot unmarshal yaml %q. Error: %s", testdata, err)
|
||||
}
|
||||
if err := New(WithTrusted(true)).Lint(conf); err != nil {
|
||||
t.Errorf("Expected lint returns no errors, got %q", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLintErrors(t *testing.T) {
|
||||
testdata := []struct {
|
||||
from string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
from: "",
|
||||
want: "Invalid or missing pipeline section",
|
||||
},
|
||||
{
|
||||
from: "pipeline: { build: { image: '' } }",
|
||||
want: "Invalid or missing image",
|
||||
},
|
||||
{
|
||||
from: "pipeline: { build: { image: golang, privileged: true } }",
|
||||
want: "Insufficient privileges to use privileged mode",
|
||||
},
|
||||
{
|
||||
from: "pipeline: { build: { image: golang, shm_size: 10gb } }",
|
||||
want: "Insufficient privileges to override shm_size",
|
||||
},
|
||||
{
|
||||
from: "pipeline: { build: { image: golang, dns: [ 8.8.8.8 ] } }",
|
||||
want: "Insufficient privileges to use custom dns",
|
||||
},
|
||||
|
||||
{
|
||||
from: "pipeline: { build: { image: golang, dns_search: [ example.com ] } }",
|
||||
want: "Insufficient privileges to use dns_search",
|
||||
},
|
||||
{
|
||||
from: "pipeline: { build: { image: golang, devices: [ '/dev/tty0:/dev/tty0' ] } }",
|
||||
want: "Insufficient privileges to use devices",
|
||||
},
|
||||
{
|
||||
from: "pipeline: { build: { image: golang, extra_hosts: [ 'somehost:162.242.195.82' ] } }",
|
||||
want: "Insufficient privileges to use extra_hosts",
|
||||
},
|
||||
{
|
||||
from: "pipeline: { build: { image: golang, network_mode: host } }",
|
||||
want: "Insufficient privileges to use network_mode",
|
||||
},
|
||||
{
|
||||
from: "pipeline: { build: { image: golang, networks: [ outside, default ] } }",
|
||||
want: "Insufficient privileges to use networks",
|
||||
},
|
||||
{
|
||||
from: "pipeline: { build: { image: golang, volumes: [ '/opt/data:/var/lib/mysql' ] } }",
|
||||
want: "Insufficient privileges to use volumes",
|
||||
},
|
||||
{
|
||||
from: "pipeline: { build: { image: golang, network_mode: 'container:name' } }",
|
||||
want: "Insufficient privileges to use network_mode",
|
||||
},
|
||||
{
|
||||
from: "pipeline: { build: { image: golang, sysctls: [ net.core.somaxconn=1024 ] } }",
|
||||
want: "Insufficient privileges to use sysctls",
|
||||
},
|
||||
// cannot override entypoint, command for script steps
|
||||
{
|
||||
from: "pipeline: { build: { image: golang, commands: [ 'go build' ], entrypoint: [ '/bin/bash' ] } }",
|
||||
want: "Cannot override container entrypoint",
|
||||
},
|
||||
{
|
||||
from: "pipeline: { build: { image: golang, commands: [ 'go build' ], command: [ '/bin/bash' ] } }",
|
||||
want: "Cannot override container command",
|
||||
},
|
||||
// cannot override entypoint, command for plugin steps
|
||||
{
|
||||
from: "pipeline: { publish: { image: plugins/docker, repo: foo/bar, entrypoint: [ '/bin/bash' ] } }",
|
||||
want: "Cannot override container entrypoint",
|
||||
},
|
||||
{
|
||||
from: "pipeline: { publish: { image: plugins/docker, repo: foo/bar, command: [ '/bin/bash' ] } }",
|
||||
want: "Cannot override container command",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testdata {
|
||||
conf, err := yaml.ParseString(test.from)
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot unmarshal yaml %q. Error: %s", test.from, err)
|
||||
}
|
||||
|
||||
lerr := New().Lint(conf)
|
||||
if lerr == nil {
|
||||
t.Errorf("Expected lint error for configuration %q", test.from)
|
||||
} else if lerr.Error() != test.want {
|
||||
t.Errorf("Want error %q, got %q", test.want, lerr.Error())
|
||||
}
|
||||
}
|
||||
}
|
70
cncd/pipeline/pipeline/frontend/yaml/matrix/matrix_test.go
Normal file
70
cncd/pipeline/pipeline/frontend/yaml/matrix/matrix_test.go
Normal file
|
@ -0,0 +1,70 @@
|
|||
package matrix
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/franela/goblin"
|
||||
)
|
||||
|
||||
func TestMatrix(t *testing.T) {
|
||||
|
||||
g := goblin.Goblin(t)
|
||||
g.Describe("Calculate matrix", func() {
|
||||
|
||||
axis, _ := ParseString(fakeMatrix)
|
||||
|
||||
g.It("Should calculate permutations", func() {
|
||||
g.Assert(len(axis)).Equal(24)
|
||||
})
|
||||
|
||||
g.It("Should not duplicate permutations", func() {
|
||||
set := map[string]bool{}
|
||||
for _, perm := range axis {
|
||||
set[perm.String()] = true
|
||||
}
|
||||
g.Assert(len(set)).Equal(24)
|
||||
})
|
||||
|
||||
g.It("Should return nil if no matrix", func() {
|
||||
axis, err := ParseString("")
|
||||
g.Assert(err == nil).IsTrue()
|
||||
g.Assert(axis == nil).IsTrue()
|
||||
})
|
||||
|
||||
g.It("Should return included axis", func() {
|
||||
axis, err := ParseString(fakeMatrixInclude)
|
||||
g.Assert(err == nil).IsTrue()
|
||||
g.Assert(len(axis)).Equal(2)
|
||||
g.Assert(axis[0]["go_version"]).Equal("1.5")
|
||||
g.Assert(axis[1]["go_version"]).Equal("1.6")
|
||||
g.Assert(axis[0]["python_version"]).Equal("3.4")
|
||||
g.Assert(axis[1]["python_version"]).Equal("3.4")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
var fakeMatrix = `
|
||||
matrix:
|
||||
go_version:
|
||||
- go1
|
||||
- go1.2
|
||||
python_version:
|
||||
- 3.2
|
||||
- 3.3
|
||||
django_version:
|
||||
- 1.7
|
||||
- 1.7.1
|
||||
- 1.7.2
|
||||
redis_version:
|
||||
- 2.6
|
||||
- 2.8
|
||||
`
|
||||
|
||||
var fakeMatrixInclude = `
|
||||
matrix:
|
||||
include:
|
||||
- go_version: 1.5
|
||||
python_version: 3.4
|
||||
- go_version: 1.6
|
||||
python_version: 3.4
|
||||
`
|
108
cncd/pipeline/pipeline/frontend/yaml/network_test.go
Normal file
108
cncd/pipeline/pipeline/frontend/yaml/network_test.go
Normal file
|
@ -0,0 +1,108 @@
|
|||
package yaml
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/kr/pretty"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func TestUnmarshalNetwork(t *testing.T) {
|
||||
testdata := []struct {
|
||||
from string
|
||||
want Network
|
||||
}{
|
||||
{
|
||||
from: "{ name: foo, driver: bar }",
|
||||
want: Network{
|
||||
Name: "foo",
|
||||
Driver: "bar",
|
||||
},
|
||||
},
|
||||
{
|
||||
from: "{ name: foo, driver: bar, driver_opts: { baz: qux } }",
|
||||
want: Network{
|
||||
Name: "foo",
|
||||
Driver: "bar",
|
||||
DriverOpts: map[string]string{
|
||||
"baz": "qux",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testdata {
|
||||
in := []byte(test.from)
|
||||
got := Network{}
|
||||
err := yaml.Unmarshal(in, &got)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(test.want, got) {
|
||||
t.Errorf("problem parsing network %q", test.from)
|
||||
pretty.Ldiff(t, test.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalNetworks(t *testing.T) {
|
||||
testdata := []struct {
|
||||
from string
|
||||
want []*Network
|
||||
}{
|
||||
{
|
||||
from: "foo: { driver: bar }",
|
||||
want: []*Network{
|
||||
{
|
||||
Name: "foo",
|
||||
Driver: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
from: "foo: { name: baz }",
|
||||
want: []*Network{
|
||||
{
|
||||
Name: "baz",
|
||||
Driver: "bridge",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
from: "foo: { name: baz, driver: bar }",
|
||||
want: []*Network{
|
||||
{
|
||||
Name: "baz",
|
||||
Driver: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testdata {
|
||||
in := []byte(test.from)
|
||||
got := Networks{}
|
||||
err := yaml.Unmarshal(in, &got)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(test.want, got.Networks) {
|
||||
t.Errorf("problem parsing network %q", test.from)
|
||||
pretty.Ldiff(t, test.want, got.Networks)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalNetworkErr(t *testing.T) {
|
||||
testdata := []string{
|
||||
"foo: { name: [ foo, bar] }",
|
||||
"- foo",
|
||||
}
|
||||
|
||||
for _, test := range testdata {
|
||||
in := []byte(test)
|
||||
err := yaml.Unmarshal(in, new(Networks))
|
||||
if err == nil {
|
||||
t.Errorf("wanted error for networks %q", test)
|
||||
}
|
||||
}
|
||||
}
|
64
cncd/pipeline/pipeline/frontend/yaml/secret_test.go
Normal file
64
cncd/pipeline/pipeline/frontend/yaml/secret_test.go
Normal file
|
@ -0,0 +1,64 @@
|
|||
package yaml
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/kr/pretty"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func TestUnmarshalSecrets(t *testing.T) {
|
||||
testdata := []struct {
|
||||
from string
|
||||
want []*Secret
|
||||
}{
|
||||
{
|
||||
from: "[ mysql_username, mysql_password]",
|
||||
want: []*Secret{
|
||||
{
|
||||
Source: "mysql_username",
|
||||
Target: "mysql_username",
|
||||
},
|
||||
{
|
||||
Source: "mysql_password",
|
||||
Target: "mysql_password",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
from: "[ { source: mysql_prod_username, target: mysql_username } ]",
|
||||
want: []*Secret{
|
||||
{
|
||||
Source: "mysql_prod_username",
|
||||
Target: "mysql_username",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
from: "[ { source: mysql_prod_username, target: mysql_username }, { source: redis_username, target: redis_username } ]",
|
||||
want: []*Secret{
|
||||
{
|
||||
Source: "mysql_prod_username",
|
||||
Target: "mysql_username",
|
||||
},
|
||||
{
|
||||
Source: "redis_username",
|
||||
Target: "redis_username",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testdata {
|
||||
in := []byte(test.from)
|
||||
got := Secrets{}
|
||||
err := yaml.Unmarshal(in, &got)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(test.want, got.Secrets) {
|
||||
t.Errorf("problem parsing secrets %q", test.from)
|
||||
pretty.Ldiff(t, test.want, got.Secrets)
|
||||
}
|
||||
}
|
||||
}
|
54
cncd/pipeline/pipeline/frontend/yaml/types/bool_test.go
Normal file
54
cncd/pipeline/pipeline/frontend/yaml/types/bool_test.go
Normal file
|
@ -0,0 +1,54 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/franela/goblin"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func TestBoolTrue(t *testing.T) {
|
||||
g := goblin.Goblin(t)
|
||||
|
||||
g.Describe("Yaml bool type", func() {
|
||||
g.Describe("given a yaml file", func() {
|
||||
|
||||
g.It("should unmarshal true", func() {
|
||||
in := []byte("true")
|
||||
out := BoolTrue{}
|
||||
err := yaml.Unmarshal(in, &out)
|
||||
if err != nil {
|
||||
g.Fail(err)
|
||||
}
|
||||
g.Assert(out.Bool()).Equal(true)
|
||||
})
|
||||
|
||||
g.It("should unmarshal false", func() {
|
||||
in := []byte("false")
|
||||
out := BoolTrue{}
|
||||
err := yaml.Unmarshal(in, &out)
|
||||
if err != nil {
|
||||
g.Fail(err)
|
||||
}
|
||||
g.Assert(out.Bool()).Equal(false)
|
||||
})
|
||||
|
||||
g.It("should unmarshal true when empty", func() {
|
||||
in := []byte("")
|
||||
out := BoolTrue{}
|
||||
err := yaml.Unmarshal(in, &out)
|
||||
if err != nil {
|
||||
g.Fail(err)
|
||||
}
|
||||
g.Assert(out.Bool()).Equal(true)
|
||||
})
|
||||
|
||||
g.It("should throw error when invalid", func() {
|
||||
in := []byte("{ }") // string value should fail parse
|
||||
out := BoolTrue{}
|
||||
err := yaml.Unmarshal(in, &out)
|
||||
g.Assert(err != nil).IsTrue("expects error")
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
108
cncd/pipeline/pipeline/frontend/yaml/volume_test.go
Normal file
108
cncd/pipeline/pipeline/frontend/yaml/volume_test.go
Normal file
|
@ -0,0 +1,108 @@
|
|||
package yaml
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/kr/pretty"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func TestUnmarshalVolume(t *testing.T) {
|
||||
testdata := []struct {
|
||||
from string
|
||||
want Volume
|
||||
}{
|
||||
{
|
||||
from: "{ name: foo, driver: bar }",
|
||||
want: Volume{
|
||||
Name: "foo",
|
||||
Driver: "bar",
|
||||
},
|
||||
},
|
||||
{
|
||||
from: "{ name: foo, driver: bar, driver_opts: { baz: qux } }",
|
||||
want: Volume{
|
||||
Name: "foo",
|
||||
Driver: "bar",
|
||||
DriverOpts: map[string]string{
|
||||
"baz": "qux",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testdata {
|
||||
in := []byte(test.from)
|
||||
got := Volume{}
|
||||
err := yaml.Unmarshal(in, &got)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(test.want, got) {
|
||||
t.Errorf("problem parsing volume %q", test.from)
|
||||
pretty.Ldiff(t, test.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalVolumes(t *testing.T) {
|
||||
testdata := []struct {
|
||||
from string
|
||||
want []*Volume
|
||||
}{
|
||||
{
|
||||
from: "foo: { driver: bar }",
|
||||
want: []*Volume{
|
||||
{
|
||||
Name: "foo",
|
||||
Driver: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
from: "foo: { name: baz }",
|
||||
want: []*Volume{
|
||||
{
|
||||
Name: "baz",
|
||||
Driver: "local",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
from: "foo: { name: baz, driver: bar }",
|
||||
want: []*Volume{
|
||||
{
|
||||
Name: "baz",
|
||||
Driver: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testdata {
|
||||
in := []byte(test.from)
|
||||
got := Volumes{}
|
||||
err := yaml.Unmarshal(in, &got)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(test.want, got.Volumes) {
|
||||
t.Errorf("problem parsing volumes %q", test.from)
|
||||
pretty.Ldiff(t, test.want, got.Volumes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalVolumesErr(t *testing.T) {
|
||||
testdata := []string{
|
||||
"foo: { name: [ foo, bar] }",
|
||||
"- foo",
|
||||
}
|
||||
|
||||
for _, test := range testdata {
|
||||
in := []byte(test)
|
||||
err := yaml.Unmarshal(in, new(Volumes))
|
||||
if err == nil {
|
||||
t.Errorf("wanted error for volumes %q", test)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
package pipeline
|
||||
|
||||
import (
|
||||
"github.com/cncd/pipeline/pipeline/backend"
|
||||
"github.com/cncd/pipeline/pipeline/multipart"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/backend"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/multipart"
|
||||
)
|
||||
|
||||
// Logger handles the process logging.
|
1
cncd/pipeline/pipeline/multipart/analysis/doc.go
Normal file
1
cncd/pipeline/pipeline/multipart/analysis/doc.go
Normal file
|
@ -0,0 +1 @@
|
|||
package analysis
|
58
cncd/pipeline/pipeline/multipart/coverage/coverage.go
Normal file
58
cncd/pipeline/pipeline/multipart/coverage/coverage.go
Normal file
|
@ -0,0 +1,58 @@
|
|||
package coverage
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"mime/multipart"
|
||||
"net/textproto"
|
||||
)
|
||||
|
||||
// MimeType used by coverage reports.
|
||||
const MimeType = "application/json+coverage"
|
||||
|
||||
type (
|
||||
// Report represents a coverage report.
|
||||
Report struct {
|
||||
Timestamp int64 `json:"timestmp,omitempty"`
|
||||
Command string `json:"command_name,omitempty"`
|
||||
Files []File `json:"files"`
|
||||
Metrics Metrics `json:"metrics"`
|
||||
}
|
||||
|
||||
// File represents a coverage report for a single file.
|
||||
File struct {
|
||||
Name string `json:"filename"`
|
||||
Digest string `json:"checksum,omitempty"`
|
||||
Coverage []*int `json:"coverage"`
|
||||
Covered float64 `json:"covered_percent,omitempty"`
|
||||
CoveredStrength float64 `json:"covered_strength,omitempty"`
|
||||
CoveredLines int `json:"covered_lines,omitempty"`
|
||||
TotalLines int `json:"lines_of_code"`
|
||||
}
|
||||
|
||||
// Metrics represents total coverage metrics for all files.
|
||||
Metrics struct {
|
||||
Covered float64 `json:"covered_percent"`
|
||||
CoveredStrength float64 `json:"covered_strength"`
|
||||
CoveredLines int `json:"covered_lines"`
|
||||
TotalLines int `json:"total_lines"`
|
||||
}
|
||||
)
|
||||
|
||||
// WriteTo writes the report to multipart.Writer w.
|
||||
func (r *Report) WriteTo(w *multipart.Writer) error {
|
||||
header := textproto.MIMEHeader{}
|
||||
header.Set("Content-Type", MimeType)
|
||||
header.Set("X-Covered", fmt.Sprintf("%.2f", r.Metrics.Covered))
|
||||
header.Set("X-Covered-Lines", strconv.Itoa(r.Metrics.CoveredLines))
|
||||
header.Set("X-Total-Lines", strconv.Itoa(r.Metrics.TotalLines))
|
||||
part, err := w.CreatePart(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
encoder := json.NewEncoder(part)
|
||||
encoder.SetIndent("", " ")
|
||||
return encoder.Encode(r)
|
||||
}
|
1
cncd/pipeline/pipeline/multipart/coverage/doc.go
Normal file
1
cncd/pipeline/pipeline/multipart/coverage/doc.go
Normal file
|
@ -0,0 +1 @@
|
|||
package coverage
|
76
cncd/pipeline/pipeline/multipart/reader_test.go
Normal file
76
cncd/pipeline/pipeline/multipart/reader_test.go
Normal file
|
@ -0,0 +1,76 @@
|
|||
package multipart
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReader(t *testing.T) {
|
||||
b := bytes.NewBufferString(sample)
|
||||
m := New(b)
|
||||
|
||||
part, err := m.NextPart()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
header := part.Header()
|
||||
if got, want := header.Get("Content-Type"), "text/plain"; got != want {
|
||||
t.Errorf("Want Content-Type %q, got %q", want, got)
|
||||
}
|
||||
body, err := ioutil.ReadAll(part)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if got, want := string(body), sampleTextPlain; got != want {
|
||||
t.Errorf("Want body %q, got %q", want, got)
|
||||
}
|
||||
|
||||
part, err = m.NextPart()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
header = part.Header()
|
||||
if got, want := header.Get("Content-Type"), "application/json+coverage"; got != want {
|
||||
t.Errorf("Want Content-Type %q, got %q", want, got)
|
||||
}
|
||||
if got, want := header.Get("X-Covered"), "96.00"; got != want {
|
||||
t.Errorf("Want X-Covered %q, got %q", want, got)
|
||||
}
|
||||
if got, want := header.Get("X-Covered-Lines"), "96"; got != want {
|
||||
t.Errorf("Want X-Covered-Lines %q, got %q", want, got)
|
||||
}
|
||||
if got, want := header.Get("X-Total-Lines"), "100"; got != want {
|
||||
t.Errorf("Want X-Total-Lines %q, got %q", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
var sample = `PIPELINE
|
||||
Content-Type: multipart/mixed; boundary=boundary
|
||||
|
||||
--boundary
|
||||
Content-Type: text/plain
|
||||
|
||||
match: pipeline/frontend/yaml/compiler/coverage.out
|
||||
match: pipeline/frontend/yaml/coverage.out
|
||||
match: pipeline/frontend/yaml/linter/coverage.out
|
||||
|
||||
--boundary
|
||||
Content-Type: application/json+coverage
|
||||
X-Covered: 96.00
|
||||
X-Covered-Lines: 96
|
||||
X-Total-Lines: 100
|
||||
|
||||
{"metrics":{"covered_lines":96,"total_lines":100}}
|
||||
|
||||
--boundary--
|
||||
`
|
||||
|
||||
var sampleTextPlain = `match: pipeline/frontend/yaml/compiler/coverage.out
|
||||
match: pipeline/frontend/yaml/coverage.out
|
||||
match: pipeline/frontend/yaml/linter/coverage.out
|
||||
`
|
1
cncd/pipeline/pipeline/multipart/selenium/doc.go
Normal file
1
cncd/pipeline/pipeline/multipart/selenium/doc.go
Normal file
|
@ -0,0 +1 @@
|
|||
package selenium
|
1
cncd/pipeline/pipeline/multipart/terminal/doc.go
Normal file
1
cncd/pipeline/pipeline/multipart/terminal/doc.go
Normal file
|
@ -0,0 +1 @@
|
|||
package terminal
|
|
@ -3,7 +3,7 @@ package pipeline
|
|||
import (
|
||||
"context"
|
||||
|
||||
"github.com/cncd/pipeline/pipeline/backend"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/backend"
|
||||
)
|
||||
|
||||
// Option configures a runtime option.
|
1
cncd/pipeline/pipeline/option_test.go
Normal file
1
cncd/pipeline/pipeline/option_test.go
Normal file
|
@ -0,0 +1 @@
|
|||
package pipeline
|
|
@ -6,7 +6,7 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/cncd/pipeline/pipeline/backend"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/backend"
|
||||
)
|
||||
|
||||
// Parse parses the pipeline config from an io.Reader.
|
1
cncd/pipeline/pipeline/parse_test.go
Normal file
1
cncd/pipeline/pipeline/parse_test.go
Normal file
|
@ -0,0 +1 @@
|
|||
package pipeline
|
|
@ -6,8 +6,8 @@ import (
|
|||
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/cncd/pipeline/pipeline/backend"
|
||||
"github.com/cncd/pipeline/pipeline/multipart"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/backend"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/multipart"
|
||||
)
|
||||
|
||||
type (
|
|
@ -6,8 +6,8 @@ import (
|
|||
"time"
|
||||
"log"
|
||||
|
||||
"github.com/cncd/pipeline/pipeline/backend"
|
||||
"github.com/cncd/pipeline/pipeline/rpc/proto"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/backend"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/rpc/proto"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
|
@ -5,8 +5,8 @@ import (
|
|||
// "encoding/json"
|
||||
"time"
|
||||
|
||||
// "github.com/cncd/pipeline/pipeline/backend"
|
||||
"github.com/cncd/pipeline/pipeline/rpc/proto"
|
||||
// "github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/backend"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/rpc/proto"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
1
cncd/pipeline/pipeline/rpc/client_test.go
Normal file
1
cncd/pipeline/pipeline/rpc/client_test.go
Normal file
|
@ -0,0 +1 @@
|
|||
package rpc
|
18
cncd/pipeline/pipeline/rpc/line_test.go
Normal file
18
cncd/pipeline/pipeline/rpc/line_test.go
Normal file
|
@ -0,0 +1,18 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLine(t *testing.T) {
|
||||
line := Line{
|
||||
Proc: "redis",
|
||||
Time: 60,
|
||||
Pos: 1,
|
||||
Out: "starting redis server",
|
||||
}
|
||||
got, want := line.String(), "[redis:L1:60s] starting redis server"
|
||||
if got != want {
|
||||
t.Errorf("Wanted line string %q, got %q", want, got)
|
||||
}
|
||||
}
|
1
cncd/pipeline/pipeline/rpc/option_test.go
Normal file
1
cncd/pipeline/pipeline/rpc/option_test.go
Normal file
|
@ -0,0 +1 @@
|
|||
package rpc
|
|
@ -3,7 +3,7 @@ package rpc
|
|||
import (
|
||||
"context"
|
||||
|
||||
"github.com/cncd/pipeline/pipeline/backend"
|
||||
"github.com/laszlocph/drone-oss-08/cncd/pipeline/pipeline/backend"
|
||||
)
|
||||
|
||||
// ErrCancelled signals the pipeine is cancelled.
|
1
cncd/pipeline/pipeline/rpc/server_test.go
Normal file
1
cncd/pipeline/pipeline/rpc/server_test.go
Normal file
|
@ -0,0 +1 @@
|
|||
package rpc
|
11
cncd/pipeline/samples/sample_1/README.md
Normal file
11
cncd/pipeline/samples/sample_1/README.md
Normal file
|
@ -0,0 +1,11 @@
|
|||
Compile the yaml to the intermediate representation:
|
||||
|
||||
```
|
||||
pipec compile
|
||||
```
|
||||
|
||||
Execute the intermediate representation:
|
||||
|
||||
```
|
||||
pipec exec
|
||||
```
|
159
cncd/pipeline/samples/sample_1/pipeline.json
Normal file
159
cncd/pipeline/samples/sample_1/pipeline.json
Normal file
|
@ -0,0 +1,159 @@
|
|||
{
|
||||
"pipeline": [
|
||||
{
|
||||
"name": "pipeline_clone_0",
|
||||
"alias": "git",
|
||||
"steps": [
|
||||
{
|
||||
"name": "pipeline_clone_0",
|
||||
"alias": "git",
|
||||
"image": "plugins/git:latest",
|
||||
"working_dir": "/go/src/github.com/drone/envsubst",
|
||||
"environment": {
|
||||
"CI": "pipec",
|
||||
"CI_BUILD_CREATED": "1486119586",
|
||||
"CI_BUILD_EVENT": "push",
|
||||
"CI_BUILD_NUMBER": "6",
|
||||
"CI_BUILD_STARTED": "1486119585",
|
||||
"CI_COMMIT_AUTHOR": "bradrydzewski",
|
||||
"CI_COMMIT_AUTHOR_NAME": "bradrydzewski",
|
||||
"CI_COMMIT_BRANCH": "master",
|
||||
"CI_COMMIT_MESSAGE": "added a few more test cases for escaping behavior",
|
||||
"CI_COMMIT_REF": "refs/heads/master",
|
||||
"CI_COMMIT_SHA": "d0876d3176965f9552a611cbd56e24a9264355e6",
|
||||
"CI_REMOTE_URL": "https://github.com/drone/envsubst.git",
|
||||
"CI_REPO": "drone/envsubst",
|
||||
"CI_REPO_LINK": "https://github.com/drone/envsubst",
|
||||
"CI_REPO_NAME": "drone/envsubst",
|
||||
"CI_REPO_REMOTE": "https://github.com/drone/envsubst.git",
|
||||
"CI_SYSTEM": "pipec",
|
||||
"CI_SYSTEM_ARCH": "linux/amd64",
|
||||
"CI_SYSTEM_LINK": "https://github.com/cncd/pipec",
|
||||
"CI_SYSTEM_NAME": "pipec",
|
||||
"CI_WORKSPACE": "/go/src/github.com/drone/envsubst",
|
||||
"DRONE_BUILD_CREATED": "1486119586",
|
||||
"DRONE_BUILD_EVENT": "push",
|
||||
"DRONE_BUILD_NUMBER": "6",
|
||||
"DRONE_BUILD_STARTED": "1486119585",
|
||||
"DRONE_COMMIT_AUTHOR": "bradrydzewski",
|
||||
"DRONE_COMMIT_AUTHOR_NAME": "bradrydzewski",
|
||||
"DRONE_COMMIT_BRANCH": "master",
|
||||
"DRONE_COMMIT_MESSAGE": "added a few more test cases for escaping behavior",
|
||||
"DRONE_COMMIT_REF": "refs/heads/master",
|
||||
"DRONE_COMMIT_SHA": "d0876d3176965f9552a611cbd56e24a9264355e6",
|
||||
"DRONE_REMOTE_URL": "https://github.com/drone/envsubst.git",
|
||||
"DRONE_REPO": "drone/envsubst",
|
||||
"DRONE_REPO_LINK": "https://github.com/drone/envsubst",
|
||||
"DRONE_REPO_NAME": "drone/envsubst",
|
||||
"DRONE_REPO_REMOTE": "https://github.com/drone/envsubst.git",
|
||||
"DRONE_SYSTEM": "pipec",
|
||||
"DRONE_SYSTEM_ARCH": "linux/amd64",
|
||||
"DRONE_SYSTEM_LINK": "https://github.com/cncd/pipec",
|
||||
"DRONE_SYSTEM_NAME": "pipec",
|
||||
"DRONE_WORKSPACE": "/go/src/github.com/drone/envsubst",
|
||||
"PLUGIN_DEPTH": "50"
|
||||
},
|
||||
"volumes": [
|
||||
"pipeline_default:/go"
|
||||
],
|
||||
"networks": [
|
||||
{
|
||||
"name": "pipeline_default",
|
||||
"aliases": null
|
||||
}
|
||||
],
|
||||
"on_success": true,
|
||||
"auth_config": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "pipeline_stage_0",
|
||||
"alias": "build",
|
||||
"steps": [
|
||||
{
|
||||
"name": "pipeline_step_0",
|
||||
"alias": "build",
|
||||
"image": "golang:1.7",
|
||||
"working_dir": "/go/src/github.com/drone/envsubst",
|
||||
"environment": {
|
||||
"CI": "pipec",
|
||||
"CI_BUILD_CREATED": "1486119586",
|
||||
"CI_BUILD_EVENT": "push",
|
||||
"CI_BUILD_NUMBER": "6",
|
||||
"CI_BUILD_STARTED": "1486119585",
|
||||
"CI_COMMIT_AUTHOR": "bradrydzewski",
|
||||
"CI_COMMIT_AUTHOR_NAME": "bradrydzewski",
|
||||
"CI_COMMIT_BRANCH": "master",
|
||||
"CI_COMMIT_MESSAGE": "added a few more test cases for escaping behavior",
|
||||
"CI_COMMIT_REF": "refs/heads/master",
|
||||
"CI_COMMIT_SHA": "d0876d3176965f9552a611cbd56e24a9264355e6",
|
||||
"CI_REMOTE_URL": "https://github.com/drone/envsubst.git",
|
||||
"CI_REPO": "drone/envsubst",
|
||||
"CI_REPO_LINK": "https://github.com/drone/envsubst",
|
||||
"CI_REPO_NAME": "drone/envsubst",
|
||||
"CI_REPO_REMOTE": "https://github.com/drone/envsubst.git",
|
||||
"CI_SCRIPT": "CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVAoKZWNobyArICJnbyBnZXQgLXQgLi8uLi4iCmdvIGdldCAtdCAuLy4uLgoKZWNobyArICJnbyBidWlsZCIKZ28gYnVpbGQKCmVjaG8gKyAiZ28gdGVzdCAtdiIKZ28gdGVzdCAtdgoK",
|
||||
"CI_SYSTEM": "pipec",
|
||||
"CI_SYSTEM_ARCH": "linux/amd64",
|
||||
"CI_SYSTEM_LINK": "https://github.com/cncd/pipec",
|
||||
"CI_SYSTEM_NAME": "pipec",
|
||||
"CI_WORKSPACE": "/go/src/github.com/drone/envsubst",
|
||||
"DRONE_BUILD_CREATED": "1486119586",
|
||||
"DRONE_BUILD_EVENT": "push",
|
||||
"DRONE_BUILD_NUMBER": "6",
|
||||
"DRONE_BUILD_STARTED": "1486119585",
|
||||
"DRONE_COMMIT_AUTHOR": "bradrydzewski",
|
||||
"DRONE_COMMIT_AUTHOR_NAME": "bradrydzewski",
|
||||
"DRONE_COMMIT_BRANCH": "master",
|
||||
"DRONE_COMMIT_MESSAGE": "added a few more test cases for escaping behavior",
|
||||
"DRONE_COMMIT_REF": "refs/heads/master",
|
||||
"DRONE_COMMIT_SHA": "d0876d3176965f9552a611cbd56e24a9264355e6",
|
||||
"DRONE_REMOTE_URL": "https://github.com/drone/envsubst.git",
|
||||
"DRONE_REPO": "drone/envsubst",
|
||||
"DRONE_REPO_LINK": "https://github.com/drone/envsubst",
|
||||
"DRONE_REPO_NAME": "drone/envsubst",
|
||||
"DRONE_REPO_REMOTE": "https://github.com/drone/envsubst.git",
|
||||
"DRONE_SYSTEM": "pipec",
|
||||
"DRONE_SYSTEM_ARCH": "linux/amd64",
|
||||
"DRONE_SYSTEM_LINK": "https://github.com/cncd/pipec",
|
||||
"DRONE_SYSTEM_NAME": "pipec",
|
||||
"DRONE_WORKSPACE": "/go/src/github.com/drone/envsubst",
|
||||
"HOME": "/root",
|
||||
"SHELL": "/bin/sh"
|
||||
},
|
||||
"entrypoint": [
|
||||
"/bin/sh",
|
||||
"-c"
|
||||
],
|
||||
"command": [
|
||||
"echo $CI_SCRIPT | base64 -d | /bin/sh -e"
|
||||
],
|
||||
"volumes": [
|
||||
"pipeline_default:/go"
|
||||
],
|
||||
"networks": [
|
||||
{
|
||||
"name": "pipeline_default",
|
||||
"aliases": null
|
||||
}
|
||||
],
|
||||
"on_success": true,
|
||||
"auth_config": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"networks": [
|
||||
{
|
||||
"name": "pipeline_default",
|
||||
"driver": "bridge"
|
||||
}
|
||||
],
|
||||
"volumes": [
|
||||
{
|
||||
"name": "pipeline_default",
|
||||
"driver": "local"
|
||||
}
|
||||
]
|
||||
}
|
16
cncd/pipeline/samples/sample_1/pipeline.yml
Normal file
16
cncd/pipeline/samples/sample_1/pipeline.yml
Normal file
|
@ -0,0 +1,16 @@
|
|||
workspace:
|
||||
base: /go
|
||||
path: src/github.com/drone/envsubst
|
||||
|
||||
clone:
|
||||
git:
|
||||
image: plugins/git
|
||||
depth: 50
|
||||
|
||||
pipeline:
|
||||
build:
|
||||
image: golang:1.7
|
||||
commands:
|
||||
- go get -t ./...
|
||||
- go build
|
||||
- go test -v
|
11
cncd/pipeline/samples/sample_10_windows/README.md
Normal file
11
cncd/pipeline/samples/sample_10_windows/README.md
Normal file
|
@ -0,0 +1,11 @@
|
|||
Compile the yaml to the intermediate representation:
|
||||
|
||||
```
|
||||
pipec compile --system-arch windows/amd64
|
||||
```
|
||||
|
||||
Execute the intermediate representation:
|
||||
|
||||
```
|
||||
pipec exec
|
||||
```
|
170
cncd/pipeline/samples/sample_10_windows/pipeline.json
Normal file
170
cncd/pipeline/samples/sample_10_windows/pipeline.json
Normal file
|
@ -0,0 +1,170 @@
|
|||
{
|
||||
"pipeline": [
|
||||
{
|
||||
"name": "pipeline_clone_0",
|
||||
"alias": "git",
|
||||
"steps": [
|
||||
{
|
||||
"name": "pipeline_clone_0",
|
||||
"alias": "git",
|
||||
"image": "plugins/git:windows",
|
||||
"working_dir": "c:\\gopath/src\\github.com\\drone\\envsubst",
|
||||
"environment": {
|
||||
"CI": "drone",
|
||||
"CI_BUILD_CREATED": "1486119586",
|
||||
"CI_BUILD_EVENT": "push",
|
||||
"CI_BUILD_NUMBER": "6",
|
||||
"CI_BUILD_STARTED": "1486119585",
|
||||
"CI_COMMIT_AUTHOR": "bradrydzewski",
|
||||
"CI_COMMIT_AUTHOR_NAME": "bradrydzewski",
|
||||
"CI_COMMIT_BRANCH": "master",
|
||||
"CI_COMMIT_MESSAGE": "added a few more test cases for escaping behavior",
|
||||
"CI_COMMIT_REF": "refs/heads/master",
|
||||
"CI_COMMIT_SHA": "d0876d3176965f9552a611cbd56e24a9264355e6",
|
||||
"CI_REMOTE_URL": "https://github.com/drone/envsubst.git",
|
||||
"CI_REPO": "drone/envsubst",
|
||||
"CI_REPO_LINK": "https://github.com/drone/envsubst",
|
||||
"CI_REPO_NAME": "drone/envsubst",
|
||||
"CI_REPO_REMOTE": "https://github.com/drone/envsubst.git",
|
||||
"CI_SYSTEM": "pipec",
|
||||
"CI_SYSTEM_ARCH": "windows/amd64",
|
||||
"CI_SYSTEM_LINK": "https://github.com/cncd/pipec",
|
||||
"CI_SYSTEM_NAME": "pipec",
|
||||
"CI_WORKSPACE": "c:\\gopath/src\\github.com\\drone\\envsubst",
|
||||
"DRONE": "true",
|
||||
"DRONE_ARCH": "windows/amd64",
|
||||
"DRONE_BRANCH": "master",
|
||||
"DRONE_BUILD_CREATED": "1486119586",
|
||||
"DRONE_BUILD_EVENT": "push",
|
||||
"DRONE_BUILD_LINK": "https://github.com/cncd/pipec/drone/envsubst/6",
|
||||
"DRONE_BUILD_NUMBER": "6",
|
||||
"DRONE_BUILD_STARTED": "1486119585",
|
||||
"DRONE_COMMIT": "d0876d3176965f9552a611cbd56e24a9264355e6",
|
||||
"DRONE_COMMIT_AUTHOR": "bradrydzewski",
|
||||
"DRONE_COMMIT_BRANCH": "master",
|
||||
"DRONE_COMMIT_MESSAGE": "added a few more test cases for escaping behavior",
|
||||
"DRONE_COMMIT_REF": "refs/heads/master",
|
||||
"DRONE_COMMIT_SHA": "d0876d3176965f9552a611cbd56e24a9264355e6",
|
||||
"DRONE_JOB_STARTED": "1486119585",
|
||||
"DRONE_REMOTE_URL": "https://github.com/drone/envsubst.git",
|
||||
"DRONE_REPO": "drone/envsubst",
|
||||
"DRONE_REPO_LINK": "https://github.com/drone/envsubst",
|
||||
"DRONE_REPO_NAME": "envsubst",
|
||||
"DRONE_REPO_OWNER": "drone",
|
||||
"DRONE_REPO_SCM": "git",
|
||||
"DRONE_WORKSPACE": "c:\\gopath/src\\github.com\\drone\\envsubst",
|
||||
"PLUGIN_DEPTH": "50"
|
||||
},
|
||||
"volumes": [
|
||||
"pipeline_default:c:\\gopath"
|
||||
],
|
||||
"networks": [
|
||||
{
|
||||
"name": "pipeline_default",
|
||||
"aliases": [
|
||||
"git"
|
||||
]
|
||||
}
|
||||
],
|
||||
"on_success": true,
|
||||
"auth_config": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "pipeline_stage_0",
|
||||
"alias": "build",
|
||||
"steps": [
|
||||
{
|
||||
"name": "pipeline_step_0",
|
||||
"alias": "build",
|
||||
"image": "golang:1.10.1-nanoserver-sac2016",
|
||||
"working_dir": "c:\\gopath/src\\github.com\\drone\\envsubst",
|
||||
"environment": {
|
||||
"CI": "drone",
|
||||
"CI_BUILD_CREATED": "1486119586",
|
||||
"CI_BUILD_EVENT": "push",
|
||||
"CI_BUILD_NUMBER": "6",
|
||||
"CI_BUILD_STARTED": "1486119585",
|
||||
"CI_COMMIT_AUTHOR": "bradrydzewski",
|
||||
"CI_COMMIT_AUTHOR_NAME": "bradrydzewski",
|
||||
"CI_COMMIT_BRANCH": "master",
|
||||
"CI_COMMIT_MESSAGE": "added a few more test cases for escaping behavior",
|
||||
"CI_COMMIT_REF": "refs/heads/master",
|
||||
"CI_COMMIT_SHA": "d0876d3176965f9552a611cbd56e24a9264355e6",
|
||||
"CI_REMOTE_URL": "https://github.com/drone/envsubst.git",
|
||||
"CI_REPO": "drone/envsubst",
|
||||
"CI_REPO_LINK": "https://github.com/drone/envsubst",
|
||||
"CI_REPO_NAME": "drone/envsubst",
|
||||
"CI_REPO_REMOTE": "https://github.com/drone/envsubst.git",
|
||||
"CI_SCRIPT": "CiRFcnJvckFjdGlvblByZWZlcmVuY2UgPSAnU3RvcCc7CiZjbWQgL2MgIm1rZGlyIGM6XHJvb3QiOwppZiAoJEVudjpDSV9ORVRSQ19NQUNISU5FKSB7CiRuZXRyYz1bc3RyaW5nXTo6Rm9ybWF0KCJ7MH1cX25ldHJjIiwkRW52OkhPTUUpOwoibWFjaGluZSAkRW52OkNJX05FVFJDX01BQ0hJTkUiID4+ICRuZXRyYzsKImxvZ2luICRFbnY6Q0lfTkVUUkNfVVNFUk5BTUUiID4+ICRuZXRyYzsKInBhc3N3b3JkICRFbnY6Q0lfTkVUUkNfUEFTU1dPUkQiID4+ICRuZXRyYzsKfTsKW0Vudmlyb25tZW50XTo6U2V0RW52aXJvbm1lbnRWYXJpYWJsZSgiQ0lfTkVUUkNfUEFTU1dPUkQiLCRudWxsKTsKW0Vudmlyb25tZW50XTo6U2V0RW52aXJvbm1lbnRWYXJpYWJsZSgiQ0lfU0NSSVBUIiwkbnVsbCk7CltFbnZpcm9ubWVudF06OlNldEVudmlyb25tZW50VmFyaWFibGUoIkRST05FX05FVFJDX1VTRVJOQU1FIiwkbnVsbCk7CltFbnZpcm9ubWVudF06OlNldEVudmlyb25tZW50VmFyaWFibGUoIkRST05FX05FVFJDX1BBU1NXT1JEIiwkbnVsbCk7CgpXcml0ZS1PdXRwdXQgKCcrICJnbyBnZXQgLXQgLlxcLi4uIicpOyAgW0NvbnNvbGVdOjpPdXQuRmx1c2goKQomIGdvIGdldCAtdCAuXC4uLjsgaWYgKCRMQVNURVhJVENPREUgLW5lIDApIHtleGl0ICRMQVNURVhJVENPREV9CgpXcml0ZS1PdXRwdXQgKCcrICJnbyBidWlsZCInKTsgIFtDb25zb2xlXTo6T3V0LkZsdXNoKCkKJiBnbyBidWlsZDsgaWYgKCRMQVNURVhJVENPREUgLW5lIDApIHtleGl0ICRMQVNURVhJVENPREV9CgpXcml0ZS1PdXRwdXQgKCcrICJnbyB0ZXN0IC12IicpOyAgW0NvbnNvbGVdOjpPdXQuRmx1c2goKQomIGdvIHRlc3QgLXY7IGlmICgkTEFTVEVYSVRDT0RFIC1uZSAwKSB7ZXhpdCAkTEFTVEVYSVRDT0RFfQoK",
|
||||
"CI_SYSTEM": "pipec",
|
||||
"CI_SYSTEM_ARCH": "windows/amd64",
|
||||
"CI_SYSTEM_LINK": "https://github.com/cncd/pipec",
|
||||
"CI_SYSTEM_NAME": "pipec",
|
||||
"CI_WORKSPACE": "c:\\gopath/src\\github.com\\drone\\envsubst",
|
||||
"DRONE": "true",
|
||||
"DRONE_ARCH": "windows/amd64",
|
||||
"DRONE_BRANCH": "master",
|
||||
"DRONE_BUILD_CREATED": "1486119586",
|
||||
"DRONE_BUILD_EVENT": "push",
|
||||
"DRONE_BUILD_LINK": "https://github.com/cncd/pipec/drone/envsubst/6",
|
||||
"DRONE_BUILD_NUMBER": "6",
|
||||
"DRONE_BUILD_STARTED": "1486119585",
|
||||
"DRONE_COMMIT": "d0876d3176965f9552a611cbd56e24a9264355e6",
|
||||
"DRONE_COMMIT_AUTHOR": "bradrydzewski",
|
||||
"DRONE_COMMIT_BRANCH": "master",
|
||||
"DRONE_COMMIT_MESSAGE": "added a few more test cases for escaping behavior",
|
||||
"DRONE_COMMIT_REF": "refs/heads/master",
|
||||
"DRONE_COMMIT_SHA": "d0876d3176965f9552a611cbd56e24a9264355e6",
|
||||
"DRONE_JOB_STARTED": "1486119585",
|
||||
"DRONE_REMOTE_URL": "https://github.com/drone/envsubst.git",
|
||||
"DRONE_REPO": "drone/envsubst",
|
||||
"DRONE_REPO_LINK": "https://github.com/drone/envsubst",
|
||||
"DRONE_REPO_NAME": "envsubst",
|
||||
"DRONE_REPO_OWNER": "drone",
|
||||
"DRONE_REPO_SCM": "git",
|
||||
"DRONE_WORKSPACE": "c:\\gopath/src\\github.com\\drone\\envsubst",
|
||||
"HOME": "c:\\root",
|
||||
"SHELL": "powershell.exe"
|
||||
},
|
||||
"entrypoint": [
|
||||
"powershell",
|
||||
"-noprofile",
|
||||
"-noninteractive",
|
||||
"-command"
|
||||
],
|
||||
"command": [
|
||||
"[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Env:CI_SCRIPT)) | iex"
|
||||
],
|
||||
"volumes": [
|
||||
"pipeline_default:c:\\gopath"
|
||||
],
|
||||
"networks": [
|
||||
{
|
||||
"name": "pipeline_default",
|
||||
"aliases": [
|
||||
"build"
|
||||
]
|
||||
}
|
||||
],
|
||||
"on_success": true,
|
||||
"auth_config": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"networks": [
|
||||
{
|
||||
"name": "pipeline_default",
|
||||
"driver": "nat"
|
||||
}
|
||||
],
|
||||
"volumes": [
|
||||
{
|
||||
"name": "pipeline_default",
|
||||
"driver": "local"
|
||||
}
|
||||
],
|
||||
"secrets": null
|
||||
}
|
18
cncd/pipeline/samples/sample_10_windows/pipeline.yml
Normal file
18
cncd/pipeline/samples/sample_10_windows/pipeline.yml
Normal file
|
@ -0,0 +1,18 @@
|
|||
platform: windows/amd64
|
||||
|
||||
workspace:
|
||||
base: c:\gopath
|
||||
path: src\github.com\drone\envsubst
|
||||
|
||||
clone:
|
||||
git:
|
||||
image: plugins/git:windows
|
||||
depth: 50
|
||||
|
||||
pipeline:
|
||||
build:
|
||||
image: golang:1.10.1-nanoserver-sac2016
|
||||
commands:
|
||||
- go get -t .\...
|
||||
- go build
|
||||
- go test -v
|
231
cncd/pipeline/samples/sample_2/pipeline.json
Normal file
231
cncd/pipeline/samples/sample_2/pipeline.json
Normal file
|
@ -0,0 +1,231 @@
|
|||
{
|
||||
"pipeline": [
|
||||
{
|
||||
"name": "pipeline_clone",
|
||||
"alias": "clone",
|
||||
"steps": [
|
||||
{
|
||||
"name": "pipeline_clone",
|
||||
"image": "plugins/git:latest",
|
||||
"working_dir": "/go/src/github.com/go-sql-driver/mysql",
|
||||
"environment": {
|
||||
"CI": "pipec",
|
||||
"CI_BUILD_CREATED": "1486119586",
|
||||
"CI_BUILD_EVENT": "push",
|
||||
"CI_BUILD_NUMBER": "530",
|
||||
"CI_BUILD_STARTED": "1486119585",
|
||||
"CI_COMMIT_AUTHOR": "egorsmkv",
|
||||
"CI_COMMIT_AUTHOR_NAME": "egorsmkv",
|
||||
"CI_COMMIT_BRANCH": "master",
|
||||
"CI_COMMIT_MESSAGE": "Fix many urls",
|
||||
"CI_COMMIT_REF": "refs/heads/master",
|
||||
"CI_COMMIT_SHA": "2e00b5cd70399450106cec6431c2e2ce3cae5034",
|
||||
"CI_REMOTE_URL": "https://github.com/go-sql-driver/mysql.git",
|
||||
"CI_REPO": "go-sql-driver/mysql",
|
||||
"CI_REPO_LINK": "https://github.com/go-sql-driver/mysql",
|
||||
"CI_REPO_NAME": "go-sql-driver/mysql",
|
||||
"CI_REPO_REMOTE": "https://github.com/go-sql-driver/mysql.git",
|
||||
"CI_SYSTEM": "pipec",
|
||||
"CI_SYSTEM_ARCH": "linux/amd64",
|
||||
"CI_SYSTEM_LINK": "https://github.com/cncd/pipec",
|
||||
"CI_SYSTEM_NAME": "pipec",
|
||||
"CI_WORKSPACE": "/go/src/github.com/go-sql-driver/mysql",
|
||||
"DRONE_BUILD_CREATED": "1486119586",
|
||||
"DRONE_BUILD_EVENT": "push",
|
||||
"DRONE_BUILD_NUMBER": "530",
|
||||
"DRONE_BUILD_STARTED": "1486119585",
|
||||
"DRONE_COMMIT_AUTHOR": "egorsmkv",
|
||||
"DRONE_COMMIT_AUTHOR_NAME": "egorsmkv",
|
||||
"DRONE_COMMIT_BRANCH": "master",
|
||||
"DRONE_COMMIT_MESSAGE": "Fix many urls",
|
||||
"DRONE_COMMIT_REF": "refs/heads/master",
|
||||
"DRONE_COMMIT_SHA": "2e00b5cd70399450106cec6431c2e2ce3cae5034",
|
||||
"DRONE_REMOTE_URL": "https://github.com/go-sql-driver/mysql.git",
|
||||
"DRONE_REPO": "go-sql-driver/mysql",
|
||||
"DRONE_REPO_LINK": "https://github.com/go-sql-driver/mysql",
|
||||
"DRONE_REPO_NAME": "go-sql-driver/mysql",
|
||||
"DRONE_REPO_REMOTE": "https://github.com/go-sql-driver/mysql.git",
|
||||
"DRONE_SYSTEM": "pipec",
|
||||
"DRONE_SYSTEM_ARCH": "linux/amd64",
|
||||
"DRONE_SYSTEM_LINK": "https://github.com/cncd/pipec",
|
||||
"DRONE_SYSTEM_NAME": "pipec",
|
||||
"DRONE_WORKSPACE": "/go/src/github.com/go-sql-driver/mysql",
|
||||
"PLUGIN_DEPTH": "0"
|
||||
},
|
||||
"volumes": [
|
||||
"pipeline_default:/go"
|
||||
],
|
||||
"networks": [
|
||||
{
|
||||
"name": "pipeline_default",
|
||||
"aliases": null
|
||||
}
|
||||
],
|
||||
"on_success": true,
|
||||
"auth_config": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "pipeline_services",
|
||||
"alias": "services",
|
||||
"steps": [
|
||||
{
|
||||
"name": "pipeline_services_0",
|
||||
"alias": "database",
|
||||
"image": "mysql:latest",
|
||||
"detach": true,
|
||||
"environment": {
|
||||
"CI": "pipec",
|
||||
"CI_BUILD_CREATED": "1486119586",
|
||||
"CI_BUILD_EVENT": "push",
|
||||
"CI_BUILD_NUMBER": "530",
|
||||
"CI_BUILD_STARTED": "1486119585",
|
||||
"CI_COMMIT_AUTHOR": "egorsmkv",
|
||||
"CI_COMMIT_AUTHOR_NAME": "egorsmkv",
|
||||
"CI_COMMIT_BRANCH": "master",
|
||||
"CI_COMMIT_MESSAGE": "Fix many urls",
|
||||
"CI_COMMIT_REF": "refs/heads/master",
|
||||
"CI_COMMIT_SHA": "2e00b5cd70399450106cec6431c2e2ce3cae5034",
|
||||
"CI_REMOTE_URL": "https://github.com/go-sql-driver/mysql.git",
|
||||
"CI_REPO": "go-sql-driver/mysql",
|
||||
"CI_REPO_LINK": "https://github.com/go-sql-driver/mysql",
|
||||
"CI_REPO_NAME": "go-sql-driver/mysql",
|
||||
"CI_REPO_REMOTE": "https://github.com/go-sql-driver/mysql.git",
|
||||
"CI_SYSTEM": "pipec",
|
||||
"CI_SYSTEM_ARCH": "linux/amd64",
|
||||
"CI_SYSTEM_LINK": "https://github.com/cncd/pipec",
|
||||
"CI_SYSTEM_NAME": "pipec",
|
||||
"CI_WORKSPACE": "/go/src/github.com/go-sql-driver/mysql",
|
||||
"DRONE_BUILD_CREATED": "1486119586",
|
||||
"DRONE_BUILD_EVENT": "push",
|
||||
"DRONE_BUILD_NUMBER": "530",
|
||||
"DRONE_BUILD_STARTED": "1486119585",
|
||||
"DRONE_COMMIT_AUTHOR": "egorsmkv",
|
||||
"DRONE_COMMIT_AUTHOR_NAME": "egorsmkv",
|
||||
"DRONE_COMMIT_BRANCH": "master",
|
||||
"DRONE_COMMIT_MESSAGE": "Fix many urls",
|
||||
"DRONE_COMMIT_REF": "refs/heads/master",
|
||||
"DRONE_COMMIT_SHA": "2e00b5cd70399450106cec6431c2e2ce3cae5034",
|
||||
"DRONE_REMOTE_URL": "https://github.com/go-sql-driver/mysql.git",
|
||||
"DRONE_REPO": "go-sql-driver/mysql",
|
||||
"DRONE_REPO_LINK": "https://github.com/go-sql-driver/mysql",
|
||||
"DRONE_REPO_NAME": "go-sql-driver/mysql",
|
||||
"DRONE_REPO_REMOTE": "https://github.com/go-sql-driver/mysql.git",
|
||||
"DRONE_SYSTEM": "pipec",
|
||||
"DRONE_SYSTEM_ARCH": "linux/amd64",
|
||||
"DRONE_SYSTEM_LINK": "https://github.com/cncd/pipec",
|
||||
"DRONE_SYSTEM_NAME": "pipec",
|
||||
"DRONE_WORKSPACE": "/go/src/github.com/go-sql-driver/mysql",
|
||||
"MYSQL_ALLOW_EMPTY_PASSWORD": "yes",
|
||||
"MYSQL_DATABASE": "gotest"
|
||||
},
|
||||
"volumes": [
|
||||
"pipeline_default:/go"
|
||||
],
|
||||
"networks": [
|
||||
{
|
||||
"name": "pipeline_default",
|
||||
"aliases": [
|
||||
"database"
|
||||
]
|
||||
}
|
||||
],
|
||||
"on_success": true,
|
||||
"auth_config": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "pipeline_stage_0",
|
||||
"alias": "build",
|
||||
"steps": [
|
||||
{
|
||||
"name": "pipeline_step_0",
|
||||
"alias": "build",
|
||||
"image": "golang:1.7",
|
||||
"working_dir": "/go/src/github.com/go-sql-driver/mysql",
|
||||
"environment": {
|
||||
"CI": "pipec",
|
||||
"CI_BUILD_CREATED": "1486119586",
|
||||
"CI_BUILD_EVENT": "push",
|
||||
"CI_BUILD_NUMBER": "530",
|
||||
"CI_BUILD_STARTED": "1486119585",
|
||||
"CI_COMMIT_AUTHOR": "egorsmkv",
|
||||
"CI_COMMIT_AUTHOR_NAME": "egorsmkv",
|
||||
"CI_COMMIT_BRANCH": "master",
|
||||
"CI_COMMIT_MESSAGE": "Fix many urls",
|
||||
"CI_COMMIT_REF": "refs/heads/master",
|
||||
"CI_COMMIT_SHA": "2e00b5cd70399450106cec6431c2e2ce3cae5034",
|
||||
"CI_REMOTE_URL": "https://github.com/go-sql-driver/mysql.git",
|
||||
"CI_REPO": "go-sql-driver/mysql",
|
||||
"CI_REPO_LINK": "https://github.com/go-sql-driver/mysql",
|
||||
"CI_REPO_NAME": "go-sql-driver/mysql",
|
||||
"CI_REPO_REMOTE": "https://github.com/go-sql-driver/mysql.git",
|
||||
"CI_SCRIPT": "CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVAoKZWNobyArICJzbGVlcCAyMCIKc2xlZXAgMjAKCmVjaG8gKyAiZ28gZ2V0IC12IC10IgpnbyBnZXQgLXYgLXQKCmVjaG8gKyAiZ28gdGVzdCAtdiIKZ28gdGVzdCAtdgoK",
|
||||
"CI_SYSTEM": "pipec",
|
||||
"CI_SYSTEM_ARCH": "linux/amd64",
|
||||
"CI_SYSTEM_LINK": "https://github.com/cncd/pipec",
|
||||
"CI_SYSTEM_NAME": "pipec",
|
||||
"CI_WORKSPACE": "/go/src/github.com/go-sql-driver/mysql",
|
||||
"DRONE_BUILD_CREATED": "1486119586",
|
||||
"DRONE_BUILD_EVENT": "push",
|
||||
"DRONE_BUILD_NUMBER": "530",
|
||||
"DRONE_BUILD_STARTED": "1486119585",
|
||||
"DRONE_COMMIT_AUTHOR": "egorsmkv",
|
||||
"DRONE_COMMIT_AUTHOR_NAME": "egorsmkv",
|
||||
"DRONE_COMMIT_BRANCH": "master",
|
||||
"DRONE_COMMIT_MESSAGE": "Fix many urls",
|
||||
"DRONE_COMMIT_REF": "refs/heads/master",
|
||||
"DRONE_COMMIT_SHA": "2e00b5cd70399450106cec6431c2e2ce3cae5034",
|
||||
"DRONE_REMOTE_URL": "https://github.com/go-sql-driver/mysql.git",
|
||||
"DRONE_REPO": "go-sql-driver/mysql",
|
||||
"DRONE_REPO_LINK": "https://github.com/go-sql-driver/mysql",
|
||||
"DRONE_REPO_NAME": "go-sql-driver/mysql",
|
||||
"DRONE_REPO_REMOTE": "https://github.com/go-sql-driver/mysql.git",
|
||||
"DRONE_SYSTEM": "pipec",
|
||||
"DRONE_SYSTEM_ARCH": "linux/amd64",
|
||||
"DRONE_SYSTEM_LINK": "https://github.com/cncd/pipec",
|
||||
"DRONE_SYSTEM_NAME": "pipec",
|
||||
"DRONE_WORKSPACE": "/go/src/github.com/go-sql-driver/mysql",
|
||||
"HOME": "/root",
|
||||
"MYSQL_TEST_ADDR": "database:3306",
|
||||
"SHELL": "/bin/sh"
|
||||
},
|
||||
"entrypoint": [
|
||||
"/bin/sh",
|
||||
"-c"
|
||||
],
|
||||
"command": [
|
||||
"echo $CI_SCRIPT | base64 -d | /bin/sh -e"
|
||||
],
|
||||
"volumes": [
|
||||
"pipeline_default:/go"
|
||||
],
|
||||
"networks": [
|
||||
{
|
||||
"name": "pipeline_default",
|
||||
"aliases": [
|
||||
"database"
|
||||
]
|
||||
}
|
||||
],
|
||||
"on_success": true,
|
||||
"auth_config": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"networks": [
|
||||
{
|
||||
"name": "pipeline_default",
|
||||
"driver": "bridge"
|
||||
}
|
||||
],
|
||||
"volumes": [
|
||||
{
|
||||
"name": "pipeline_default",
|
||||
"driver": "local"
|
||||
}
|
||||
]
|
||||
}
|
20
cncd/pipeline/samples/sample_2/pipeline.yml
Normal file
20
cncd/pipeline/samples/sample_2/pipeline.yml
Normal file
|
@ -0,0 +1,20 @@
|
|||
workspace:
|
||||
base: /go
|
||||
path: src/github.com/go-sql-driver/mysql
|
||||
|
||||
pipeline:
|
||||
build:
|
||||
image: golang:1.7
|
||||
environment:
|
||||
MYSQL_TEST_ADDR: database:3306
|
||||
commands:
|
||||
- sleep 20
|
||||
- go get -v -t
|
||||
- go test -v
|
||||
|
||||
services:
|
||||
database:
|
||||
image: mysql
|
||||
environment:
|
||||
- MYSQL_DATABASE=gotest
|
||||
- MYSQL_ALLOW_EMPTY_PASSWORD=yes
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue