From 51aa5d03e17d04e07128b443ff20c30a827bafee Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Wed, 28 Nov 2018 00:07:58 +0900 Subject: [PATCH 001/135] Add new task runner --- application/service/runner/task_runner.go | 135 ++++++++++++++++++ .../service/runner/task_runner_test.go | 67 +++++++++ 2 files changed, 202 insertions(+) create mode 100644 application/service/runner/task_runner.go create mode 100644 application/service/runner/task_runner_test.go diff --git a/application/service/runner/task_runner.go b/application/service/runner/task_runner.go new file mode 100644 index 00000000..23f98888 --- /dev/null +++ b/application/service/runner/task_runner.go @@ -0,0 +1,135 @@ +package runner + +import ( + "context" + "github.com/duck8823/duci/application" + "github.com/duck8823/duci/application/semaphore" + "github.com/duck8823/duci/application/service/docker" + "github.com/pkg/errors" +) + +// Tag is a docker tag. +type Tag string + +// Command is docker command. +type Command []string + +// RunOpts is options for docker. +type RunOpts struct { + Tag + Command +} + +// TaskRunner is a interface describes task runner. +type TaskRunner interface { + Run(ctx context.Context, dir string, opts RunOpts) error +} + +// DockerTaskRunner is a implement of TaskRunner with Docker +type DockerTaskRunner struct { + Docker docker.Service + StartFunc []func() + LogFunc []func(docker.Log) + SuccessFunc []func() + ErrFunc []func(error) + TimeoutFunc []func() + FailureFunc []func(error) +} + +// Run task in docker container. +func (r *DockerTaskRunner) Run(ctx context.Context, dir string, opts RunOpts) error { + for _, f := range r.StartFunc { + go f() + } + + errs := make(chan error, 1) + + timeout, cancel := context.WithTimeout(ctx, application.Config.Timeout()) + defer cancel() + + go func() { + semaphore.Acquire() + errs <- r.run(timeout, dir, opts) + semaphore.Release() + }() + + select { + case <-timeout.Done(): + for _, f := range r.TimeoutFunc { + go f() + } + return timeout.Err() + case err := <-errs: + if err == ErrFailure { + for _, f := range r.FailureFunc { + go f(err) + } + } else if err != nil { + for _, f := range r.ErrFunc { + go f(err) + } + } else { + for _, f := range r.SuccessFunc { + go f() + } + } + return err + } +} + +func (r *DockerTaskRunner) run(ctx context.Context, dir string, opts RunOpts) error { + if err := r.dockerBuild(ctx, dir, opts.Tag); err != nil { + return errors.WithStack(err) + } + + conID, err := r.dockerRun(ctx, dir, opts) + if err != nil { + return errors.WithStack(err) + } + + code, err := r.Docker.ExitCode(ctx, conID) + if err != nil { + return errors.WithStack(err) + } + if err := r.Docker.Rm(ctx, conID); err != nil { + return errors.WithStack(err) + } + if code != 0 { + return ErrFailure + } + + return err +} + +func (r *DockerTaskRunner) dockerBuild(ctx context.Context, dir string, tag Tag) error { + tarball, err := createTarball(dir) + if err != nil { + return errors.WithStack(err) + } + defer tarball.Close() + + buildLog, err := r.Docker.Build(ctx, tarball, docker.Tag(tag), dockerfilePath(dir)) + if err != nil { + return errors.WithStack(err) + } + for _, f := range r.LogFunc { + go f(buildLog) + } + return nil +} + +func (r *DockerTaskRunner) dockerRun(ctx context.Context, dir string, opts RunOpts) (docker.ContainerID, error) { + dockerOpts, err := runtimeOpts(dir) + if err != nil { + return "", errors.WithStack(err) + } + + conID, runLog, err := r.Docker.Run(ctx, dockerOpts, docker.Tag(opts.Tag), docker.Command(opts.Command)) + if err != nil { + return conID, errors.WithStack(err) + } + for _, f := range r.LogFunc { + go f(runLog) + } + return conID, nil +} diff --git a/application/service/runner/task_runner_test.go b/application/service/runner/task_runner_test.go new file mode 100644 index 00000000..4ec1bd61 --- /dev/null +++ b/application/service/runner/task_runner_test.go @@ -0,0 +1,67 @@ +package runner_test + +import ( + "context" + "github.com/duck8823/duci/application/service/docker" + "github.com/duck8823/duci/application/service/docker/mock_docker" + "github.com/duck8823/duci/application/service/runner" + . "github.com/golang/mock/gomock" + "github.com/labstack/gommon/random" + "os" + "path" + "testing" +) + +func TestDockerTaskRunner_Run(t *testing.T) { + // given + dir, rmDir := tmpDir(t) + defer rmDir() + + // and + ctrl := NewController(t) + defer ctrl.Finish() + + // and + mockDocker := mock_docker.NewMockService(ctrl) + mockDocker.EXPECT(). + Build(Any(), Any(), Any(), Any()). + Return(&runner.MockBuildLog{}, nil). + Times(1) + mockDocker.EXPECT(). + Run(Any(), Any(), Any(), Any()). + Return(docker.ContainerID(""), &runner.MockJobLog{}, nil). + Times(1) + mockDocker.EXPECT(). + ExitCode(Any(), Any()). + Return(docker.ExitCode(0), nil). + Times(1) + mockDocker.EXPECT(). + Rm(Any(), Any()). + Return(nil). + Times(1) + + // and + sut := &runner.DockerTaskRunner{ + Docker: mockDocker, + } + + // when + err := sut.Run(context.Background(), dir, runner.RunOpts{}) + + // then + if err != nil { + t.Errorf("must not error. but: %+v", err) + } +} + +func tmpDir(t *testing.T) (string, func()) { + tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + if err := os.MkdirAll(tmpDir, 0700); err != nil { + t.Fatalf("error occured: %+v", err) + } + return tmpDir, func() { + if err := os.RemoveAll(tmpDir); err != nil { + t.Fatalf("error occured: %+v", err) + } + } +} From 240d65e936a5093122b9b3a48b5e51bd15132acb Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Thu, 29 Nov 2018 00:03:07 +0900 Subject: [PATCH 002/135] Reduce instance variables --- application/service/runner/task_runner.go | 41 ++++++++--------------- 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/application/service/runner/task_runner.go b/application/service/runner/task_runner.go index 23f98888..c802c727 100644 --- a/application/service/runner/task_runner.go +++ b/application/service/runner/task_runner.go @@ -22,24 +22,21 @@ type RunOpts struct { // TaskRunner is a interface describes task runner. type TaskRunner interface { - Run(ctx context.Context, dir string, opts RunOpts) error + Run(ctx context.Context, dir string, opts RunOptions) error } // DockerTaskRunner is a implement of TaskRunner with Docker type DockerTaskRunner struct { - Docker docker.Service - StartFunc []func() - LogFunc []func(docker.Log) - SuccessFunc []func() - ErrFunc []func(error) - TimeoutFunc []func() - FailureFunc []func(error) + Docker docker.Service + StartFunc []func(context.Context) + LogFunc []func(context.Context, docker.Log) + EndFunc []func(context.Context, error) } // Run task in docker container. -func (r *DockerTaskRunner) Run(ctx context.Context, dir string, opts RunOpts) error { +func (r *DockerTaskRunner) Run(ctx context.Context, dir string, opts RunOptions) error { for _, f := range r.StartFunc { - go f() + go f(ctx) } errs := make(chan error, 1) @@ -55,23 +52,13 @@ func (r *DockerTaskRunner) Run(ctx context.Context, dir string, opts RunOpts) er select { case <-timeout.Done(): - for _, f := range r.TimeoutFunc { - go f() + for _, f := range r.EndFunc { + go f(ctx, timeout.Err()) } return timeout.Err() case err := <-errs: - if err == ErrFailure { - for _, f := range r.FailureFunc { - go f(err) - } - } else if err != nil { - for _, f := range r.ErrFunc { - go f(err) - } - } else { - for _, f := range r.SuccessFunc { - go f() - } + for _, f := range r.EndFunc { + go f(ctx, err) } return err } @@ -113,12 +100,12 @@ func (r *DockerTaskRunner) dockerBuild(ctx context.Context, dir string, tag Tag) return errors.WithStack(err) } for _, f := range r.LogFunc { - go f(buildLog) + go f(ctx, buildLog) } return nil } -func (r *DockerTaskRunner) dockerRun(ctx context.Context, dir string, opts RunOpts) (docker.ContainerID, error) { +func (r *DockerTaskRunner) dockerRun(ctx context.Context, dir string, opts RunOptions) (docker.ContainerID, error) { dockerOpts, err := runtimeOpts(dir) if err != nil { return "", errors.WithStack(err) @@ -129,7 +116,7 @@ func (r *DockerTaskRunner) dockerRun(ctx context.Context, dir string, opts RunOp return conID, errors.WithStack(err) } for _, f := range r.LogFunc { - go f(runLog) + go f(ctx, runLog) } return conID, nil } From 3fd0d1d3f01a923fb6b63399c0c4ea4a15f43ff7 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Thu, 29 Nov 2018 00:03:22 +0900 Subject: [PATCH 003/135] Change type name --- application/service/runner/task_runner.go | 6 +++--- application/service/runner/task_runner_test.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/application/service/runner/task_runner.go b/application/service/runner/task_runner.go index c802c727..8d8e0e11 100644 --- a/application/service/runner/task_runner.go +++ b/application/service/runner/task_runner.go @@ -14,8 +14,8 @@ type Tag string // Command is docker command. type Command []string -// RunOpts is options for docker. -type RunOpts struct { +// RunOptions is options for docker. +type RunOptions struct { Tag Command } @@ -64,7 +64,7 @@ func (r *DockerTaskRunner) Run(ctx context.Context, dir string, opts RunOptions) } } -func (r *DockerTaskRunner) run(ctx context.Context, dir string, opts RunOpts) error { +func (r *DockerTaskRunner) run(ctx context.Context, dir string, opts RunOptions) error { if err := r.dockerBuild(ctx, dir, opts.Tag); err != nil { return errors.WithStack(err) } diff --git a/application/service/runner/task_runner_test.go b/application/service/runner/task_runner_test.go index 4ec1bd61..ae8ec7a4 100644 --- a/application/service/runner/task_runner_test.go +++ b/application/service/runner/task_runner_test.go @@ -46,7 +46,7 @@ func TestDockerTaskRunner_Run(t *testing.T) { } // when - err := sut.Run(context.Background(), dir, runner.RunOpts{}) + err := sut.Run(context.Background(), dir, runner.RunOptions{}) // then if err != nil { From 53db3bb570c675766e8f158fa93218ef35607637 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Thu, 29 Nov 2018 00:12:37 +0900 Subject: [PATCH 004/135] Cleanup config --- application/service/runner/runner_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/application/service/runner/runner_test.go b/application/service/runner/runner_test.go index f30fc656..0ee760bc 100644 --- a/application/service/runner/runner_test.go +++ b/application/service/runner/runner_test.go @@ -768,6 +768,9 @@ func TestRunnerImpl_Run_NonNormal(t *testing.T) { // and application.Config.Job.Timeout = 1 + defer func() { + application.Config.Job.Timeout = 600 + }() mockDocker := mock_docker.NewMockService(ctrl) mockDocker.EXPECT(). From 949dd8d2338edb08c44718f0c41bb442fe7b036a Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Thu, 29 Nov 2018 04:42:15 +0900 Subject: [PATCH 005/135] Separate helper methods --- application/service/runner/helper.go | 62 +++++++++++++++++++++++ application/service/runner/runner.go | 30 ----------- application/service/runner/task_runner.go | 7 ++- 3 files changed, 67 insertions(+), 32 deletions(-) create mode 100644 application/service/runner/helper.go diff --git a/application/service/runner/helper.go b/application/service/runner/helper.go new file mode 100644 index 00000000..2c47f483 --- /dev/null +++ b/application/service/runner/helper.go @@ -0,0 +1,62 @@ +package runner + +import ( + "bytes" + "github.com/duck8823/duci/application/service/docker" + "github.com/duck8823/duci/infrastructure/archive/tar" + "github.com/pkg/errors" + "gopkg.in/yaml.v2" + "io/ioutil" + "os" + "path/filepath" +) + +// createTarball creates a tar archive +func createTarball(workDir string) (*os.File, error) { + tarFilePath := filepath.Join(workDir, "duci.tar") + writeFile, err := os.OpenFile(tarFilePath, os.O_RDWR|os.O_CREATE, 0600) + if err != nil { + return nil, errors.WithStack(err) + } + defer writeFile.Close() + + if err := tar.Create(workDir, writeFile); err != nil { + return nil, errors.WithStack(err) + } + + readFile, _ := os.Open(tarFilePath) + return readFile, nil +} + +// dockerfilePath returns a path to dockerfile for duci using +func dockerfilePath(workDir string) docker.Dockerfile { + dockerfile := "./Dockerfile" + if exists(filepath.Join(workDir, ".duci/Dockerfile")) { + dockerfile = ".duci/Dockerfile" + } + return docker.Dockerfile(dockerfile) +} + +// exists indicates whether the file exists +func exists(name string) bool { + _, err := os.Stat(name) + return !os.IsNotExist(err) +} + +// runtimeOptions parses a config.yml and returns a docker runtime options +func runtimeOptions(workDir string) (docker.RuntimeOptions, error) { + var opts docker.RuntimeOptions + + if !exists(filepath.Join(workDir, ".duci/config.yml")) { + return opts, nil + } + content, err := ioutil.ReadFile(filepath.Join(workDir, ".duci/config.yml")) + if err != nil { + return opts, errors.WithStack(err) + } + content = []byte(os.ExpandEnv(string(content))) + if err := yaml.NewDecoder(bytes.NewReader(content)).Decode(&opts); err != nil { + return opts, errors.WithStack(err) + } + return opts, nil +} diff --git a/application/service/runner/runner.go b/application/service/runner/runner.go index aa6d8052..ecc0919f 100644 --- a/application/service/runner/runner.go +++ b/application/service/runner/runner.go @@ -10,7 +10,6 @@ import ( "github.com/duck8823/duci/application/service/github" "github.com/duck8823/duci/application/service/logstore" "github.com/duck8823/duci/data/model" - "github.com/duck8823/duci/infrastructure/archive/tar" "github.com/duck8823/duci/infrastructure/logger" "github.com/labstack/gommon/random" "github.com/pkg/errors" @@ -116,30 +115,6 @@ func (r *DockerRunner) dockerBuild(ctx context.Context, dir string, repo github. return nil } -func createTarball(workDir string) (*os.File, error) { - tarFilePath := filepath.Join(workDir, "duci.tar") - writeFile, err := os.OpenFile(tarFilePath, os.O_RDWR|os.O_CREATE, 0600) - if err != nil { - return nil, errors.WithStack(err) - } - defer writeFile.Close() - - if err := tar.Create(workDir, writeFile); err != nil { - return nil, errors.WithStack(err) - } - - readFile, _ := os.Open(tarFilePath) - return readFile, nil -} - -func dockerfilePath(workDir string) docker.Dockerfile { - dockerfile := "./Dockerfile" - if exists(filepath.Join(workDir, ".duci/Dockerfile")) { - dockerfile = ".duci/Dockerfile" - } - return docker.Dockerfile(dockerfile) -} - func (r *DockerRunner) dockerRun(ctx context.Context, dir string, repo github.Repository, cmd docker.Command) (docker.ContainerID, error) { opts, err := runtimeOpts(dir) if err != nil { @@ -211,8 +186,3 @@ func (r *DockerRunner) finish(ctx context.Context, src *github.TargetSource, err } r.LogStore.Finish(ctx.UUID()) } - -func exists(name string) bool { - _, err := os.Stat(name) - return !os.IsNotExist(err) -} diff --git a/application/service/runner/task_runner.go b/application/service/runner/task_runner.go index 8d8e0e11..fe9b04fb 100644 --- a/application/service/runner/task_runner.go +++ b/application/service/runner/task_runner.go @@ -64,6 +64,7 @@ func (r *DockerTaskRunner) Run(ctx context.Context, dir string, opts RunOptions) } } +// run task in docker container func (r *DockerTaskRunner) run(ctx context.Context, dir string, opts RunOptions) error { if err := r.dockerBuild(ctx, dir, opts.Tag); err != nil { return errors.WithStack(err) @@ -85,9 +86,10 @@ func (r *DockerTaskRunner) run(ctx context.Context, dir string, opts RunOptions) return ErrFailure } - return err + return nil } +// dockerBuild build a docker image func (r *DockerTaskRunner) dockerBuild(ctx context.Context, dir string, tag Tag) error { tarball, err := createTarball(dir) if err != nil { @@ -105,8 +107,9 @@ func (r *DockerTaskRunner) dockerBuild(ctx context.Context, dir string, tag Tag) return nil } +// dockerRun run docker container func (r *DockerTaskRunner) dockerRun(ctx context.Context, dir string, opts RunOptions) (docker.ContainerID, error) { - dockerOpts, err := runtimeOpts(dir) + dockerOpts, err := runtimeOptions(dir) if err != nil { return "", errors.WithStack(err) } From c3ef14cf2e0e29e700301ed5b18e5e007985e0b9 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Thu, 29 Nov 2018 07:31:24 +0900 Subject: [PATCH 006/135] DockerRunner as domain service --- application/service/executor/executor.go | 50 +++++++ application/service/runner/task_runner.go | 125 ------------------ domain/model/docker/types.go | 26 ++++ domain/model/log/log.go | 14 ++ domain/model/log/mock_log/log.go | 47 +++++++ domain/service/docker/docker.go | 84 ++++++++++++ domain/service/docker/mock_docker/docker.go | 114 ++++++++++++++++ domain/service/runner/errors.go | 6 + domain/service/runner/export_test.go | 3 + domain/service/runner/helper.go | 63 +++++++++ domain/service/runner/runner.go | 80 +++++++++++ .../service/runner/runner_test.go | 17 +-- 12 files changed, 496 insertions(+), 133 deletions(-) create mode 100644 application/service/executor/executor.go delete mode 100644 application/service/runner/task_runner.go create mode 100644 domain/model/docker/types.go create mode 100644 domain/model/log/log.go create mode 100644 domain/model/log/mock_log/log.go create mode 100644 domain/service/docker/docker.go create mode 100644 domain/service/docker/mock_docker/docker.go create mode 100644 domain/service/runner/errors.go create mode 100644 domain/service/runner/export_test.go create mode 100644 domain/service/runner/helper.go create mode 100644 domain/service/runner/runner.go rename application/service/runner/task_runner_test.go => domain/service/runner/runner_test.go (68%) diff --git a/application/service/executor/executor.go b/application/service/executor/executor.go new file mode 100644 index 00000000..f326f38c --- /dev/null +++ b/application/service/executor/executor.go @@ -0,0 +1,50 @@ +package executor + +import ( + "context" + "github.com/duck8823/duci/application" + "github.com/duck8823/duci/application/semaphore" + "github.com/duck8823/duci/domain/model/docker" + "github.com/duck8823/duci/domain/service/runner" + "github.com/labstack/gommon/random" +) + +type JobExecutor struct { + runner.DockerRunner + StartFunc []func(context.Context) + EndFunc []func(context.Context, error) +} + +// Execute job +func (r *JobExecutor) Execute(ctx context.Context, dir string, cmd ...string) error { + for _, f := range r.StartFunc { + go f(ctx) + } + + errs := make(chan error, 1) + + timeout, cancel := context.WithTimeout(ctx, application.Config.Timeout()) + defer cancel() + + go func() { + semaphore.Acquire() + errs <- r.DockerRunner.Run(timeout, dir, docker.Tag(random.String(16, random.Alphanumeric)), cmd) + semaphore.Release() + }() + + select { + case <-timeout.Done(): + r.executeEndFunc(ctx, timeout.Err()) + return timeout.Err() + case err := <-errs: + r.executeEndFunc(ctx, err) + return err + } +} + +// executeEndFunc execute functions +func (r *JobExecutor) executeEndFunc(ctx context.Context, err error) { + for _, f := range r.EndFunc { + go f(ctx, err) + } +} diff --git a/application/service/runner/task_runner.go b/application/service/runner/task_runner.go deleted file mode 100644 index fe9b04fb..00000000 --- a/application/service/runner/task_runner.go +++ /dev/null @@ -1,125 +0,0 @@ -package runner - -import ( - "context" - "github.com/duck8823/duci/application" - "github.com/duck8823/duci/application/semaphore" - "github.com/duck8823/duci/application/service/docker" - "github.com/pkg/errors" -) - -// Tag is a docker tag. -type Tag string - -// Command is docker command. -type Command []string - -// RunOptions is options for docker. -type RunOptions struct { - Tag - Command -} - -// TaskRunner is a interface describes task runner. -type TaskRunner interface { - Run(ctx context.Context, dir string, opts RunOptions) error -} - -// DockerTaskRunner is a implement of TaskRunner with Docker -type DockerTaskRunner struct { - Docker docker.Service - StartFunc []func(context.Context) - LogFunc []func(context.Context, docker.Log) - EndFunc []func(context.Context, error) -} - -// Run task in docker container. -func (r *DockerTaskRunner) Run(ctx context.Context, dir string, opts RunOptions) error { - for _, f := range r.StartFunc { - go f(ctx) - } - - errs := make(chan error, 1) - - timeout, cancel := context.WithTimeout(ctx, application.Config.Timeout()) - defer cancel() - - go func() { - semaphore.Acquire() - errs <- r.run(timeout, dir, opts) - semaphore.Release() - }() - - select { - case <-timeout.Done(): - for _, f := range r.EndFunc { - go f(ctx, timeout.Err()) - } - return timeout.Err() - case err := <-errs: - for _, f := range r.EndFunc { - go f(ctx, err) - } - return err - } -} - -// run task in docker container -func (r *DockerTaskRunner) run(ctx context.Context, dir string, opts RunOptions) error { - if err := r.dockerBuild(ctx, dir, opts.Tag); err != nil { - return errors.WithStack(err) - } - - conID, err := r.dockerRun(ctx, dir, opts) - if err != nil { - return errors.WithStack(err) - } - - code, err := r.Docker.ExitCode(ctx, conID) - if err != nil { - return errors.WithStack(err) - } - if err := r.Docker.Rm(ctx, conID); err != nil { - return errors.WithStack(err) - } - if code != 0 { - return ErrFailure - } - - return nil -} - -// dockerBuild build a docker image -func (r *DockerTaskRunner) dockerBuild(ctx context.Context, dir string, tag Tag) error { - tarball, err := createTarball(dir) - if err != nil { - return errors.WithStack(err) - } - defer tarball.Close() - - buildLog, err := r.Docker.Build(ctx, tarball, docker.Tag(tag), dockerfilePath(dir)) - if err != nil { - return errors.WithStack(err) - } - for _, f := range r.LogFunc { - go f(ctx, buildLog) - } - return nil -} - -// dockerRun run docker container -func (r *DockerTaskRunner) dockerRun(ctx context.Context, dir string, opts RunOptions) (docker.ContainerID, error) { - dockerOpts, err := runtimeOptions(dir) - if err != nil { - return "", errors.WithStack(err) - } - - conID, runLog, err := r.Docker.Run(ctx, dockerOpts, docker.Tag(opts.Tag), docker.Command(opts.Command)) - if err != nil { - return conID, errors.WithStack(err) - } - for _, f := range r.LogFunc { - go f(ctx, runLog) - } - return conID, nil -} diff --git a/domain/model/docker/types.go b/domain/model/docker/types.go new file mode 100644 index 00000000..b2d3b0e3 --- /dev/null +++ b/domain/model/docker/types.go @@ -0,0 +1,26 @@ +package docker + +import "github.com/duck8823/duci/infrastructure/docker" + +// Tag describes a docker tag +type Tag string + +// Command describes a docker CMD +type Command []string + +// Dockerfile represents a path to dockerfile +type Dockerfile string + +// RuntimeOptions represents a options +type RuntimeOptions = docker.RuntimeOptions + +// ContainerID describes a container id of docker +type ContainerID string + +// ExitCode describes a exit code +type ExitCode int64 + +// IsFailure returns whether failure code or not +func (c ExitCode) IsFailure() bool { + return c != 1 +} diff --git a/domain/model/log/log.go b/domain/model/log/log.go new file mode 100644 index 00000000..49b36fc4 --- /dev/null +++ b/domain/model/log/log.go @@ -0,0 +1,14 @@ +package log + +import "time" + +// Log is a interface represents docker log. +type Log interface { + ReadLine() (*Line, error) +} + +// Line stores timestamp and message. +type Line struct { + Timestamp time.Time + Message []byte +} diff --git a/domain/model/log/mock_log/log.go b/domain/model/log/mock_log/log.go new file mode 100644 index 00000000..b5a73268 --- /dev/null +++ b/domain/model/log/mock_log/log.go @@ -0,0 +1,47 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: domain/model/log/log.go + +// Package mock_log is a generated GoMock package. +package mock_log + +import ( + log "github.com/duck8823/duci/domain/model/log" + gomock "github.com/golang/mock/gomock" + reflect "reflect" +) + +// MockLog is a mock of Log interface +type MockLog struct { + ctrl *gomock.Controller + recorder *MockLogMockRecorder +} + +// MockLogMockRecorder is the mock recorder for MockLog +type MockLogMockRecorder struct { + mock *MockLog +} + +// NewMockLog creates a new mock instance +func NewMockLog(ctrl *gomock.Controller) *MockLog { + mock := &MockLog{ctrl: ctrl} + mock.recorder = &MockLogMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockLog) EXPECT() *MockLogMockRecorder { + return m.recorder +} + +// ReadLine mocks base method +func (m *MockLog) ReadLine() (*log.Line, error) { + ret := m.ctrl.Call(m, "ReadLine") + ret0, _ := ret[0].(*log.Line) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ReadLine indicates an expected call of ReadLine +func (mr *MockLogMockRecorder) ReadLine() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadLine", reflect.TypeOf((*MockLog)(nil).ReadLine)) +} diff --git a/domain/service/docker/docker.go b/domain/service/docker/docker.go new file mode 100644 index 00000000..f655ec55 --- /dev/null +++ b/domain/service/docker/docker.go @@ -0,0 +1,84 @@ +package docker + +import ( + "context" + . "github.com/duck8823/duci/domain/model/docker" + "github.com/duck8823/duci/domain/model/log" + "github.com/duck8823/duci/infrastructure/docker" + "github.com/pkg/errors" + "io" +) + +// Docker is a interface describe docker service. +type Docker interface { + Build(ctx context.Context, file io.Reader, tag Tag, dockerfile Dockerfile) (log.Log, error) + Run(ctx context.Context, opts docker.RuntimeOptions, tag Tag, cmd Command) (ContainerID, log.Log, error) + Rm(ctx context.Context, containerID ContainerID) error + Rmi(ctx context.Context, tag Tag) error + ExitCode(ctx context.Context, containerID ContainerID) (ExitCode, error) + Status() error +} + +type dockerService struct { + moby docker.Client +} + +// New returns instance of docker service +func New() (Docker, error) { + cli, err := docker.New() + if err != nil { + return nil, errors.WithStack(err) + } + return &dockerService{moby: cli}, nil +} + +// Build a docker image. +func (s *dockerService) Build(ctx context.Context, file io.Reader, tag Tag, dockerfile Dockerfile) (log.Log, error) { + buildLog, err := s.moby.Build(ctx, file, string(tag), string(dockerfile)) + if err != nil { + return nil, errors.WithStack(err) + } + return buildLog.(log.Log), nil +} + +// Run docker container with command. +func (s *dockerService) Run(ctx context.Context, opts docker.RuntimeOptions, tag Tag, cmd Command) (ContainerID, log.Log, error) { + conID, runLog, err := s.moby.Run(ctx, opts, string(tag), cmd...) + if err != nil { + return ContainerID(conID), nil, errors.WithStack(err) + } + return ContainerID(conID), runLog.(log.Log), nil +} + +// Rm remove docker container. +func (s *dockerService) Rm(ctx context.Context, conID ContainerID) error { + if err := s.moby.Rm(ctx, string(conID)); err != nil { + return errors.WithStack(err) + } + return nil +} + +// Rmi remove docker image. +func (s *dockerService) Rmi(ctx context.Context, tag Tag) error { + if err := s.moby.Rmi(ctx, string(tag)); err != nil { + return errors.WithStack(err) + } + return nil +} + +// ExitCode returns exit code specific container id. +func (s *dockerService) ExitCode(ctx context.Context, conID ContainerID) (ExitCode, error) { + code, err := s.moby.ExitCode(ctx, string(conID)) + if err != nil { + return ExitCode(code), errors.WithStack(err) + } + return ExitCode(code), nil +} + +// Status returns error of docker daemon status. +func (s *dockerService) Status() error { + if _, err := s.moby.Info(context.Background()); err != nil { + return errors.Wrap(err, "Couldn't connect to Docker daemon.") + } + return nil +} diff --git a/domain/service/docker/mock_docker/docker.go b/domain/service/docker/mock_docker/docker.go new file mode 100644 index 00000000..56a504f5 --- /dev/null +++ b/domain/service/docker/mock_docker/docker.go @@ -0,0 +1,114 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: domain/service/docker/docker.go + +// Package mock_docker is a generated GoMock package. +package mock_docker + +import ( + "context" + docker0 "github.com/duck8823/duci/domain/model/docker" + "github.com/duck8823/duci/domain/model/log" + docker1 "github.com/duck8823/duci/infrastructure/docker" + "github.com/golang/mock/gomock" + "io" + "reflect" +) + +// MockDocker is a mock of Docker interface +type MockDocker struct { + ctrl *gomock.Controller + recorder *MockDockerMockRecorder +} + +// MockDockerMockRecorder is the mock recorder for MockDocker +type MockDockerMockRecorder struct { + mock *MockDocker +} + +// NewMockDocker creates a new mock instance +func NewMockDocker(ctrl *gomock.Controller) *MockDocker { + mock := &MockDocker{ctrl: ctrl} + mock.recorder = &MockDockerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockDocker) EXPECT() *MockDockerMockRecorder { + return m.recorder +} + +// Build mocks base method +func (m *MockDocker) Build(ctx context.Context, file io.Reader, tag docker0.Tag, dockerfile docker0.Dockerfile) (log.Log, error) { + ret := m.ctrl.Call(m, "Build", ctx, file, tag, dockerfile) + ret0, _ := ret[0].(log.Log) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Build indicates an expected call of Build +func (mr *MockDockerMockRecorder) Build(ctx, file, tag, dockerfile interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Build", reflect.TypeOf((*MockDocker)(nil).Build), ctx, file, tag, dockerfile) +} + +// Run mocks base method +func (m *MockDocker) Run(ctx context.Context, opts docker1.RuntimeOptions, tag docker0.Tag, cmd docker0.Command) (docker0.ContainerID, log.Log, error) { + ret := m.ctrl.Call(m, "Run", ctx, opts, tag, cmd) + ret0, _ := ret[0].(docker0.ContainerID) + ret1, _ := ret[1].(log.Log) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// Run indicates an expected call of Run +func (mr *MockDockerMockRecorder) Run(ctx, opts, tag, cmd interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Run", reflect.TypeOf((*MockDocker)(nil).Run), ctx, opts, tag, cmd) +} + +// Rm mocks base method +func (m *MockDocker) Rm(ctx context.Context, containerID docker0.ContainerID) error { + ret := m.ctrl.Call(m, "Rm", ctx, containerID) + ret0, _ := ret[0].(error) + return ret0 +} + +// Rm indicates an expected call of Rm +func (mr *MockDockerMockRecorder) Rm(ctx, containerID interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Rm", reflect.TypeOf((*MockDocker)(nil).Rm), ctx, containerID) +} + +// Rmi mocks base method +func (m *MockDocker) Rmi(ctx context.Context, tag docker0.Tag) error { + ret := m.ctrl.Call(m, "Rmi", ctx, tag) + ret0, _ := ret[0].(error) + return ret0 +} + +// Rmi indicates an expected call of Rmi +func (mr *MockDockerMockRecorder) Rmi(ctx, tag interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Rmi", reflect.TypeOf((*MockDocker)(nil).Rmi), ctx, tag) +} + +// ExitCode mocks base method +func (m *MockDocker) ExitCode(ctx context.Context, containerID docker0.ContainerID) (docker0.ExitCode, error) { + ret := m.ctrl.Call(m, "ExitCode", ctx, containerID) + ret0, _ := ret[0].(docker0.ExitCode) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ExitCode indicates an expected call of ExitCode +func (mr *MockDockerMockRecorder) ExitCode(ctx, containerID interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExitCode", reflect.TypeOf((*MockDocker)(nil).ExitCode), ctx, containerID) +} + +// Status mocks base method +func (m *MockDocker) Status() error { + ret := m.ctrl.Call(m, "Status") + ret0, _ := ret[0].(error) + return ret0 +} + +// Status indicates an expected call of Status +func (mr *MockDockerMockRecorder) Status() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Status", reflect.TypeOf((*MockDocker)(nil).Status)) +} diff --git a/domain/service/runner/errors.go b/domain/service/runner/errors.go new file mode 100644 index 00000000..807f6512 --- /dev/null +++ b/domain/service/runner/errors.go @@ -0,0 +1,6 @@ +package runner + +import "github.com/pkg/errors" + +// ErrFailure is a error describes task failure. +var ErrFailure = errors.New("Task Failure") diff --git a/domain/service/runner/export_test.go b/domain/service/runner/export_test.go new file mode 100644 index 00000000..a1657120 --- /dev/null +++ b/domain/service/runner/export_test.go @@ -0,0 +1,3 @@ +package runner + +type DockerRunnerImpl = dockerRunnerImpl diff --git a/domain/service/runner/helper.go b/domain/service/runner/helper.go new file mode 100644 index 00000000..ef39ac37 --- /dev/null +++ b/domain/service/runner/helper.go @@ -0,0 +1,63 @@ +package runner + +import ( + "bytes" + . "github.com/duck8823/duci/domain/model/docker" + "github.com/duck8823/duci/infrastructure/archive/tar" + "github.com/duck8823/duci/infrastructure/docker" + "github.com/pkg/errors" + "gopkg.in/yaml.v2" + "io/ioutil" + "os" + "path/filepath" +) + +// createTarball creates a tar archive +func createTarball(workDir string) (*os.File, error) { + tarFilePath := filepath.Join(workDir, "duci.tar") + writeFile, err := os.OpenFile(tarFilePath, os.O_RDWR|os.O_CREATE, 0600) + if err != nil { + return nil, errors.WithStack(err) + } + defer writeFile.Close() + + if err := tar.Create(workDir, writeFile); err != nil { + return nil, errors.WithStack(err) + } + + readFile, _ := os.Open(tarFilePath) + return readFile, nil +} + +// dockerfilePath returns a path to dockerfile for duci using +func dockerfilePath(workDir string) Dockerfile { + dockerfile := "./Dockerfile" + if exists(filepath.Join(workDir, ".duci/Dockerfile")) { + dockerfile = ".duci/Dockerfile" + } + return Dockerfile(dockerfile) +} + +// exists indicates whether the file exists +func exists(name string) bool { + _, err := os.Stat(name) + return !os.IsNotExist(err) +} + +// runtimeOptions parses a config.yml and returns a docker runtime options +func runtimeOptions(workDir string) (docker.RuntimeOptions, error) { + var opts docker.RuntimeOptions + + if !exists(filepath.Join(workDir, ".duci/config.yml")) { + return opts, nil + } + content, err := ioutil.ReadFile(filepath.Join(workDir, ".duci/config.yml")) + if err != nil { + return opts, errors.WithStack(err) + } + content = []byte(os.ExpandEnv(string(content))) + if err := yaml.NewDecoder(bytes.NewReader(content)).Decode(&opts); err != nil { + return opts, errors.WithStack(err) + } + return opts, nil +} diff --git a/domain/service/runner/runner.go b/domain/service/runner/runner.go new file mode 100644 index 00000000..df3938dc --- /dev/null +++ b/domain/service/runner/runner.go @@ -0,0 +1,80 @@ +package runner + +import ( + "context" + "github.com/duck8823/duci/domain/model/docker" + "github.com/duck8823/duci/domain/model/log" + . "github.com/duck8823/duci/domain/service/docker" + "github.com/pkg/errors" +) + +// DockerRunner is a interface describes task runner. +type DockerRunner interface { + Run(ctx context.Context, dir string, tag docker.Tag, cmd docker.Command) error +} + +// dockerRunnerImpl is a implement of DockerRunner +type dockerRunnerImpl struct { + Docker + LogFunc []func(context.Context, log.Log) +} + +// Run task in docker container +func (r *dockerRunnerImpl) Run(ctx context.Context, dir string, tag docker.Tag, cmd docker.Command) error { + if err := r.dockerBuild(ctx, dir, tag); err != nil { + return errors.WithStack(err) + } + + conID, err := r.dockerRun(ctx, dir, tag, cmd) + if err != nil { + return errors.WithStack(err) + } + + code, err := r.Docker.ExitCode(ctx, conID) + if err != nil { + return errors.WithStack(err) + } + if err := r.Docker.Rm(ctx, conID); err != nil { + return errors.WithStack(err) + } + if code != 0 { + return ErrFailure + } + + return nil +} + +// dockerBuild build a docker image +func (r *dockerRunnerImpl) dockerBuild(ctx context.Context, dir string, tag docker.Tag) error { + tarball, err := createTarball(dir) + if err != nil { + return errors.WithStack(err) + } + defer tarball.Close() + + buildLog, err := r.Docker.Build(ctx, tarball, docker.Tag(tag), dockerfilePath(dir)) + if err != nil { + return errors.WithStack(err) + } + for _, f := range r.LogFunc { + go f(ctx, buildLog) + } + return nil +} + +// dockerRun run docker container +func (r *dockerRunnerImpl) dockerRun(ctx context.Context, dir string, tag docker.Tag, cmd docker.Command) (docker.ContainerID, error) { + opts, err := runtimeOptions(dir) + if err != nil { + return "", errors.WithStack(err) + } + + conID, runLog, err := r.Docker.Run(ctx, opts, tag, cmd) + if err != nil { + return conID, errors.WithStack(err) + } + for _, f := range r.LogFunc { + go f(ctx, runLog) + } + return conID, nil +} diff --git a/application/service/runner/task_runner_test.go b/domain/service/runner/runner_test.go similarity index 68% rename from application/service/runner/task_runner_test.go rename to domain/service/runner/runner_test.go index ae8ec7a4..ac3c2202 100644 --- a/application/service/runner/task_runner_test.go +++ b/domain/service/runner/runner_test.go @@ -2,9 +2,10 @@ package runner_test import ( "context" - "github.com/duck8823/duci/application/service/docker" - "github.com/duck8823/duci/application/service/docker/mock_docker" - "github.com/duck8823/duci/application/service/runner" + "github.com/duck8823/duci/domain/model/docker" + "github.com/duck8823/duci/domain/model/log/mock_log" + "github.com/duck8823/duci/domain/service/docker/mock_docker" + "github.com/duck8823/duci/domain/service/runner" . "github.com/golang/mock/gomock" "github.com/labstack/gommon/random" "os" @@ -22,14 +23,14 @@ func TestDockerTaskRunner_Run(t *testing.T) { defer ctrl.Finish() // and - mockDocker := mock_docker.NewMockService(ctrl) + mockDocker := mock_docker.NewMockDocker(ctrl) mockDocker.EXPECT(). Build(Any(), Any(), Any(), Any()). - Return(&runner.MockBuildLog{}, nil). + Return(mock_log.NewMockLog(ctrl), nil). Times(1) mockDocker.EXPECT(). Run(Any(), Any(), Any(), Any()). - Return(docker.ContainerID(""), &runner.MockJobLog{}, nil). + Return(docker.ContainerID(""), mock_log.NewMockLog(ctrl), nil). Times(1) mockDocker.EXPECT(). ExitCode(Any(), Any()). @@ -41,12 +42,12 @@ func TestDockerTaskRunner_Run(t *testing.T) { Times(1) // and - sut := &runner.DockerTaskRunner{ + sut := &runner.DockerRunnerImpl{ Docker: mockDocker, } // when - err := sut.Run(context.Background(), dir, runner.RunOptions{}) + err := sut.Run(context.Background(), dir, docker.Tag("duck8823/duci:test"), []string{}) // then if err != nil { From f1fe4f474233664c7278589f0014b7e080ea9ecb Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 1 Dec 2018 01:50:15 +0900 Subject: [PATCH 007/135] Implement core modules --- domain/model/docker/log.go | 92 ++++++++++++++++ domain/model/docker/options.go | 37 +++++++ domain/model/docker/types.go | 25 ++++- domain/model/log/mock_log/log.go | 47 -------- domain/service/docker/docker.go | 75 +++++++++---- domain/service/docker/mock_docker/docker.go | 114 -------------------- domain/service/docker/third_pirty.go | 54 ++++++++++ domain/service/runner/export_test.go | 3 - domain/service/runner/helper.go | 5 +- domain/service/runner/runner.go | 2 +- domain/service/runner/runner_test.go | 68 ------------ 11 files changed, 259 insertions(+), 263 deletions(-) create mode 100644 domain/model/docker/log.go create mode 100644 domain/model/docker/options.go delete mode 100644 domain/model/log/mock_log/log.go delete mode 100644 domain/service/docker/mock_docker/docker.go create mode 100644 domain/service/docker/third_pirty.go delete mode 100644 domain/service/runner/export_test.go delete mode 100644 domain/service/runner/runner_test.go diff --git a/domain/model/docker/log.go b/domain/model/docker/log.go new file mode 100644 index 00000000..7eb11187 --- /dev/null +++ b/domain/model/docker/log.go @@ -0,0 +1,92 @@ +package docker + +import ( + "bufio" + "bytes" + "encoding/json" + "fmt" + "github.com/duck8823/duci/domain/model/log" + "github.com/pkg/errors" + "io" + "time" +) + +var now = time.Now + +type buildLogger struct { + reader *bufio.Reader +} + +// NewBuildLog return a instance of Log. +func NewBuildLog(r io.Reader) *buildLogger { + return &buildLogger{bufio.NewReader(r)} +} + +// ReadLine returns LogLine. +func (l *buildLogger) ReadLine() (*log.Line, error) { + for { + line, _, readErr := l.reader.ReadLine() + msg := extractMessage(line) + if readErr == io.EOF { + return &log.Line{Timestamp: now(), Message: msg}, readErr + } + if readErr != nil { + return nil, errors.WithStack(readErr) + } + + if len(msg) == 0 { + continue + } + + return &log.Line{Timestamp: now(), Message: msg}, readErr + } +} + +type runLogger struct { + reader *bufio.Reader +} + +// NewRunLog returns a instance of Log +func NewRunLog(r io.Reader) *runLogger { + return &runLogger{bufio.NewReader(r)} +} + +// ReadLine returns LogLine. +func (l *runLogger) ReadLine() (*log.Line, error) { + for { + line, _, readErr := l.reader.ReadLine() + if readErr != nil && readErr != io.EOF { + return nil, errors.WithStack(readErr) + } + + messages, err := trimPrefix(line) + if err != nil { + return nil, errors.WithStack(err) + } + + // prevent to CR + progress := bytes.Split(messages, []byte{'\r'}) + return &log.Line{Timestamp: now(), Message: progress[0]}, readErr + } +} + +func extractMessage(line []byte) []byte { + s := &struct { + Stream string `json:"stream"` + }{} + json.NewDecoder(bytes.NewReader(line)).Decode(s) + return []byte(s.Stream) +} + +func trimPrefix(line []byte) ([]byte, error) { + if len(line) < 8 { + return []byte{}, nil + } + + // detect logstore prefix + // see https://godoc.org/github.com/docker/docker/client#Client.ContainerLogs + if !((line[0] == 1 || line[0] == 2) && (line[1] == 0 && line[2] == 0 && line[3] == 0)) { + return nil, fmt.Errorf("invalid logstore prefix: %+v", line[:7]) + } + return line[8:], nil +} diff --git a/domain/model/docker/options.go b/domain/model/docker/options.go new file mode 100644 index 00000000..4a74348e --- /dev/null +++ b/domain/model/docker/options.go @@ -0,0 +1,37 @@ +package docker + +import ( + "fmt" + "strings" +) + +// RuntimeOptions is a docker options. +type RuntimeOptions struct { + Environments Environments + Volumes Volumes +} + +// Environments represents a docker `-e` option. +type Environments map[string]interface{} + +// ToArray returns string array of environments +func (e Environments) ToArray() []string { + var a []string + for key, val := range e { + a = append(a, fmt.Sprintf("%s=%v", key, val)) + } + return a +} + +// Volumes represents a docker `-v` option. +type Volumes []string + +// ToMap returns map of volumes. +func (v Volumes) ToMap() map[string]struct{} { + m := make(map[string]struct{}) + for _, volume := range v { + key := strings.Split(volume, ":")[0] + m[key] = struct{}{} + } + return m +} diff --git a/domain/model/docker/types.go b/domain/model/docker/types.go index b2d3b0e3..c2057a4d 100644 --- a/domain/model/docker/types.go +++ b/domain/model/docker/types.go @@ -1,26 +1,41 @@ package docker -import "github.com/duck8823/duci/infrastructure/docker" - // Tag describes a docker tag type Tag string +// ToString return string value +func (t Tag) ToString() string { + return string(t) +} + // Command describes a docker CMD type Command []string +// ToSlice returns slice values +func (c Command) ToSlice() []string { + return []string(c) +} + // Dockerfile represents a path to dockerfile type Dockerfile string -// RuntimeOptions represents a options -type RuntimeOptions = docker.RuntimeOptions +// ToString returns string value +func (d Dockerfile) ToString() string { + return string(d) +} // ContainerID describes a container id of docker type ContainerID string +// ToString returns string value +func (c ContainerID) ToString() string { + return string(c) +} + // ExitCode describes a exit code type ExitCode int64 // IsFailure returns whether failure code or not func (c ExitCode) IsFailure() bool { return c != 1 -} +} \ No newline at end of file diff --git a/domain/model/log/mock_log/log.go b/domain/model/log/mock_log/log.go deleted file mode 100644 index b5a73268..00000000 --- a/domain/model/log/mock_log/log.go +++ /dev/null @@ -1,47 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: domain/model/log/log.go - -// Package mock_log is a generated GoMock package. -package mock_log - -import ( - log "github.com/duck8823/duci/domain/model/log" - gomock "github.com/golang/mock/gomock" - reflect "reflect" -) - -// MockLog is a mock of Log interface -type MockLog struct { - ctrl *gomock.Controller - recorder *MockLogMockRecorder -} - -// MockLogMockRecorder is the mock recorder for MockLog -type MockLogMockRecorder struct { - mock *MockLog -} - -// NewMockLog creates a new mock instance -func NewMockLog(ctrl *gomock.Controller) *MockLog { - mock := &MockLog{ctrl: ctrl} - mock.recorder = &MockLogMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockLog) EXPECT() *MockLogMockRecorder { - return m.recorder -} - -// ReadLine mocks base method -func (m *MockLog) ReadLine() (*log.Line, error) { - ret := m.ctrl.Call(m, "ReadLine") - ret0, _ := ret[0].(*log.Line) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ReadLine indicates an expected call of ReadLine -func (mr *MockLogMockRecorder) ReadLine() *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadLine", reflect.TypeOf((*MockLog)(nil).ReadLine)) -} diff --git a/domain/service/docker/docker.go b/domain/service/docker/docker.go index f655ec55..599ab591 100644 --- a/domain/service/docker/docker.go +++ b/domain/service/docker/docker.go @@ -2,9 +2,11 @@ package docker import ( "context" + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + moby "github.com/docker/docker/client" . "github.com/duck8823/duci/domain/model/docker" "github.com/duck8823/duci/domain/model/log" - "github.com/duck8823/duci/infrastructure/docker" "github.com/pkg/errors" "io" ) @@ -12,20 +14,20 @@ import ( // Docker is a interface describe docker service. type Docker interface { Build(ctx context.Context, file io.Reader, tag Tag, dockerfile Dockerfile) (log.Log, error) - Run(ctx context.Context, opts docker.RuntimeOptions, tag Tag, cmd Command) (ContainerID, log.Log, error) - Rm(ctx context.Context, containerID ContainerID) error - Rmi(ctx context.Context, tag Tag) error + Run(ctx context.Context, opts RuntimeOptions, tag Tag, cmd Command) (ContainerID, log.Log, error) + RemoveContainer(ctx context.Context, containerID ContainerID) error + RemoveImage(ctx context.Context, tag Tag) error ExitCode(ctx context.Context, containerID ContainerID) (ExitCode, error) Status() error } type dockerService struct { - moby docker.Client + moby Moby } // New returns instance of docker service func New() (Docker, error) { - cli, err := docker.New() + cli, err := moby.NewClientWithOpts(moby.FromEnv) if err != nil { return nil, errors.WithStack(err) } @@ -34,33 +36,60 @@ func New() (Docker, error) { // Build a docker image. func (s *dockerService) Build(ctx context.Context, file io.Reader, tag Tag, dockerfile Dockerfile) (log.Log, error) { - buildLog, err := s.moby.Build(ctx, file, string(tag), string(dockerfile)) + opts := types.ImageBuildOptions{ + Tags: []string{tag.ToString()}, + Dockerfile: dockerfile.ToString(), + Remove: true, + } + resp, err := s.moby.ImageBuild(ctx, file, opts) if err != nil { return nil, errors.WithStack(err) } - return buildLog.(log.Log), nil + + return NewBuildLog(resp.Body), nil } // Run docker container with command. -func (s *dockerService) Run(ctx context.Context, opts docker.RuntimeOptions, tag Tag, cmd Command) (ContainerID, log.Log, error) { - conID, runLog, err := s.moby.Run(ctx, opts, string(tag), cmd...) +func (s *dockerService) Run(ctx context.Context, opts RuntimeOptions, tag Tag, cmd Command) (ContainerID, log.Log, error) { + con, err := s.moby.ContainerCreate(ctx, &container.Config{ + Image: tag.ToString(), + Env: opts.Environments.ToArray(), + Volumes: opts.Volumes.ToMap(), + Cmd: cmd.ToSlice(), + }, &container.HostConfig{ + Binds: opts.Volumes, + }, nil, "") if err != nil { - return ContainerID(conID), nil, errors.WithStack(err) + return "", nil, errors.WithStack(err) } - return ContainerID(conID), runLog.(log.Log), nil + + if err := s.moby.ContainerStart(ctx, con.ID, types.ContainerStartOptions{}); err != nil { + return ContainerID(con.ID), nil, errors.WithStack(err) + } + + logs, err := s.moby.ContainerLogs(ctx, con.ID, types.ContainerLogsOptions{ + ShowStdout: true, + ShowStderr: true, + Follow: true, + }) + if err != nil { + return ContainerID(con.ID), nil, errors.WithStack(err) + } + + return ContainerID(con.ID), NewRunLog(logs), nil } -// Rm remove docker container. -func (s *dockerService) Rm(ctx context.Context, conID ContainerID) error { - if err := s.moby.Rm(ctx, string(conID)); err != nil { +// RemoveContainer remove docker container. +func (s *dockerService) RemoveContainer(ctx context.Context, conID ContainerID) error { + if err := s.moby.ContainerRemove(ctx, conID.ToString(), types.ContainerRemoveOptions{}); err != nil { return errors.WithStack(err) } return nil } -// Rmi remove docker image. -func (s *dockerService) Rmi(ctx context.Context, tag Tag) error { - if err := s.moby.Rmi(ctx, string(tag)); err != nil { +// RemoveImage remove docker image. +func (s *dockerService) RemoveImage(ctx context.Context, tag Tag) error { + if _, err := s.moby.ImageRemove(ctx, tag.ToString(), types.ImageRemoveOptions{}); err != nil { return errors.WithStack(err) } return nil @@ -68,11 +97,13 @@ func (s *dockerService) Rmi(ctx context.Context, tag Tag) error { // ExitCode returns exit code specific container id. func (s *dockerService) ExitCode(ctx context.Context, conID ContainerID) (ExitCode, error) { - code, err := s.moby.ExitCode(ctx, string(conID)) - if err != nil { - return ExitCode(code), errors.WithStack(err) + body, err := s.moby.ContainerWait(ctx, conID.ToString(), container.WaitConditionNotRunning) + select { + case b := <-body: + return ExitCode(b.StatusCode), nil + case e := <-err: + return -1, errors.WithStack(e) } - return ExitCode(code), nil } // Status returns error of docker daemon status. diff --git a/domain/service/docker/mock_docker/docker.go b/domain/service/docker/mock_docker/docker.go deleted file mode 100644 index 56a504f5..00000000 --- a/domain/service/docker/mock_docker/docker.go +++ /dev/null @@ -1,114 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: domain/service/docker/docker.go - -// Package mock_docker is a generated GoMock package. -package mock_docker - -import ( - "context" - docker0 "github.com/duck8823/duci/domain/model/docker" - "github.com/duck8823/duci/domain/model/log" - docker1 "github.com/duck8823/duci/infrastructure/docker" - "github.com/golang/mock/gomock" - "io" - "reflect" -) - -// MockDocker is a mock of Docker interface -type MockDocker struct { - ctrl *gomock.Controller - recorder *MockDockerMockRecorder -} - -// MockDockerMockRecorder is the mock recorder for MockDocker -type MockDockerMockRecorder struct { - mock *MockDocker -} - -// NewMockDocker creates a new mock instance -func NewMockDocker(ctrl *gomock.Controller) *MockDocker { - mock := &MockDocker{ctrl: ctrl} - mock.recorder = &MockDockerMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockDocker) EXPECT() *MockDockerMockRecorder { - return m.recorder -} - -// Build mocks base method -func (m *MockDocker) Build(ctx context.Context, file io.Reader, tag docker0.Tag, dockerfile docker0.Dockerfile) (log.Log, error) { - ret := m.ctrl.Call(m, "Build", ctx, file, tag, dockerfile) - ret0, _ := ret[0].(log.Log) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Build indicates an expected call of Build -func (mr *MockDockerMockRecorder) Build(ctx, file, tag, dockerfile interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Build", reflect.TypeOf((*MockDocker)(nil).Build), ctx, file, tag, dockerfile) -} - -// Run mocks base method -func (m *MockDocker) Run(ctx context.Context, opts docker1.RuntimeOptions, tag docker0.Tag, cmd docker0.Command) (docker0.ContainerID, log.Log, error) { - ret := m.ctrl.Call(m, "Run", ctx, opts, tag, cmd) - ret0, _ := ret[0].(docker0.ContainerID) - ret1, _ := ret[1].(log.Log) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// Run indicates an expected call of Run -func (mr *MockDockerMockRecorder) Run(ctx, opts, tag, cmd interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Run", reflect.TypeOf((*MockDocker)(nil).Run), ctx, opts, tag, cmd) -} - -// Rm mocks base method -func (m *MockDocker) Rm(ctx context.Context, containerID docker0.ContainerID) error { - ret := m.ctrl.Call(m, "Rm", ctx, containerID) - ret0, _ := ret[0].(error) - return ret0 -} - -// Rm indicates an expected call of Rm -func (mr *MockDockerMockRecorder) Rm(ctx, containerID interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Rm", reflect.TypeOf((*MockDocker)(nil).Rm), ctx, containerID) -} - -// Rmi mocks base method -func (m *MockDocker) Rmi(ctx context.Context, tag docker0.Tag) error { - ret := m.ctrl.Call(m, "Rmi", ctx, tag) - ret0, _ := ret[0].(error) - return ret0 -} - -// Rmi indicates an expected call of Rmi -func (mr *MockDockerMockRecorder) Rmi(ctx, tag interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Rmi", reflect.TypeOf((*MockDocker)(nil).Rmi), ctx, tag) -} - -// ExitCode mocks base method -func (m *MockDocker) ExitCode(ctx context.Context, containerID docker0.ContainerID) (docker0.ExitCode, error) { - ret := m.ctrl.Call(m, "ExitCode", ctx, containerID) - ret0, _ := ret[0].(docker0.ExitCode) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ExitCode indicates an expected call of ExitCode -func (mr *MockDockerMockRecorder) ExitCode(ctx, containerID interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExitCode", reflect.TypeOf((*MockDocker)(nil).ExitCode), ctx, containerID) -} - -// Status mocks base method -func (m *MockDocker) Status() error { - ret := m.ctrl.Call(m, "Status") - ret0, _ := ret[0].(error) - return ret0 -} - -// Status indicates an expected call of Status -func (mr *MockDockerMockRecorder) Status() *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Status", reflect.TypeOf((*MockDocker)(nil).Status)) -} diff --git a/domain/service/docker/third_pirty.go b/domain/service/docker/third_pirty.go new file mode 100644 index 00000000..6b7ad5d1 --- /dev/null +++ b/domain/service/docker/third_pirty.go @@ -0,0 +1,54 @@ +package docker + +import ( + "context" + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/network" + "io" +) + +// Moby is a interface of docker client +// see also github.com/moby/moby/client +type Moby interface { + ImageBuild( + ctx context.Context, + buildContext io.Reader, + options types.ImageBuildOptions, + ) (types.ImageBuildResponse, error) + ContainerCreate( + ctx context.Context, + config *container.Config, + hostConfig *container.HostConfig, + networkingConfig *network.NetworkingConfig, + containerName string, + ) (container.ContainerCreateCreatedBody, error) + ContainerStart( + ctx context.Context, + containerID string, + options types.ContainerStartOptions, + ) error + ContainerLogs( + ctx context.Context, + container string, + options types.ContainerLogsOptions, + ) (io.ReadCloser, error) + ContainerRemove( + ctx context.Context, + containerID string, + options types.ContainerRemoveOptions, + ) error + ImageRemove( + ctx context.Context, + imageID string, + options types.ImageRemoveOptions, + ) ([]types.ImageDeleteResponseItem, error) + ContainerWait( + ctx context.Context, + containerID string, + condition container.WaitCondition, + ) (<-chan container.ContainerWaitOKBody, <-chan error) + Info( + ctx context.Context, + ) (types.Info, error) +} diff --git a/domain/service/runner/export_test.go b/domain/service/runner/export_test.go deleted file mode 100644 index a1657120..00000000 --- a/domain/service/runner/export_test.go +++ /dev/null @@ -1,3 +0,0 @@ -package runner - -type DockerRunnerImpl = dockerRunnerImpl diff --git a/domain/service/runner/helper.go b/domain/service/runner/helper.go index ef39ac37..7823e250 100644 --- a/domain/service/runner/helper.go +++ b/domain/service/runner/helper.go @@ -4,7 +4,6 @@ import ( "bytes" . "github.com/duck8823/duci/domain/model/docker" "github.com/duck8823/duci/infrastructure/archive/tar" - "github.com/duck8823/duci/infrastructure/docker" "github.com/pkg/errors" "gopkg.in/yaml.v2" "io/ioutil" @@ -45,8 +44,8 @@ func exists(name string) bool { } // runtimeOptions parses a config.yml and returns a docker runtime options -func runtimeOptions(workDir string) (docker.RuntimeOptions, error) { - var opts docker.RuntimeOptions +func runtimeOptions(workDir string) (RuntimeOptions, error) { + var opts RuntimeOptions if !exists(filepath.Join(workDir, ".duci/config.yml")) { return opts, nil diff --git a/domain/service/runner/runner.go b/domain/service/runner/runner.go index df3938dc..7dd0c588 100644 --- a/domain/service/runner/runner.go +++ b/domain/service/runner/runner.go @@ -34,7 +34,7 @@ func (r *dockerRunnerImpl) Run(ctx context.Context, dir string, tag docker.Tag, if err != nil { return errors.WithStack(err) } - if err := r.Docker.Rm(ctx, conID); err != nil { + if err := r.Docker.RemoveContainer(ctx, conID); err != nil { return errors.WithStack(err) } if code != 0 { diff --git a/domain/service/runner/runner_test.go b/domain/service/runner/runner_test.go deleted file mode 100644 index ac3c2202..00000000 --- a/domain/service/runner/runner_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package runner_test - -import ( - "context" - "github.com/duck8823/duci/domain/model/docker" - "github.com/duck8823/duci/domain/model/log/mock_log" - "github.com/duck8823/duci/domain/service/docker/mock_docker" - "github.com/duck8823/duci/domain/service/runner" - . "github.com/golang/mock/gomock" - "github.com/labstack/gommon/random" - "os" - "path" - "testing" -) - -func TestDockerTaskRunner_Run(t *testing.T) { - // given - dir, rmDir := tmpDir(t) - defer rmDir() - - // and - ctrl := NewController(t) - defer ctrl.Finish() - - // and - mockDocker := mock_docker.NewMockDocker(ctrl) - mockDocker.EXPECT(). - Build(Any(), Any(), Any(), Any()). - Return(mock_log.NewMockLog(ctrl), nil). - Times(1) - mockDocker.EXPECT(). - Run(Any(), Any(), Any(), Any()). - Return(docker.ContainerID(""), mock_log.NewMockLog(ctrl), nil). - Times(1) - mockDocker.EXPECT(). - ExitCode(Any(), Any()). - Return(docker.ExitCode(0), nil). - Times(1) - mockDocker.EXPECT(). - Rm(Any(), Any()). - Return(nil). - Times(1) - - // and - sut := &runner.DockerRunnerImpl{ - Docker: mockDocker, - } - - // when - err := sut.Run(context.Background(), dir, docker.Tag("duck8823/duci:test"), []string{}) - - // then - if err != nil { - t.Errorf("must not error. but: %+v", err) - } -} - -func tmpDir(t *testing.T) (string, func()) { - tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) - if err := os.MkdirAll(tmpDir, 0700); err != nil { - t.Fatalf("error occured: %+v", err) - } - return tmpDir, func() { - if err := os.RemoveAll(tmpDir); err != nil { - t.Fatalf("error occured: %+v", err) - } - } -} From 8a5f2d61a862b2ecd0f10f6a145a676bf6d186fc Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 1 Dec 2018 09:00:10 +0900 Subject: [PATCH 008/135] Add runner builder --- domain/model/docker/types.go | 2 +- domain/service/runner/builder.go | 30 ++++++++++++++++++++++++++++++ domain/service/runner/function.go | 19 +++++++++++++++++++ domain/service/runner/runner.go | 7 +++---- 4 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 domain/service/runner/builder.go create mode 100644 domain/service/runner/function.go diff --git a/domain/model/docker/types.go b/domain/model/docker/types.go index c2057a4d..9495a103 100644 --- a/domain/model/docker/types.go +++ b/domain/model/docker/types.go @@ -38,4 +38,4 @@ type ExitCode int64 // IsFailure returns whether failure code or not func (c ExitCode) IsFailure() bool { return c != 1 -} \ No newline at end of file +} diff --git a/domain/service/runner/builder.go b/domain/service/runner/builder.go new file mode 100644 index 00000000..21d4ea2f --- /dev/null +++ b/domain/service/runner/builder.go @@ -0,0 +1,30 @@ +package runner + +import ( + "github.com/duck8823/duci/domain/service/docker" +) + +// DefaultDockerRunnerBuilder create new builder of docker runner +func DefaultDockerRunnerBuilder() *builder { + cli, _ := docker.New() + return &builder{docker: cli} +} + +type builder struct { + docker docker.Docker + logFuncs LogFuncs +} + +// LogFunc append a LogFunc +func (b *builder) LogFunc(f LogFunc) *builder { + b.logFuncs = append(b.logFuncs, f) + return b +} + +// Build returns a docker runner +func (b *builder) Build() *dockerRunnerImpl { + return &dockerRunnerImpl{ + Docker: b.docker, + LogFuncs: b.logFuncs, + } +} diff --git a/domain/service/runner/function.go b/domain/service/runner/function.go new file mode 100644 index 00000000..0556eeed --- /dev/null +++ b/domain/service/runner/function.go @@ -0,0 +1,19 @@ +package runner + +import ( + "context" + . "github.com/duck8823/duci/domain/model/log" +) + +// LogFunc is function of Log +type LogFunc func(context.Context, Log) + +// LogFuncs is slice of LogFunc +type LogFuncs []LogFunc + +// Exec execute in goroutine +func (l LogFuncs) Exec(ctx context.Context, log Log) { + for _, f := range l { + f(ctx, log) + } +} diff --git a/domain/service/runner/runner.go b/domain/service/runner/runner.go index 7dd0c588..0464422f 100644 --- a/domain/service/runner/runner.go +++ b/domain/service/runner/runner.go @@ -3,7 +3,6 @@ package runner import ( "context" "github.com/duck8823/duci/domain/model/docker" - "github.com/duck8823/duci/domain/model/log" . "github.com/duck8823/duci/domain/service/docker" "github.com/pkg/errors" ) @@ -16,7 +15,7 @@ type DockerRunner interface { // dockerRunnerImpl is a implement of DockerRunner type dockerRunnerImpl struct { Docker - LogFunc []func(context.Context, log.Log) + LogFuncs } // Run task in docker container @@ -56,7 +55,7 @@ func (r *dockerRunnerImpl) dockerBuild(ctx context.Context, dir string, tag dock if err != nil { return errors.WithStack(err) } - for _, f := range r.LogFunc { + for _, f := range r.LogFuncs { go f(ctx, buildLog) } return nil @@ -73,7 +72,7 @@ func (r *dockerRunnerImpl) dockerRun(ctx context.Context, dir string, tag docker if err != nil { return conID, errors.WithStack(err) } - for _, f := range r.LogFunc { + for _, f := range r.LogFuncs { go f(ctx, runLog) } return conID, nil From b8b9a4e42c83a44fea08ed33a04727fdfa13b507 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 1 Dec 2018 12:34:54 +0900 Subject: [PATCH 009/135] Add job model --- domain/model/docker/log.go | 16 +++--- domain/model/job/job.go | 50 ++++++++++++++++ domain/model/job/log.go | 14 +++++ domain/model/job/repository.go | 9 +++ domain/model/log/log.go | 14 ----- domain/service/docker/docker.go | 10 ++-- domain/service/runner/function.go | 2 +- infrastructure/job/data_source.go | 96 +++++++++++++++++++++++++++++++ infrastructure/job/third_pirty.go | 13 +++++ 9 files changed, 196 insertions(+), 28 deletions(-) create mode 100644 domain/model/job/job.go create mode 100644 domain/model/job/log.go create mode 100644 domain/model/job/repository.go delete mode 100644 domain/model/log/log.go create mode 100644 infrastructure/job/data_source.go create mode 100644 infrastructure/job/third_pirty.go diff --git a/domain/model/docker/log.go b/domain/model/docker/log.go index 7eb11187..3704eff2 100644 --- a/domain/model/docker/log.go +++ b/domain/model/docker/log.go @@ -5,7 +5,7 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/duck8823/duci/domain/model/log" + "github.com/duck8823/duci/domain/model/job" "github.com/pkg/errors" "io" "time" @@ -23,12 +23,12 @@ func NewBuildLog(r io.Reader) *buildLogger { } // ReadLine returns LogLine. -func (l *buildLogger) ReadLine() (*log.Line, error) { +func (l *buildLogger) ReadLine() (*job.LogLine, error) { for { line, _, readErr := l.reader.ReadLine() msg := extractMessage(line) if readErr == io.EOF { - return &log.Line{Timestamp: now(), Message: msg}, readErr + return &job.LogLine{Timestamp: now(), Message: msg}, readErr } if readErr != nil { return nil, errors.WithStack(readErr) @@ -38,7 +38,7 @@ func (l *buildLogger) ReadLine() (*log.Line, error) { continue } - return &log.Line{Timestamp: now(), Message: msg}, readErr + return &job.LogLine{Timestamp: now(), Message: msg}, readErr } } @@ -52,7 +52,7 @@ func NewRunLog(r io.Reader) *runLogger { } // ReadLine returns LogLine. -func (l *runLogger) ReadLine() (*log.Line, error) { +func (l *runLogger) ReadLine() (*job.LogLine, error) { for { line, _, readErr := l.reader.ReadLine() if readErr != nil && readErr != io.EOF { @@ -66,16 +66,16 @@ func (l *runLogger) ReadLine() (*log.Line, error) { // prevent to CR progress := bytes.Split(messages, []byte{'\r'}) - return &log.Line{Timestamp: now(), Message: progress[0]}, readErr + return &job.LogLine{Timestamp: now(), Message: string(progress[0])}, readErr } } -func extractMessage(line []byte) []byte { +func extractMessage(line []byte) string { s := &struct { Stream string `json:"stream"` }{} json.NewDecoder(bytes.NewReader(line)).Decode(s) - return []byte(s.Stream) + return s.Stream } func trimPrefix(line []byte) ([]byte, error) { diff --git a/domain/model/job/job.go b/domain/model/job/job.go new file mode 100644 index 00000000..18988378 --- /dev/null +++ b/domain/model/job/job.go @@ -0,0 +1,50 @@ +package job + +import ( + "bytes" + "encoding/json" + "github.com/google/uuid" + "github.com/pkg/errors" +) + +// Job represents a task +type Job struct { + Finished bool `json:"finished"` + Stream []LogLine `json:"stream"` +} + +// AppendLog append log line to stream +func (j *Job) AppendLog(line LogLine) { + j.Stream = append(j.Stream, line) +} + +// Finish set true to Finished +func (j *Job) Finish() { + j.Finished = true +} + +// ToBytes returns marshal byte slice +func (j *Job) ToBytes() ([]byte, error) { + data, err := json.Marshal(j) + if err != nil { + return nil, errors.WithStack(err) + } + return data, nil +} + +// NewJob returns unmarshal Job instance +func NewJob(data []byte) (*Job, error) { + job := &Job{} + if err := json.NewDecoder(bytes.NewReader(data)).Decode(job); err != nil { + return nil, errors.WithStack(err) + } + return job, nil +} + +// ID is the identifier of job +type ID uuid.UUID + +// ToSlice returns slice value +func (i ID) ToSlice() []byte { + return []byte(i[:]) +} diff --git a/domain/model/job/log.go b/domain/model/job/log.go new file mode 100644 index 00000000..e49ef58d --- /dev/null +++ b/domain/model/job/log.go @@ -0,0 +1,14 @@ +package job + +import "time" + +// Log is a interface represents docker log. +type Log interface { + ReadLine() (*LogLine, error) +} + +// LogLine stores timestamp and message. +type LogLine struct { + Timestamp time.Time + Message string +} diff --git a/domain/model/job/repository.go b/domain/model/job/repository.go new file mode 100644 index 00000000..1969697c --- /dev/null +++ b/domain/model/job/repository.go @@ -0,0 +1,9 @@ +package job + +// Repository is Job Repository +type Repository interface { + Get(ID) (*Job, error) + Start(ID) error + Append(ID, *LogLine) error + Finish(ID) error +} diff --git a/domain/model/log/log.go b/domain/model/log/log.go deleted file mode 100644 index 49b36fc4..00000000 --- a/domain/model/log/log.go +++ /dev/null @@ -1,14 +0,0 @@ -package log - -import "time" - -// Log is a interface represents docker log. -type Log interface { - ReadLine() (*Line, error) -} - -// Line stores timestamp and message. -type Line struct { - Timestamp time.Time - Message []byte -} diff --git a/domain/service/docker/docker.go b/domain/service/docker/docker.go index 599ab591..e3ffec2c 100644 --- a/domain/service/docker/docker.go +++ b/domain/service/docker/docker.go @@ -6,15 +6,15 @@ import ( "github.com/docker/docker/api/types/container" moby "github.com/docker/docker/client" . "github.com/duck8823/duci/domain/model/docker" - "github.com/duck8823/duci/domain/model/log" + . "github.com/duck8823/duci/domain/model/job" "github.com/pkg/errors" "io" ) // Docker is a interface describe docker service. type Docker interface { - Build(ctx context.Context, file io.Reader, tag Tag, dockerfile Dockerfile) (log.Log, error) - Run(ctx context.Context, opts RuntimeOptions, tag Tag, cmd Command) (ContainerID, log.Log, error) + Build(ctx context.Context, file io.Reader, tag Tag, dockerfile Dockerfile) (Log, error) + Run(ctx context.Context, opts RuntimeOptions, tag Tag, cmd Command) (ContainerID, Log, error) RemoveContainer(ctx context.Context, containerID ContainerID) error RemoveImage(ctx context.Context, tag Tag) error ExitCode(ctx context.Context, containerID ContainerID) (ExitCode, error) @@ -35,7 +35,7 @@ func New() (Docker, error) { } // Build a docker image. -func (s *dockerService) Build(ctx context.Context, file io.Reader, tag Tag, dockerfile Dockerfile) (log.Log, error) { +func (s *dockerService) Build(ctx context.Context, file io.Reader, tag Tag, dockerfile Dockerfile) (Log, error) { opts := types.ImageBuildOptions{ Tags: []string{tag.ToString()}, Dockerfile: dockerfile.ToString(), @@ -50,7 +50,7 @@ func (s *dockerService) Build(ctx context.Context, file io.Reader, tag Tag, dock } // Run docker container with command. -func (s *dockerService) Run(ctx context.Context, opts RuntimeOptions, tag Tag, cmd Command) (ContainerID, log.Log, error) { +func (s *dockerService) Run(ctx context.Context, opts RuntimeOptions, tag Tag, cmd Command) (ContainerID, Log, error) { con, err := s.moby.ContainerCreate(ctx, &container.Config{ Image: tag.ToString(), Env: opts.Environments.ToArray(), diff --git a/domain/service/runner/function.go b/domain/service/runner/function.go index 0556eeed..f0875cb3 100644 --- a/domain/service/runner/function.go +++ b/domain/service/runner/function.go @@ -2,7 +2,7 @@ package runner import ( "context" - . "github.com/duck8823/duci/domain/model/log" + . "github.com/duck8823/duci/domain/model/job" ) // LogFunc is function of Log diff --git a/infrastructure/job/data_source.go b/infrastructure/job/data_source.go new file mode 100644 index 00000000..ee14bf2e --- /dev/null +++ b/infrastructure/job/data_source.go @@ -0,0 +1,96 @@ +package job + +import ( + . "github.com/duck8823/duci/domain/model/job" + "github.com/pkg/errors" + "github.com/syndtr/goleveldb/leveldb" +) + +type dataSource struct { + db LevelDB +} + +func NewDataSource(path string) (*dataSource, error) { + db, err := leveldb.OpenFile(path, nil) + if err != nil { + return nil, errors.WithStack(err) + } + return &dataSource{db}, nil +} + +func (d *dataSource) Get(id ID) (*Job, error) { + data, err := d.db.Get(id.ToSlice(), nil) + if err != nil { + return nil, errors.WithStack(err) + } + + job, err := NewJob(data) + if err != nil { + return nil, errors.WithStack(err) + } + return job, nil +} + +func (d *dataSource) Start(id ID) error { + data, _ := (&Job{Finished: false}).ToBytes() + if err := d.db.Put(id.ToSlice(), data, nil); err != nil { + return errors.WithStack(err) + } + return nil +} + +func (d *dataSource) Append(id ID, line LogLine) error { + job, err := d.findOrInitialize(id) + if err != nil { + return errors.WithStack(err) + } + + job.AppendLog(line) + + data, err := job.ToBytes() + if err != nil { + return errors.WithStack(err) + } + if err := d.db.Put(id.ToSlice(), data, nil); err != nil { + return errors.WithStack(err) + } + return nil +} + +func (d *dataSource) findOrInitialize(id ID) (*Job, error) { + data, err := d.db.Get(id.ToSlice(), nil) + if err == leveldb.ErrNotFound { + return &Job{}, nil + } else if err != nil { + return nil, errors.WithStack(err) + } + + job, err := NewJob(data) + if err != nil { + return nil, errors.WithStack(err) + } + return job, nil +} + +func (d *dataSource) Finish(id ID) error { + data, err := d.db.Get(id.ToSlice(), nil) + if err != nil { + return errors.WithStack(err) + } + + job, err := NewJob(data) + if err != nil { + return errors.WithStack(err) + } + + job.Finish() + + finished, err := job.ToBytes() + if err != nil { + return errors.WithStack(err) + } + if err := d.db.Put(id.ToSlice(), finished, nil); err != nil { + return errors.WithStack(err) + } + return nil +} diff --git a/infrastructure/job/third_pirty.go b/infrastructure/job/third_pirty.go new file mode 100644 index 00000000..b37740f9 --- /dev/null +++ b/infrastructure/job/third_pirty.go @@ -0,0 +1,13 @@ +package job + +import ( + . "github.com/syndtr/goleveldb/leveldb/opt" +) + +// LevelDB is a interface represents key-value store. +type LevelDB interface { + Get(key []byte, ro *ReadOptions) (value []byte, err error) + Has(key []byte, ro *ReadOptions) (ret bool, err error) + Put(key, value []byte, wo *WriteOptions) error + Close() error +} From d04040ccc57c8c18f2702d64e3934790bbcc77e4 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 1 Dec 2018 13:58:21 +0900 Subject: [PATCH 010/135] reduce for loop --- domain/service/runner/function.go | 2 +- domain/service/runner/runner.go | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/domain/service/runner/function.go b/domain/service/runner/function.go index f0875cb3..603fd481 100644 --- a/domain/service/runner/function.go +++ b/domain/service/runner/function.go @@ -14,6 +14,6 @@ type LogFuncs []LogFunc // Exec execute in goroutine func (l LogFuncs) Exec(ctx context.Context, log Log) { for _, f := range l { - f(ctx, log) + go f(ctx, log) } } diff --git a/domain/service/runner/runner.go b/domain/service/runner/runner.go index 0464422f..bcf4428a 100644 --- a/domain/service/runner/runner.go +++ b/domain/service/runner/runner.go @@ -55,9 +55,7 @@ func (r *dockerRunnerImpl) dockerBuild(ctx context.Context, dir string, tag dock if err != nil { return errors.WithStack(err) } - for _, f := range r.LogFuncs { - go f(ctx, buildLog) - } + r.LogFuncs.Exec(ctx, buildLog) return nil } @@ -72,8 +70,6 @@ func (r *dockerRunnerImpl) dockerRun(ctx context.Context, dir string, tag docker if err != nil { return conID, errors.WithStack(err) } - for _, f := range r.LogFuncs { - go f(ctx, runLog) - } + r.LogFuncs.Exec(ctx, runLog) return conID, nil } From cda5f2c281fd93d8a37ccbfebd3800aba2e02d21 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 1 Dec 2018 14:41:39 +0900 Subject: [PATCH 011/135] Replace to single function --- application/service/executor/executor.go | 21 ++++++--------------- domain/service/runner/builder.go | 10 +++++----- domain/service/runner/function.go | 10 ---------- domain/service/runner/runner.go | 6 +++--- 4 files changed, 14 insertions(+), 33 deletions(-) diff --git a/application/service/executor/executor.go b/application/service/executor/executor.go index f326f38c..77221447 100644 --- a/application/service/executor/executor.go +++ b/application/service/executor/executor.go @@ -11,15 +11,13 @@ import ( type JobExecutor struct { runner.DockerRunner - StartFunc []func(context.Context) - EndFunc []func(context.Context, error) + StartFunc func(context.Context) + EndFunc func(context.Context, error) } // Execute job func (r *JobExecutor) Execute(ctx context.Context, dir string, cmd ...string) error { - for _, f := range r.StartFunc { - go f(ctx) - } + r.StartFunc(ctx) errs := make(chan error, 1) @@ -28,23 +26,16 @@ func (r *JobExecutor) Execute(ctx context.Context, dir string, cmd ...string) er go func() { semaphore.Acquire() - errs <- r.DockerRunner.Run(timeout, dir, docker.Tag(random.String(16, random.Alphanumeric)), cmd) + errs <- r.DockerRunner.Run(timeout, dir, docker.Tag(random.String(16, random.Lowercase)), cmd) semaphore.Release() }() select { case <-timeout.Done(): - r.executeEndFunc(ctx, timeout.Err()) + r.EndFunc(ctx, timeout.Err()) return timeout.Err() case err := <-errs: - r.executeEndFunc(ctx, err) + r.EndFunc(ctx, err) return err } } - -// executeEndFunc execute functions -func (r *JobExecutor) executeEndFunc(ctx context.Context, err error) { - for _, f := range r.EndFunc { - go f(ctx, err) - } -} diff --git a/domain/service/runner/builder.go b/domain/service/runner/builder.go index 21d4ea2f..4e8e0158 100644 --- a/domain/service/runner/builder.go +++ b/domain/service/runner/builder.go @@ -11,20 +11,20 @@ func DefaultDockerRunnerBuilder() *builder { } type builder struct { - docker docker.Docker - logFuncs LogFuncs + docker docker.Docker + logFunc LogFunc } // LogFunc append a LogFunc func (b *builder) LogFunc(f LogFunc) *builder { - b.logFuncs = append(b.logFuncs, f) + b.logFunc = f return b } // Build returns a docker runner func (b *builder) Build() *dockerRunnerImpl { return &dockerRunnerImpl{ - Docker: b.docker, - LogFuncs: b.logFuncs, + Docker: b.docker, + LogFunc: b.logFunc, } } diff --git a/domain/service/runner/function.go b/domain/service/runner/function.go index 603fd481..5daab0a8 100644 --- a/domain/service/runner/function.go +++ b/domain/service/runner/function.go @@ -7,13 +7,3 @@ import ( // LogFunc is function of Log type LogFunc func(context.Context, Log) - -// LogFuncs is slice of LogFunc -type LogFuncs []LogFunc - -// Exec execute in goroutine -func (l LogFuncs) Exec(ctx context.Context, log Log) { - for _, f := range l { - go f(ctx, log) - } -} diff --git a/domain/service/runner/runner.go b/domain/service/runner/runner.go index bcf4428a..b47a4864 100644 --- a/domain/service/runner/runner.go +++ b/domain/service/runner/runner.go @@ -15,7 +15,7 @@ type DockerRunner interface { // dockerRunnerImpl is a implement of DockerRunner type dockerRunnerImpl struct { Docker - LogFuncs + LogFunc } // Run task in docker container @@ -55,7 +55,7 @@ func (r *dockerRunnerImpl) dockerBuild(ctx context.Context, dir string, tag dock if err != nil { return errors.WithStack(err) } - r.LogFuncs.Exec(ctx, buildLog) + r.LogFunc(ctx, buildLog) return nil } @@ -70,6 +70,6 @@ func (r *dockerRunnerImpl) dockerRun(ctx context.Context, dir string, tag docker if err != nil { return conID, errors.WithStack(err) } - r.LogFuncs.Exec(ctx, runLog) + r.LogFunc(ctx, runLog) return conID, nil } From 8f8a0c7ae4f3c235f06ac0c42a4c8337044e3842 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 1 Dec 2018 20:02:17 +0900 Subject: [PATCH 012/135] Add target model --- application/service/executor/executor.go | 12 +++- domain/model/job/target.go | 13 ++++ domain/model/job/target/local.go | 85 ++++++++++++++++++++++++ domain/service/runner/helper.go | 17 ++--- domain/service/runner/runner.go | 9 +-- 5 files changed, 122 insertions(+), 14 deletions(-) create mode 100644 domain/model/job/target.go create mode 100644 domain/model/job/target/local.go diff --git a/application/service/executor/executor.go b/application/service/executor/executor.go index 77221447..d5a4acbf 100644 --- a/application/service/executor/executor.go +++ b/application/service/executor/executor.go @@ -5,8 +5,10 @@ import ( "github.com/duck8823/duci/application" "github.com/duck8823/duci/application/semaphore" "github.com/duck8823/duci/domain/model/docker" + "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/service/runner" "github.com/labstack/gommon/random" + "github.com/pkg/errors" ) type JobExecutor struct { @@ -16,9 +18,15 @@ type JobExecutor struct { } // Execute job -func (r *JobExecutor) Execute(ctx context.Context, dir string, cmd ...string) error { +func (r *JobExecutor) Execute(ctx context.Context, target job.Target, cmd ...string) error { r.StartFunc(ctx) + workDir, cleanup, err := target.Prepare() + if err != nil { + return errors.WithStack(err) + } + defer cleanup() + errs := make(chan error, 1) timeout, cancel := context.WithTimeout(ctx, application.Config.Timeout()) @@ -26,7 +34,7 @@ func (r *JobExecutor) Execute(ctx context.Context, dir string, cmd ...string) er go func() { semaphore.Acquire() - errs <- r.DockerRunner.Run(timeout, dir, docker.Tag(random.String(16, random.Lowercase)), cmd) + errs <- r.DockerRunner.Run(timeout, workDir, docker.Tag(random.String(16, random.Lowercase)), cmd) semaphore.Release() }() diff --git a/domain/model/job/target.go b/domain/model/job/target.go new file mode 100644 index 00000000..26c615b7 --- /dev/null +++ b/domain/model/job/target.go @@ -0,0 +1,13 @@ +package job + +type Target interface { + Prepare() (WorkDir, Cleanup, error) +} + +type WorkDir string + +func (w WorkDir) ToString() string { + return string(w) +} + +type Cleanup func() error diff --git a/domain/model/job/target/local.go b/domain/model/job/target/local.go new file mode 100644 index 00000000..42fbbe00 --- /dev/null +++ b/domain/model/job/target/local.go @@ -0,0 +1,85 @@ +package target + +import ( + "github.com/duck8823/duci/domain/model/job" + "github.com/labstack/gommon/random" + "github.com/pkg/errors" + "io" + "io/ioutil" + "os" + "path" +) + +// Local is target with local directory +type Local struct { + Path string +} + +// Prepare working directory +func (l *Local) Prepare() (job.WorkDir, job.Cleanup, error) { + tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric, random.Numeric)) + if err := os.MkdirAll(tmpDir, 0700); err != nil { + return "", nil, errors.WithStack(err) + } + + if err := copyDir(tmpDir, l.Path); err != nil { + return "", nil, errors.WithStack(err) + } + + return job.WorkDir(tmpDir), cleanupFunc(tmpDir), nil +} + +func copyDir(dstDir string, srcDir string) error { + entries, err := ioutil.ReadDir(srcDir) + if err != nil { + return errors.WithStack(err) + } + + for _, entry := range entries { + dstPath := path.Join(dstDir, entry.Name()) + srcPath := path.Join(srcDir, entry.Name()) + + if entry.IsDir() { + if err := os.MkdirAll(dstPath, 0700); err != nil { + return errors.WithStack(err) + } + + if err := copyDir(dstPath, srcPath); err != nil { + return errors.WithStack(err) + } + } else if err := copyFile(dstPath, srcPath); err != nil { + return errors.WithStack(err) + } + } + + return nil +} + +func copyFile(dstFile string, srcFile string) error { + dst, err := os.OpenFile(dstFile, os.O_WRONLY|os.O_CREATE, 0600) + if err != nil { + return errors.WithStack(err) + } + defer dst.Close() + + src, err := os.Open(srcFile) + if err != nil { + return errors.WithStack(err) + } + defer src.Close() + + if _, err := io.Copy(dst, src); err != nil { + return errors.WithStack(err) + } + + return nil +} + +func cleanupFunc(path string) job.Cleanup { + return func() error { + if err := os.RemoveAll(path); err != nil { + return errors.WithStack(err) + } + return nil + } +} diff --git a/domain/service/runner/helper.go b/domain/service/runner/helper.go index 7823e250..09a897ee 100644 --- a/domain/service/runner/helper.go +++ b/domain/service/runner/helper.go @@ -3,6 +3,7 @@ package runner import ( "bytes" . "github.com/duck8823/duci/domain/model/docker" + "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/infrastructure/archive/tar" "github.com/pkg/errors" "gopkg.in/yaml.v2" @@ -12,15 +13,15 @@ import ( ) // createTarball creates a tar archive -func createTarball(workDir string) (*os.File, error) { - tarFilePath := filepath.Join(workDir, "duci.tar") +func createTarball(workDir job.WorkDir) (*os.File, error) { + tarFilePath := filepath.Join(workDir.ToString(), "duci.tar") writeFile, err := os.OpenFile(tarFilePath, os.O_RDWR|os.O_CREATE, 0600) if err != nil { return nil, errors.WithStack(err) } defer writeFile.Close() - if err := tar.Create(workDir, writeFile); err != nil { + if err := tar.Create(workDir.ToString(), writeFile); err != nil { return nil, errors.WithStack(err) } @@ -29,9 +30,9 @@ func createTarball(workDir string) (*os.File, error) { } // dockerfilePath returns a path to dockerfile for duci using -func dockerfilePath(workDir string) Dockerfile { +func dockerfilePath(workDir job.WorkDir) Dockerfile { dockerfile := "./Dockerfile" - if exists(filepath.Join(workDir, ".duci/Dockerfile")) { + if exists(filepath.Join(workDir.ToString(), ".duci/Dockerfile")) { dockerfile = ".duci/Dockerfile" } return Dockerfile(dockerfile) @@ -44,13 +45,13 @@ func exists(name string) bool { } // runtimeOptions parses a config.yml and returns a docker runtime options -func runtimeOptions(workDir string) (RuntimeOptions, error) { +func runtimeOptions(workDir job.WorkDir) (RuntimeOptions, error) { var opts RuntimeOptions - if !exists(filepath.Join(workDir, ".duci/config.yml")) { + if !exists(filepath.Join(workDir.ToString(), ".duci/config.yml")) { return opts, nil } - content, err := ioutil.ReadFile(filepath.Join(workDir, ".duci/config.yml")) + content, err := ioutil.ReadFile(filepath.Join(workDir.ToString(), ".duci/config.yml")) if err != nil { return opts, errors.WithStack(err) } diff --git a/domain/service/runner/runner.go b/domain/service/runner/runner.go index b47a4864..62535721 100644 --- a/domain/service/runner/runner.go +++ b/domain/service/runner/runner.go @@ -3,13 +3,14 @@ package runner import ( "context" "github.com/duck8823/duci/domain/model/docker" + "github.com/duck8823/duci/domain/model/job" . "github.com/duck8823/duci/domain/service/docker" "github.com/pkg/errors" ) // DockerRunner is a interface describes task runner. type DockerRunner interface { - Run(ctx context.Context, dir string, tag docker.Tag, cmd docker.Command) error + Run(ctx context.Context, dir job.WorkDir, tag docker.Tag, cmd docker.Command) error } // dockerRunnerImpl is a implement of DockerRunner @@ -19,7 +20,7 @@ type dockerRunnerImpl struct { } // Run task in docker container -func (r *dockerRunnerImpl) Run(ctx context.Context, dir string, tag docker.Tag, cmd docker.Command) error { +func (r *dockerRunnerImpl) Run(ctx context.Context, dir job.WorkDir, tag docker.Tag, cmd docker.Command) error { if err := r.dockerBuild(ctx, dir, tag); err != nil { return errors.WithStack(err) } @@ -44,7 +45,7 @@ func (r *dockerRunnerImpl) Run(ctx context.Context, dir string, tag docker.Tag, } // dockerBuild build a docker image -func (r *dockerRunnerImpl) dockerBuild(ctx context.Context, dir string, tag docker.Tag) error { +func (r *dockerRunnerImpl) dockerBuild(ctx context.Context, dir job.WorkDir, tag docker.Tag) error { tarball, err := createTarball(dir) if err != nil { return errors.WithStack(err) @@ -60,7 +61,7 @@ func (r *dockerRunnerImpl) dockerBuild(ctx context.Context, dir string, tag dock } // dockerRun run docker container -func (r *dockerRunnerImpl) dockerRun(ctx context.Context, dir string, tag docker.Tag, cmd docker.Command) (docker.ContainerID, error) { +func (r *dockerRunnerImpl) dockerRun(ctx context.Context, dir job.WorkDir, tag docker.Tag, cmd docker.Command) (docker.ContainerID, error) { opts, err := runtimeOptions(dir) if err != nil { return "", errors.WithStack(err) From a1d4d4bd2b8b21a62bdf3dc10f8a3ce60481c3a2 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 1 Dec 2018 21:11:44 +0900 Subject: [PATCH 013/135] Move package --- application/service/executor/executor.go | 2 +- domain/{service => model}/docker/docker.go | 1 - .../{service => model}/docker/third_pirty.go | 0 domain/{service => model}/runner/builder.go | 2 +- domain/{service => model}/runner/errors.go | 0 domain/{service => model}/runner/function.go | 0 domain/{service => model}/runner/helper.go | 0 domain/{service => model}/runner/runner.go | 3 +- main.go | 32 +++++++++++++++++-- 9 files changed, 32 insertions(+), 8 deletions(-) rename domain/{service => model}/docker/docker.go (98%) rename domain/{service => model}/docker/third_pirty.go (100%) rename domain/{service => model}/runner/builder.go (91%) rename domain/{service => model}/runner/errors.go (100%) rename domain/{service => model}/runner/function.go (100%) rename domain/{service => model}/runner/helper.go (100%) rename domain/{service => model}/runner/runner.go (96%) diff --git a/application/service/executor/executor.go b/application/service/executor/executor.go index d5a4acbf..76440b6c 100644 --- a/application/service/executor/executor.go +++ b/application/service/executor/executor.go @@ -6,7 +6,7 @@ import ( "github.com/duck8823/duci/application/semaphore" "github.com/duck8823/duci/domain/model/docker" "github.com/duck8823/duci/domain/model/job" - "github.com/duck8823/duci/domain/service/runner" + "github.com/duck8823/duci/domain/model/runner" "github.com/labstack/gommon/random" "github.com/pkg/errors" ) diff --git a/domain/service/docker/docker.go b/domain/model/docker/docker.go similarity index 98% rename from domain/service/docker/docker.go rename to domain/model/docker/docker.go index e3ffec2c..d83eb74a 100644 --- a/domain/service/docker/docker.go +++ b/domain/model/docker/docker.go @@ -5,7 +5,6 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" moby "github.com/docker/docker/client" - . "github.com/duck8823/duci/domain/model/docker" . "github.com/duck8823/duci/domain/model/job" "github.com/pkg/errors" "io" diff --git a/domain/service/docker/third_pirty.go b/domain/model/docker/third_pirty.go similarity index 100% rename from domain/service/docker/third_pirty.go rename to domain/model/docker/third_pirty.go diff --git a/domain/service/runner/builder.go b/domain/model/runner/builder.go similarity index 91% rename from domain/service/runner/builder.go rename to domain/model/runner/builder.go index 4e8e0158..5183a794 100644 --- a/domain/service/runner/builder.go +++ b/domain/model/runner/builder.go @@ -1,7 +1,7 @@ package runner import ( - "github.com/duck8823/duci/domain/service/docker" + "github.com/duck8823/duci/domain/model/docker" ) // DefaultDockerRunnerBuilder create new builder of docker runner diff --git a/domain/service/runner/errors.go b/domain/model/runner/errors.go similarity index 100% rename from domain/service/runner/errors.go rename to domain/model/runner/errors.go diff --git a/domain/service/runner/function.go b/domain/model/runner/function.go similarity index 100% rename from domain/service/runner/function.go rename to domain/model/runner/function.go diff --git a/domain/service/runner/helper.go b/domain/model/runner/helper.go similarity index 100% rename from domain/service/runner/helper.go rename to domain/model/runner/helper.go diff --git a/domain/service/runner/runner.go b/domain/model/runner/runner.go similarity index 96% rename from domain/service/runner/runner.go rename to domain/model/runner/runner.go index 62535721..fcfba8eb 100644 --- a/domain/service/runner/runner.go +++ b/domain/model/runner/runner.go @@ -4,7 +4,6 @@ import ( "context" "github.com/duck8823/duci/domain/model/docker" "github.com/duck8823/duci/domain/model/job" - . "github.com/duck8823/duci/domain/service/docker" "github.com/pkg/errors" ) @@ -15,7 +14,7 @@ type DockerRunner interface { // dockerRunnerImpl is a implement of DockerRunner type dockerRunnerImpl struct { - Docker + docker.Docker LogFunc } diff --git a/main.go b/main.go index d71b1ebe..d8422434 100644 --- a/main.go +++ b/main.go @@ -1,10 +1,36 @@ package main import ( - "github.com/duck8823/duci/application/cmd" - "os" + "context" + "fmt" + "github.com/duck8823/duci/application/service/executor" + "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/job/target" + "github.com/duck8823/duci/domain/model/runner" ) func main() { - cmd.Execute(os.Args[1:]) + e := &executor.JobExecutor{ + DockerRunner: runner. + DefaultDockerRunnerBuilder(). + LogFunc(func(_ context.Context, log job.Log) { + for line, err := log.ReadLine(); err == nil; line, err = log.ReadLine() { + println(line.Message) + } + }). + Build(), + StartFunc: func(_ context.Context) { + println("Job Started") + }, + EndFunc: func(_ context.Context, err error) { + if err != nil { + println(fmt.Sprintf("%+v", err)) + } + println("Job End") + }, + } + + if err := e.Execute(context.Background(), &target.Local{Path: "."}); err != nil { + println(fmt.Sprintf("%+v", err)) + } } From 56d994363bacde2bbadc513f40fe84fd4b71b061 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 1 Dec 2018 21:13:32 +0900 Subject: [PATCH 014/135] Change import --- domain/model/docker/log.go | 12 ++++++------ domain/model/runner/function.go | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/domain/model/docker/log.go b/domain/model/docker/log.go index 3704eff2..a68a5c26 100644 --- a/domain/model/docker/log.go +++ b/domain/model/docker/log.go @@ -5,7 +5,7 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/duck8823/duci/domain/model/job" + . "github.com/duck8823/duci/domain/model/job" "github.com/pkg/errors" "io" "time" @@ -23,12 +23,12 @@ func NewBuildLog(r io.Reader) *buildLogger { } // ReadLine returns LogLine. -func (l *buildLogger) ReadLine() (*job.LogLine, error) { +func (l *buildLogger) ReadLine() (*LogLine, error) { for { line, _, readErr := l.reader.ReadLine() msg := extractMessage(line) if readErr == io.EOF { - return &job.LogLine{Timestamp: now(), Message: msg}, readErr + return &LogLine{Timestamp: now(), Message: msg}, readErr } if readErr != nil { return nil, errors.WithStack(readErr) @@ -38,7 +38,7 @@ func (l *buildLogger) ReadLine() (*job.LogLine, error) { continue } - return &job.LogLine{Timestamp: now(), Message: msg}, readErr + return &LogLine{Timestamp: now(), Message: msg}, readErr } } @@ -52,7 +52,7 @@ func NewRunLog(r io.Reader) *runLogger { } // ReadLine returns LogLine. -func (l *runLogger) ReadLine() (*job.LogLine, error) { +func (l *runLogger) ReadLine() (*LogLine, error) { for { line, _, readErr := l.reader.ReadLine() if readErr != nil && readErr != io.EOF { @@ -66,7 +66,7 @@ func (l *runLogger) ReadLine() (*job.LogLine, error) { // prevent to CR progress := bytes.Split(messages, []byte{'\r'}) - return &job.LogLine{Timestamp: now(), Message: string(progress[0])}, readErr + return &LogLine{Timestamp: now(), Message: string(progress[0])}, readErr } } diff --git a/domain/model/runner/function.go b/domain/model/runner/function.go index 5daab0a8..494a6b60 100644 --- a/domain/model/runner/function.go +++ b/domain/model/runner/function.go @@ -2,8 +2,8 @@ package runner import ( "context" - . "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/job" ) // LogFunc is function of Log -type LogFunc func(context.Context, Log) +type LogFunc func(context.Context, job.Log) From b702f4106b5677c5692e34f56b113720c411e653 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 1 Dec 2018 21:17:54 +0900 Subject: [PATCH 015/135] Rename struct --- domain/model/docker/docker.go | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/domain/model/docker/docker.go b/domain/model/docker/docker.go index d83eb74a..fdf719ce 100644 --- a/domain/model/docker/docker.go +++ b/domain/model/docker/docker.go @@ -20,27 +20,27 @@ type Docker interface { Status() error } -type dockerService struct { +type client struct { moby Moby } -// New returns instance of docker service +// New returns instance of docker client func New() (Docker, error) { cli, err := moby.NewClientWithOpts(moby.FromEnv) if err != nil { return nil, errors.WithStack(err) } - return &dockerService{moby: cli}, nil + return &client{moby: cli}, nil } // Build a docker image. -func (s *dockerService) Build(ctx context.Context, file io.Reader, tag Tag, dockerfile Dockerfile) (Log, error) { +func (c *client) Build(ctx context.Context, file io.Reader, tag Tag, dockerfile Dockerfile) (Log, error) { opts := types.ImageBuildOptions{ Tags: []string{tag.ToString()}, Dockerfile: dockerfile.ToString(), Remove: true, } - resp, err := s.moby.ImageBuild(ctx, file, opts) + resp, err := c.moby.ImageBuild(ctx, file, opts) if err != nil { return nil, errors.WithStack(err) } @@ -49,8 +49,8 @@ func (s *dockerService) Build(ctx context.Context, file io.Reader, tag Tag, dock } // Run docker container with command. -func (s *dockerService) Run(ctx context.Context, opts RuntimeOptions, tag Tag, cmd Command) (ContainerID, Log, error) { - con, err := s.moby.ContainerCreate(ctx, &container.Config{ +func (c *client) Run(ctx context.Context, opts RuntimeOptions, tag Tag, cmd Command) (ContainerID, Log, error) { + con, err := c.moby.ContainerCreate(ctx, &container.Config{ Image: tag.ToString(), Env: opts.Environments.ToArray(), Volumes: opts.Volumes.ToMap(), @@ -62,11 +62,11 @@ func (s *dockerService) Run(ctx context.Context, opts RuntimeOptions, tag Tag, c return "", nil, errors.WithStack(err) } - if err := s.moby.ContainerStart(ctx, con.ID, types.ContainerStartOptions{}); err != nil { + if err := c.moby.ContainerStart(ctx, con.ID, types.ContainerStartOptions{}); err != nil { return ContainerID(con.ID), nil, errors.WithStack(err) } - logs, err := s.moby.ContainerLogs(ctx, con.ID, types.ContainerLogsOptions{ + logs, err := c.moby.ContainerLogs(ctx, con.ID, types.ContainerLogsOptions{ ShowStdout: true, ShowStderr: true, Follow: true, @@ -79,24 +79,24 @@ func (s *dockerService) Run(ctx context.Context, opts RuntimeOptions, tag Tag, c } // RemoveContainer remove docker container. -func (s *dockerService) RemoveContainer(ctx context.Context, conID ContainerID) error { - if err := s.moby.ContainerRemove(ctx, conID.ToString(), types.ContainerRemoveOptions{}); err != nil { +func (c *client) RemoveContainer(ctx context.Context, conID ContainerID) error { + if err := c.moby.ContainerRemove(ctx, conID.ToString(), types.ContainerRemoveOptions{}); err != nil { return errors.WithStack(err) } return nil } // RemoveImage remove docker image. -func (s *dockerService) RemoveImage(ctx context.Context, tag Tag) error { - if _, err := s.moby.ImageRemove(ctx, tag.ToString(), types.ImageRemoveOptions{}); err != nil { +func (c *client) RemoveImage(ctx context.Context, tag Tag) error { + if _, err := c.moby.ImageRemove(ctx, tag.ToString(), types.ImageRemoveOptions{}); err != nil { return errors.WithStack(err) } return nil } // ExitCode returns exit code specific container id. -func (s *dockerService) ExitCode(ctx context.Context, conID ContainerID) (ExitCode, error) { - body, err := s.moby.ContainerWait(ctx, conID.ToString(), container.WaitConditionNotRunning) +func (c *client) ExitCode(ctx context.Context, conID ContainerID) (ExitCode, error) { + body, err := c.moby.ContainerWait(ctx, conID.ToString(), container.WaitConditionNotRunning) select { case b := <-body: return ExitCode(b.StatusCode), nil @@ -106,8 +106,8 @@ func (s *dockerService) ExitCode(ctx context.Context, conID ContainerID) (ExitCo } // Status returns error of docker daemon status. -func (s *dockerService) Status() error { - if _, err := s.moby.Info(context.Background()); err != nil { +func (c *client) Status() error { + if _, err := c.moby.Info(context.Background()); err != nil { return errors.Wrap(err, "Couldn't connect to Docker daemon.") } return nil From fb910a17b67f13de865ff6866a1be5d77890c89a Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 1 Dec 2018 21:51:24 +0900 Subject: [PATCH 016/135] Revert: commit b702f4106b5677c5692e34f56b113720c411e653 --- main.go | 32 +++----------------------------- 1 file changed, 3 insertions(+), 29 deletions(-) diff --git a/main.go b/main.go index d8422434..d71b1ebe 100644 --- a/main.go +++ b/main.go @@ -1,36 +1,10 @@ package main import ( - "context" - "fmt" - "github.com/duck8823/duci/application/service/executor" - "github.com/duck8823/duci/domain/model/job" - "github.com/duck8823/duci/domain/model/job/target" - "github.com/duck8823/duci/domain/model/runner" + "github.com/duck8823/duci/application/cmd" + "os" ) func main() { - e := &executor.JobExecutor{ - DockerRunner: runner. - DefaultDockerRunnerBuilder(). - LogFunc(func(_ context.Context, log job.Log) { - for line, err := log.ReadLine(); err == nil; line, err = log.ReadLine() { - println(line.Message) - } - }). - Build(), - StartFunc: func(_ context.Context) { - println("Job Started") - }, - EndFunc: func(_ context.Context, err error) { - if err != nil { - println(fmt.Sprintf("%+v", err)) - } - println("Job End") - }, - } - - if err := e.Execute(context.Background(), &target.Local{Path: "."}); err != nil { - println(fmt.Sprintf("%+v", err)) - } + cmd.Execute(os.Args[1:]) } From e431df6437b88a56b07d92c3dabec3d6fe535df9 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sun, 2 Dec 2018 14:19:25 +0900 Subject: [PATCH 017/135] Add github push target --- application/service/git/mock_git/git.go | 2 +- .../service/github/mock_github/github.go | 4 +- domain/model/job/target/git/git.go | 37 ++++++++++++ domain/model/job/target/git/http_client.go | 36 +++++++++++ domain/model/job/target/git/log.go | 58 ++++++++++++++++++ domain/model/job/target/git/ssh_client.go | 44 ++++++++++++++ domain/model/job/target/github/github.go | 60 +++++++++++++++++++ domain/model/job/target/github/repository.go | 43 +++++++++++++ domain/model/job/target/github/state.go | 15 +++++ .../model/job/target/github/target_point.go | 7 +++ .../model/job/target/github/target_source.go | 22 +++++++ domain/model/job/target/github_push.go | 43 +++++++++++++ 12 files changed, 368 insertions(+), 3 deletions(-) create mode 100644 domain/model/job/target/git/git.go create mode 100644 domain/model/job/target/git/http_client.go create mode 100644 domain/model/job/target/git/log.go create mode 100644 domain/model/job/target/git/ssh_client.go create mode 100644 domain/model/job/target/github/github.go create mode 100644 domain/model/job/target/github/repository.go create mode 100644 domain/model/job/target/github/state.go create mode 100644 domain/model/job/target/github/target_point.go create mode 100644 domain/model/job/target/github/target_source.go create mode 100644 domain/model/job/target/github_push.go diff --git a/application/service/git/mock_git/git.go b/application/service/git/mock_git/git.go index d34a8bc8..6ed0dbe7 100644 --- a/application/service/git/mock_git/git.go +++ b/application/service/git/mock_git/git.go @@ -11,7 +11,7 @@ import ( reflect "reflect" ) -// MockService is a mock of Service interface +// MockService is a mock of Git interface type MockService struct { ctrl *gomock.Controller recorder *MockServiceMockRecorder diff --git a/application/service/github/mock_github/github.go b/application/service/github/mock_github/github.go index a469778e..37b521d5 100644 --- a/application/service/github/mock_github/github.go +++ b/application/service/github/mock_github/github.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: application/service/github/github.go +// Source: application/service/github/github_push.go // Package mock_github is a generated GoMock package. package mock_github @@ -11,7 +11,7 @@ import ( reflect "reflect" ) -// MockService is a mock of Service interface +// MockService is a mock of GitHub interface type MockService struct { ctrl *gomock.Controller recorder *MockServiceMockRecorder diff --git a/domain/model/job/target/git/git.go b/domain/model/job/target/git/git.go new file mode 100644 index 00000000..d0a5c706 --- /dev/null +++ b/domain/model/job/target/git/git.go @@ -0,0 +1,37 @@ +package git + +import ( + "context" + "github.com/pkg/errors" + "gopkg.in/src-d/go-git.v4" + "gopkg.in/src-d/go-git.v4/plumbing" +) + +// TargetSource is a interface returns clone URLs, Ref and SHA for target +type TargetSource interface { + GetSSHURL() string + GetCloneURL() string + GetRef() string + GetSHA() plumbing.Hash +} + +// Git describes a git service. +type Git interface { + Clone(ctx context.Context, dir string, src TargetSource) error +} + +func checkout(repo *git.Repository, sha plumbing.Hash) error { + wt, err := repo.Worktree() + if err != nil { + return errors.WithStack(err) + } + + if err := wt.Checkout(&git.CheckoutOptions{ + Hash: sha, + Branch: plumbing.ReferenceName(sha.String()), + Create: true, + }); err != nil { + return errors.WithStack(err) + } + return nil +} diff --git a/domain/model/job/target/git/http_client.go b/domain/model/job/target/git/http_client.go new file mode 100644 index 00000000..37f1d0c8 --- /dev/null +++ b/domain/model/job/target/git/http_client.go @@ -0,0 +1,36 @@ +package git + +import ( + "context" + "github.com/duck8823/duci/domain/model/runner" + "github.com/pkg/errors" + "gopkg.in/src-d/go-git.v4" + "gopkg.in/src-d/go-git.v4/plumbing" +) + +type httpGitClient struct { + runner.LogFunc +} + +// NewWithHTTP returns git client with http protocol +func NewWithHTTP(logFunc runner.LogFunc) *httpGitClient { + return &httpGitClient{LogFunc: logFunc} +} + +// Clone a repository into the path with target source. +func (s *httpGitClient) Clone(ctx context.Context, dir string, src TargetSource) error { + gitRepository, err := git.PlainClone(dir, false, &git.CloneOptions{ + URL: src.GetCloneURL(), + Progress: &ProgressLogger{ctx: ctx, LogFunc: s.LogFunc}, + ReferenceName: plumbing.ReferenceName(src.GetRef()), + Depth: 1, + }) + if err != nil { + return errors.WithStack(err) + } + + if err := checkout(gitRepository, src.GetSHA()); err != nil { + return errors.WithStack(err) + } + return nil +} diff --git a/domain/model/job/target/git/log.go b/domain/model/job/target/git/log.go new file mode 100644 index 00000000..1fc9477d --- /dev/null +++ b/domain/model/job/target/git/log.go @@ -0,0 +1,58 @@ +package git + +import ( + "bufio" + "context" + "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/runner" + "github.com/pkg/errors" + "io" + "regexp" + "strings" + "time" +) + +var now = time.Now + +type cloneLogger struct { + reader *bufio.Reader +} + +// ReadLine returns LogLine. +func (l *cloneLogger) ReadLine() (*job.LogLine, error) { + for { + line, _, readErr := l.reader.ReadLine() + msg := string(line) + if readErr == io.EOF { + return &job.LogLine{Timestamp: now(), Message: msg}, readErr + } + if readErr != nil { + return nil, errors.WithStack(readErr) + } + + if len(line) == 0 { + continue + } + + return &job.LogLine{Timestamp: now(), Message: msg}, readErr + } +} + +// Regexp to remove CR or later (inline progress) +var rep = regexp.MustCompile("\r.*$") + +// ProgressLogger is a writer for git progress +type ProgressLogger struct { + ctx context.Context + runner.LogFunc +} + +// Write a log without CR or later. +func (l *ProgressLogger) Write(p []byte) (n int, err error) { + msg := rep.ReplaceAllString(string(p), "") + log := &cloneLogger{ + reader: bufio.NewReader(strings.NewReader(msg)), + } + l.LogFunc(l.ctx, log) + return 0, nil +} diff --git a/domain/model/job/target/git/ssh_client.go b/domain/model/job/target/git/ssh_client.go new file mode 100644 index 00000000..3a02b422 --- /dev/null +++ b/domain/model/job/target/git/ssh_client.go @@ -0,0 +1,44 @@ +package git + +import ( + "context" + "github.com/duck8823/duci/domain/model/runner" + "github.com/pkg/errors" + "gopkg.in/src-d/go-git.v4" + "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/transport" + "gopkg.in/src-d/go-git.v4/plumbing/transport/ssh" +) + +type sshGitClient struct { + auth transport.AuthMethod + runner.LogFunc +} + +// NewWithSSH returns git client with ssh protocol +func NewWithSSH(path string, logFunc runner.LogFunc) (*sshGitClient, error) { + auth, err := ssh.NewPublicKeysFromFile("git", path, "") + if err != nil { + return nil, err + } + return &sshGitClient{auth: auth, LogFunc: logFunc}, nil +} + +// Clone a repository into the path with target source. +func (s *sshGitClient) Clone(ctx context.Context, dir string, src TargetSource) error { + gitRepository, err := git.PlainClone(dir, false, &git.CloneOptions{ + URL: src.GetSSHURL(), + Auth: s.auth, + Progress: &ProgressLogger{ctx: ctx, LogFunc: s.LogFunc}, + ReferenceName: plumbing.ReferenceName(src.GetRef()), + Depth: 1, + }) + if err != nil { + return errors.WithStack(err) + } + + if err := checkout(gitRepository, src.GetSHA()); err != nil { + return errors.WithStack(err) + } + return nil +} diff --git a/domain/model/job/target/github/github.go b/domain/model/job/target/github/github.go new file mode 100644 index 00000000..84e409bc --- /dev/null +++ b/domain/model/job/target/github/github.go @@ -0,0 +1,60 @@ +package github + +import ( + "context" + "github.com/duck8823/duci/application/service/github" + go_github "github.com/google/go-github/github" + "github.com/pkg/errors" + "golang.org/x/oauth2" +) + +// GitHub describes a github client. +type GitHub interface { + GetPullRequest(ctx context.Context, repo github.Repository, num int) (*go_github.PullRequest, error) +} + +type client struct { + cli *go_github.Client +} + +var instance GitHub + +// Initialize create a github client. +func Initialize(token string) (GitHub, error) { + if instance != nil { + return nil, errors.New("instance already initialized.") + } + + ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token}) + tc := oauth2.NewClient(context.Background(), ts) + + return &client{go_github.NewClient(tc)}, nil +} + +// GetInstance returns a github client +func GetInstance() (GitHub, error) { + if instance == nil { + return nil, errors.New("instance still not initialized.") + } + + return instance, nil +} + +// GetPullRequest returns a pull request with specific repository and number. +func (c *client) GetPullRequest(ctx context.Context, repo github.Repository, num int) (*go_github.PullRequest, error) { + ownerName, repoName, err := RepositoryName(repo.GetFullName()).Split() + if err != nil { + return nil, errors.WithStack(err) + } + + pr, _, err := c.cli.PullRequests.Get( + ctx, + ownerName, + repoName, + num, + ) + if err != nil { + return nil, errors.WithStack(err) + } + return pr, nil +} diff --git a/domain/model/job/target/github/repository.go b/domain/model/job/target/github/repository.go new file mode 100644 index 00000000..cb193bdd --- /dev/null +++ b/domain/model/job/target/github/repository.go @@ -0,0 +1,43 @@ +package github + +import ( + "fmt" + "strings" +) + +// Repository is a github repository +type Repository interface { + GetFullName() string + GetSSHURL() string + GetCloneURL() string +} + +// RepositoryName is a github repository name. +type RepositoryName string + +// Owner get a repository owner. +func (r RepositoryName) Owner() (string, error) { + ss := strings.Split(string(r), "/") + if len(ss) != 2 { + return "", fmt.Errorf("Invalid repository name: %s ", r) + } + return ss[0], nil +} + +// Repo get a repository name without owner. +func (r RepositoryName) Repo() (string, error) { + ss := strings.Split(string(r), "/") + if len(ss) != 2 { + return "", fmt.Errorf("Invalid repository name: %s ", r) + } + return ss[1], nil +} + +// Split repository name to owner and repo +func (r RepositoryName) Split() (owner string, repo string, err error) { + ss := strings.Split(string(r), "/") + if len(ss) != 2 { + return "", "", fmt.Errorf("Invalid repository name: %s ", r) + } + return ss[0], ss[1], nil +} diff --git a/domain/model/job/target/github/state.go b/domain/model/job/target/github/state.go new file mode 100644 index 00000000..fdc365e2 --- /dev/null +++ b/domain/model/job/target/github/state.go @@ -0,0 +1,15 @@ +package github + +// State represents state of commit status +type State = string + +const ( + // PENDING represents pending state. + PENDING State = "pending" + // SUCCESS represents success state. + SUCCESS State = "success" + // ERROR represents error state. + ERROR State = "error" + // FAILURE represents failure state. + FAILURE State = "failure" +) diff --git a/domain/model/job/target/github/target_point.go b/domain/model/job/target/github/target_point.go new file mode 100644 index 00000000..40a03911 --- /dev/null +++ b/domain/model/job/target/github/target_point.go @@ -0,0 +1,7 @@ +package github + +// TargetPoint represents a target point for clone. +type TargetPoint interface { + GetRef() string + GetHead() string +} diff --git a/domain/model/job/target/github/target_source.go b/domain/model/job/target/github/target_source.go new file mode 100644 index 00000000..6181d951 --- /dev/null +++ b/domain/model/job/target/github/target_source.go @@ -0,0 +1,22 @@ +package github + +import ( + "gopkg.in/src-d/go-git.v4/plumbing" +) + +// TargetSource stores Repo, Ref and SHA for target +type TargetSource struct { + Repository + Ref string + SHA plumbing.Hash +} + +// GetRef returns a ref +func (s *TargetSource) GetRef() string { + return s.Ref +} + +// GetSHA returns a hash +func (s *TargetSource) GetSHA() plumbing.Hash { + return s.SHA +} diff --git a/domain/model/job/target/github_push.go b/domain/model/job/target/github_push.go new file mode 100644 index 00000000..20d7f508 --- /dev/null +++ b/domain/model/job/target/github_push.go @@ -0,0 +1,43 @@ +package target + +import ( + "context" + "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/job/target/git" + "github.com/duck8823/duci/domain/model/job/target/github" + "github.com/labstack/gommon/random" + "github.com/pkg/errors" + "gopkg.in/src-d/go-git.v4/plumbing" + "os" + "path" +) + +// GitHub is target with github repository +type GitHubPush struct { + Repo github.Repository + Point github.TargetPoint +} + +// Prepare working directory +func (g *GitHubPush) Prepare() (job.WorkDir, job.Cleanup, error) { + tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric, random.Numeric)) + if err := os.MkdirAll(tmpDir, 0700); err != nil { + return "", nil, errors.WithStack(err) + } + + // FIXME: switch client + cli := git.NewWithHTTP(func(_ context.Context, log job.Log) { + for line, err := log.ReadLine(); err == nil; line, err = log.ReadLine() { + println(line.Message) + } + }) + if err := cli.Clone(context.Background(), tmpDir, &github.TargetSource{ + Repository: g.Repo, + Ref: g.Point.GetRef(), + SHA: plumbing.NewHash(g.Point.GetHead()), + }); err != nil { + return "", nil, errors.WithStack(err) + } + + return job.WorkDir(tmpDir), cleanupFunc(tmpDir), nil +} From a6f39be6cfaffaa9c960ededc4d40f5aacff15a4 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sun, 2 Dec 2018 14:25:22 +0900 Subject: [PATCH 018/135] Fix to be able to checkout past commit --- domain/model/job/target/git/http_client.go | 1 - domain/model/job/target/git/ssh_client.go | 1 - 2 files changed, 2 deletions(-) diff --git a/domain/model/job/target/git/http_client.go b/domain/model/job/target/git/http_client.go index 37f1d0c8..f4371ba8 100644 --- a/domain/model/job/target/git/http_client.go +++ b/domain/model/job/target/git/http_client.go @@ -23,7 +23,6 @@ func (s *httpGitClient) Clone(ctx context.Context, dir string, src TargetSource) URL: src.GetCloneURL(), Progress: &ProgressLogger{ctx: ctx, LogFunc: s.LogFunc}, ReferenceName: plumbing.ReferenceName(src.GetRef()), - Depth: 1, }) if err != nil { return errors.WithStack(err) diff --git a/domain/model/job/target/git/ssh_client.go b/domain/model/job/target/git/ssh_client.go index 3a02b422..6ddc6af0 100644 --- a/domain/model/job/target/git/ssh_client.go +++ b/domain/model/job/target/git/ssh_client.go @@ -31,7 +31,6 @@ func (s *sshGitClient) Clone(ctx context.Context, dir string, src TargetSource) Auth: s.auth, Progress: &ProgressLogger{ctx: ctx, LogFunc: s.LogFunc}, ReferenceName: plumbing.ReferenceName(src.GetRef()), - Depth: 1, }) if err != nil { return errors.WithStack(err) From 186a24c1c61bd2ba2992565d7999ae656f16d14e Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sun, 2 Dec 2018 16:41:46 +0900 Subject: [PATCH 019/135] Add initialize method --- domain/model/job/target/git/git.go | 11 +++++++++++ domain/model/job/target/git/http_client.go | 11 ++++++++--- domain/model/job/target/git/ssh_client.go | 14 ++++++++++---- domain/model/job/target/github/github.go | 11 ++++++----- domain/model/job/target/github_push.go | 11 +++++------ 5 files changed, 40 insertions(+), 18 deletions(-) diff --git a/domain/model/job/target/git/git.go b/domain/model/job/target/git/git.go index d0a5c706..969a5bca 100644 --- a/domain/model/job/target/git/git.go +++ b/domain/model/job/target/git/git.go @@ -7,6 +7,8 @@ import ( "gopkg.in/src-d/go-git.v4/plumbing" ) +var instance Git + // TargetSource is a interface returns clone URLs, Ref and SHA for target type TargetSource interface { GetSSHURL() string @@ -20,6 +22,15 @@ type Git interface { Clone(ctx context.Context, dir string, src TargetSource) error } +// GetInstance returns a git client +func GetInstance() (Git, error) { + if instance == nil { + return nil, errors.New("instance still not initialized.") + } + + return instance, nil +} + func checkout(repo *git.Repository, sha plumbing.Hash) error { wt, err := repo.Worktree() if err != nil { diff --git a/domain/model/job/target/git/http_client.go b/domain/model/job/target/git/http_client.go index f4371ba8..c830c5a9 100644 --- a/domain/model/job/target/git/http_client.go +++ b/domain/model/job/target/git/http_client.go @@ -12,9 +12,14 @@ type httpGitClient struct { runner.LogFunc } -// NewWithHTTP returns git client with http protocol -func NewWithHTTP(logFunc runner.LogFunc) *httpGitClient { - return &httpGitClient{LogFunc: logFunc} +// InitializeWithHTTP initialize git client with http protocol +func InitializeWithHTTP(logFunc runner.LogFunc) error { + if instance != nil { + return errors.New("instance already initialized.") + } + + instance = &httpGitClient{LogFunc: logFunc} + return nil } // Clone a repository into the path with target source. diff --git a/domain/model/job/target/git/ssh_client.go b/domain/model/job/target/git/ssh_client.go index 6ddc6af0..db34bd26 100644 --- a/domain/model/job/target/git/ssh_client.go +++ b/domain/model/job/target/git/ssh_client.go @@ -15,13 +15,19 @@ type sshGitClient struct { runner.LogFunc } -// NewWithSSH returns git client with ssh protocol -func NewWithSSH(path string, logFunc runner.LogFunc) (*sshGitClient, error) { +// InitializeWithSSH returns git client with ssh protocol +func InitializeWithSSH(path string, logFunc runner.LogFunc) error { + if instance != nil { + return errors.New("instance already initialized.") + } + auth, err := ssh.NewPublicKeysFromFile("git", path, "") if err != nil { - return nil, err + return err } - return &sshGitClient{auth: auth, LogFunc: logFunc}, nil + + instance = &sshGitClient{auth: auth, LogFunc: logFunc} + return nil } // Clone a repository into the path with target source. diff --git a/domain/model/job/target/github/github.go b/domain/model/job/target/github/github.go index 84e409bc..1c7cabbb 100644 --- a/domain/model/job/target/github/github.go +++ b/domain/model/job/target/github/github.go @@ -8,6 +8,8 @@ import ( "golang.org/x/oauth2" ) +var instance GitHub + // GitHub describes a github client. type GitHub interface { GetPullRequest(ctx context.Context, repo github.Repository, num int) (*go_github.PullRequest, error) @@ -17,18 +19,17 @@ type client struct { cli *go_github.Client } -var instance GitHub - // Initialize create a github client. -func Initialize(token string) (GitHub, error) { +func Initialize(token string) error { if instance != nil { - return nil, errors.New("instance already initialized.") + return errors.New("instance already initialized.") } ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token}) tc := oauth2.NewClient(context.Background(), ts) - return &client{go_github.NewClient(tc)}, nil + instance = &client{go_github.NewClient(tc)} + return nil } // GetInstance returns a github client diff --git a/domain/model/job/target/github_push.go b/domain/model/job/target/github_push.go index 20d7f508..13546d7b 100644 --- a/domain/model/job/target/github_push.go +++ b/domain/model/job/target/github_push.go @@ -25,12 +25,11 @@ func (g *GitHubPush) Prepare() (job.WorkDir, job.Cleanup, error) { return "", nil, errors.WithStack(err) } - // FIXME: switch client - cli := git.NewWithHTTP(func(_ context.Context, log job.Log) { - for line, err := log.ReadLine(); err == nil; line, err = log.ReadLine() { - println(line.Message) - } - }) + cli, err := git.GetInstance() + if err != nil { + return "", nil, errors.WithStack(err) + } + if err := cli.Clone(context.Background(), tmpDir, &github.TargetSource{ Repository: g.Repo, Ref: g.Point.GetRef(), From 9516ecf7929862f4c20d8013aeadd26a7085f9d7 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sun, 2 Dec 2018 16:42:31 +0900 Subject: [PATCH 020/135] Add nothing to do function and set as default --- domain/model/runner/builder.go | 12 ++++++------ domain/model/runner/function.go | 3 +++ domain/model/runner/runner.go | 1 + 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/domain/model/runner/builder.go b/domain/model/runner/builder.go index 5183a794..e6761f81 100644 --- a/domain/model/runner/builder.go +++ b/domain/model/runner/builder.go @@ -4,17 +4,17 @@ import ( "github.com/duck8823/duci/domain/model/docker" ) -// DefaultDockerRunnerBuilder create new builder of docker runner -func DefaultDockerRunnerBuilder() *builder { - cli, _ := docker.New() - return &builder{docker: cli} -} - type builder struct { docker docker.Docker logFunc LogFunc } +// DefaultDockerRunnerBuilder create new builder of docker runner +func DefaultDockerRunnerBuilder() *builder { + cli, _ := docker.New() + return &builder{docker: cli, logFunc: NothingToDo} +} + // LogFunc append a LogFunc func (b *builder) LogFunc(f LogFunc) *builder { b.logFunc = f diff --git a/domain/model/runner/function.go b/domain/model/runner/function.go index 494a6b60..ac259a09 100644 --- a/domain/model/runner/function.go +++ b/domain/model/runner/function.go @@ -7,3 +7,6 @@ import ( // LogFunc is function of Log type LogFunc func(context.Context, job.Log) + +// NothingToDo is function nothing to do +var NothingToDo = func(_ context.Context, _ job.Log) {} diff --git a/domain/model/runner/runner.go b/domain/model/runner/runner.go index fcfba8eb..16032fba 100644 --- a/domain/model/runner/runner.go +++ b/domain/model/runner/runner.go @@ -24,6 +24,7 @@ func (r *dockerRunnerImpl) Run(ctx context.Context, dir job.WorkDir, tag docker. return errors.WithStack(err) } + // TODO: wait building container conID, err := r.dockerRun(ctx, dir, tag, cmd) if err != nil { return errors.WithStack(err) From c9e9a004da998cce239bd6cc013541568961d779 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sun, 2 Dec 2018 16:58:35 +0900 Subject: [PATCH 021/135] Change log replace method --- domain/model/job/target/git/log.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/domain/model/job/target/git/log.go b/domain/model/job/target/git/log.go index 1fc9477d..61939eb8 100644 --- a/domain/model/job/target/git/log.go +++ b/domain/model/job/target/git/log.go @@ -2,13 +2,13 @@ package git import ( "bufio" + "bytes" "context" "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/runner" "github.com/pkg/errors" "io" "regexp" - "strings" "time" ) @@ -23,6 +23,7 @@ func (l *cloneLogger) ReadLine() (*job.LogLine, error) { for { line, _, readErr := l.reader.ReadLine() msg := string(line) + if readErr == io.EOF { return &job.LogLine{Timestamp: now(), Message: msg}, readErr } @@ -30,7 +31,7 @@ func (l *cloneLogger) ReadLine() (*job.LogLine, error) { return nil, errors.WithStack(readErr) } - if len(line) == 0 { + if len(line) == 0 || rep.Match(line) { continue } @@ -49,9 +50,8 @@ type ProgressLogger struct { // Write a log without CR or later. func (l *ProgressLogger) Write(p []byte) (n int, err error) { - msg := rep.ReplaceAllString(string(p), "") log := &cloneLogger{ - reader: bufio.NewReader(strings.NewReader(msg)), + reader: bufio.NewReader(bytes.NewReader(p)), } l.LogFunc(l.ctx, log) return 0, nil From cf28ead039840e4c4e631afad1f1aedf30e127f2 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sun, 2 Dec 2018 21:52:38 +0900 Subject: [PATCH 022/135] Add target github pull request --- domain/model/job/target/github_pr.go | 53 ++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 domain/model/job/target/github_pr.go diff --git a/domain/model/job/target/github_pr.go b/domain/model/job/target/github_pr.go new file mode 100644 index 00000000..73097a15 --- /dev/null +++ b/domain/model/job/target/github_pr.go @@ -0,0 +1,53 @@ +package target + +import ( + "context" + "fmt" + "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/job/target/git" + "github.com/duck8823/duci/domain/model/job/target/github" + "github.com/labstack/gommon/random" + "github.com/pkg/errors" + "gopkg.in/src-d/go-git.v4/plumbing" + "os" + "path" +) + +// GitHubPR is target with github pull request +type GitHubPR struct { + Repo github.Repository + Num int +} + +// Prepare working directory +func (g *GitHubPR) Prepare() (job.WorkDir, job.Cleanup, error) { + tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric, random.Numeric)) + if err := os.MkdirAll(tmpDir, 0700); err != nil { + return "", nil, errors.WithStack(err) + } + + githubCli, err := github.GetInstance() + if err != nil { + return "", nil, errors.WithStack(err) + } + + pr, err := githubCli.GetPullRequest(context.Background(), g.Repo, g.Num) + if err != nil { + return "", nil, errors.WithStack(err) + } + + gitCli, err := git.GetInstance() + if err != nil { + return "", nil, errors.WithStack(err) + } + + if err := gitCli.Clone(context.Background(), tmpDir, &github.TargetSource{ + Repository: g.Repo, + Ref: fmt.Sprintf("refs/heads/%s", pr.GetHead().GetRef()), + SHA: plumbing.NewHash(pr.GetHead().GetSHA()), + }); err != nil { + return "", nil, errors.WithStack(err) + } + + return job.WorkDir(tmpDir), cleanupFunc(tmpDir), nil +} From d07860bd33325414d885c4465f9be07051e1f2de Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sun, 2 Dec 2018 21:52:49 +0900 Subject: [PATCH 023/135] Fix godoc --- domain/model/job/target/github_push.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain/model/job/target/github_push.go b/domain/model/job/target/github_push.go index 13546d7b..eefd23c1 100644 --- a/domain/model/job/target/github_push.go +++ b/domain/model/job/target/github_push.go @@ -12,7 +12,7 @@ import ( "path" ) -// GitHub is target with github repository +// GitHubPush is target with github repository type GitHubPush struct { Repo github.Repository Point github.TargetPoint From bfe1e8f7ca6d9139abdba17455d413d277cfbf66 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sun, 2 Dec 2018 22:12:10 +0900 Subject: [PATCH 024/135] Change to use model --- application/cmd/health.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/application/cmd/health.go b/application/cmd/health.go index 443bd281..ff5277e7 100644 --- a/application/cmd/health.go +++ b/application/cmd/health.go @@ -1,9 +1,8 @@ package cmd import ( - "github.com/duck8823/duci/application/service/docker" - "github.com/duck8823/duci/infrastructure/logger" - "github.com/google/uuid" + "fmt" + "github.com/duck8823/duci/domain/model/docker" "github.com/spf13/cobra" "os" ) @@ -13,17 +12,20 @@ var healthCmd = createCmd("health", "Health check", healthCheck) func healthCheck(cmd *cobra.Command, _ []string) { readConfiguration(cmd) - dockerService, err := docker.New() + cli, err := docker.New() if err != nil { - logger.Errorf(uuid.New(), "Failed to set configuration.\n%+v", err) + msg := fmt.Sprintf("Failed to set configuration.\n%+v", err) + if _, err := fmt.Fprint(os.Stderr, msg); err != nil { + println(err) + } os.Exit(1) } - if err := dockerService.Status(); err != nil { - logger.Errorf(uuid.New(), "Unhealthy.\n%s", err) + if err := cli.Status(); err != nil { + println(fmt.Sprintf("Unhealth\n%s", err)) os.Exit(1) } else { - logger.Info(uuid.New(), "ok.") + println("ok") os.Exit(0) } } From e7d1d291a14e6eb45530016851decf8e7d3ab60b Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sun, 2 Dec 2018 22:26:21 +0900 Subject: [PATCH 025/135] Add function "CreateCommitStatus" --- domain/model/job/target/github/github.go | 49 ++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/domain/model/job/target/github/github.go b/domain/model/job/target/github/github.go index 1c7cabbb..cfb833f7 100644 --- a/domain/model/job/target/github/github.go +++ b/domain/model/job/target/github/github.go @@ -2,17 +2,20 @@ package github import ( "context" - "github.com/duck8823/duci/application/service/github" go_github "github.com/google/go-github/github" + "github.com/google/uuid" "github.com/pkg/errors" "golang.org/x/oauth2" + "net/url" + "path" ) var instance GitHub // GitHub describes a github client. type GitHub interface { - GetPullRequest(ctx context.Context, repo github.Repository, num int) (*go_github.PullRequest, error) + GetPullRequest(ctx context.Context, repo Repository, num int) (*go_github.PullRequest, error) + CreateCommitStatus(ctx context.Context, src *TargetSource, state State, description string) error } type client struct { @@ -42,7 +45,7 @@ func GetInstance() (GitHub, error) { } // GetPullRequest returns a pull request with specific repository and number. -func (c *client) GetPullRequest(ctx context.Context, repo github.Repository, num int) (*go_github.PullRequest, error) { +func (c *client) GetPullRequest(ctx context.Context, repo Repository, num int) (*go_github.PullRequest, error) { ownerName, repoName, err := RepositoryName(repo.GetFullName()).Split() if err != nil { return nil, errors.WithStack(err) @@ -59,3 +62,43 @@ func (c *client) GetPullRequest(ctx context.Context, repo github.Repository, num } return pr, nil } + +// CreateCommitStatus create commit status to github. +func (c *client) CreateCommitStatus(ctx context.Context, src *TargetSource, state State, description string) error { + // TODO: key must be const + taskName := ctx.Value("TaskName").(string) + if len(description) >= 50 { + description = string([]rune(description)[:46]) + "..." + } + + status := &go_github.RepoStatus{ + Context: &taskName, + Description: &description, + State: &state, + TargetURL: go_github.String(targetURL(ctx)), + } + + ownerName, repoName, err := RepositoryName(src.GetFullName()).Split() + if err != nil { + return errors.WithStack(err) + } + + if _, _, err := c.cli.Repositories.CreateStatus( + ctx, + ownerName, + repoName, + src.GetSHA().String(), + status, + ); err != nil { + return errors.WithStack(err) + } + return nil +} + +func targetURL(ctx context.Context) string { + // TODO: key must be const + jobID := ctx.Value("uuid").(uuid.UUID) + targetURL := ctx.Value("targetURL").(url.URL) + targetURL.Path = path.Join(targetURL.Path, "logs", jobID.String()) + return targetURL.String() +} From 49591aa5b8124d9150d8d30facd9000bd73ba051 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Mon, 3 Dec 2018 00:02:50 +0900 Subject: [PATCH 026/135] Fix return type --- domain/model/job/target/github/github.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain/model/job/target/github/github.go b/domain/model/job/target/github/github.go index cfb833f7..3ca89862 100644 --- a/domain/model/job/target/github/github.go +++ b/domain/model/job/target/github/github.go @@ -98,7 +98,7 @@ func (c *client) CreateCommitStatus(ctx context.Context, src *TargetSource, stat func targetURL(ctx context.Context) string { // TODO: key must be const jobID := ctx.Value("uuid").(uuid.UUID) - targetURL := ctx.Value("targetURL").(url.URL) + targetURL := ctx.Value("targetURL").(*url.URL) targetURL.Path = path.Join(targetURL.Path, "logs", jobID.String()) return targetURL.String() } From 0c56a8b3a76cd7e7bd2eb697160f6464dbcfdf9e Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Mon, 3 Dec 2018 01:10:07 +0900 Subject: [PATCH 027/135] Add executor builder --- application/service/executor/builder.go | 60 ++++++++++++++++++++++++ application/service/executor/executor.go | 9 +++- 2 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 application/service/executor/builder.go diff --git a/application/service/executor/builder.go b/application/service/executor/builder.go new file mode 100644 index 00000000..202614f8 --- /dev/null +++ b/application/service/executor/builder.go @@ -0,0 +1,60 @@ +package executor + +import ( + "context" + "github.com/duck8823/duci/domain/model/docker" + "github.com/duck8823/duci/domain/model/runner" +) + +type builder struct { + docker docker.Docker + logFunc runner.LogFunc + startFunc func(context.Context) + endFunc func(context.Context, error) +} + +// DefaultExecutorBuilder create new builder of docker runner +func DefaultExecutorBuilder() *builder { + cli, _ := docker.New() + return &builder{ + docker: cli, + logFunc: runner.NothingToDo, + startFunc: func(context.Context) { + // nothing to do + }, + endFunc: func(context.Context, error) { + // nothing to do + }, + } +} + +// LogFunc set a LogFunc +func (b *builder) LogFunc(f runner.LogFunc) *builder { + b.logFunc = f + return b +} + +// StartFunc set a startFunc +func (b *builder) StartFunc(f func(context.Context)) *builder { + b.startFunc = f + return b +} + +// EndFunc set a endFunc +func (b *builder) EndFunc(f func(context.Context, error)) *builder { + b.endFunc = f + return b +} + +// Build returns a executor +func (b *builder) Build() *jobExecutor { + r := runner.DefaultDockerRunnerBuilder(). + LogFunc(b.logFunc). + Build() + + return &jobExecutor{ + DockerRunner: r, + StartFunc: b.startFunc, + EndFunc: b.endFunc, + } +} diff --git a/application/service/executor/executor.go b/application/service/executor/executor.go index 76440b6c..1354d6c2 100644 --- a/application/service/executor/executor.go +++ b/application/service/executor/executor.go @@ -11,14 +11,19 @@ import ( "github.com/pkg/errors" ) -type JobExecutor struct { +// Executor is job executor +type Executor interface { + Execute(ctx context.Context, target job.Target, cmd ...string) error +} + +type jobExecutor struct { runner.DockerRunner StartFunc func(context.Context) EndFunc func(context.Context, error) } // Execute job -func (r *JobExecutor) Execute(ctx context.Context, target job.Target, cmd ...string) error { +func (r *jobExecutor) Execute(ctx context.Context, target job.Target, cmd ...string) error { r.StartFunc(ctx) workDir, cleanup, err := target.Prepare() From 6f3fb0beb91d8dab43e2a9f5978844550f92803d Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Tue, 4 Dec 2018 02:10:42 +0900 Subject: [PATCH 028/135] Add context to application --- application/context.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 application/context.go diff --git a/application/context.go b/application/context.go new file mode 100644 index 00000000..a1e86b3c --- /dev/null +++ b/application/context.go @@ -0,0 +1,32 @@ +package application + +import ( + "context" + "fmt" + "github.com/duck8823/duci/domain/model/job/target/github" + "github.com/google/uuid" + "net/url" +) + +var ctxKey = "duci_job" + +type BuildJob struct { + ID uuid.UUID + TargetSource *github.TargetSource + TaskName string + TargetURL *url.URL +} + +// ContextWithJob set parent context BuildJob and returns it. +func ContextWithJob(parent context.Context, job *BuildJob) context.Context { + return context.WithValue(parent, ctxKey, job) +} + +// BuildJobFromContext extract BuildJob from context +func BuildJobFromContext(ctx context.Context) (*BuildJob, error) { + job := ctx.Value(ctxKey) + if job == nil { + return nil, fmt.Errorf("context value '%s' should not be null", ctxKey) + } + return ctx.Value(ctxKey).(*BuildJob), nil +} From b4f9d96b8a7122ff426cf971ed6116547653e93d Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Tue, 4 Dec 2018 08:46:57 +0900 Subject: [PATCH 029/135] Add new PushHandler --- presentation/controller/webhook.go | 90 ++++++++++++++++++++++++++++++ presentation/router/router.go | 32 +++++++++++ 2 files changed, 122 insertions(+) create mode 100644 presentation/controller/webhook.go diff --git a/presentation/controller/webhook.go b/presentation/controller/webhook.go new file mode 100644 index 00000000..ddf255b3 --- /dev/null +++ b/presentation/controller/webhook.go @@ -0,0 +1,90 @@ +package controller + +import ( + "context" + "encoding/json" + "fmt" + "github.com/duck8823/duci/application" + "github.com/duck8823/duci/application/service/executor" + "github.com/duck8823/duci/domain/model/job/target" + "github.com/duck8823/duci/domain/model/job/target/github" + go_github "github.com/google/go-github/github" + "github.com/google/uuid" + "github.com/pkg/errors" + "gopkg.in/src-d/go-git.v4/plumbing" + "net/http" + "net/url" +) + +type WebhookHandler struct { + Executor executor.Executor +} + +func (h *WebhookHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + event := r.Header.Get("X-GitHub-Event") + switch event { + case "push": + h.PushEvent(w, r) + default: + msg := fmt.Sprintf("payload event type must be push. but %s", event) + http.Error(w, msg, http.StatusBadRequest) + return + } + + w.WriteHeader(http.StatusOK) +} + +func (h *WebhookHandler) PushEvent(w http.ResponseWriter, r *http.Request) { + event := &go_github.PushEvent{} + if err := json.NewDecoder(r.Body).Decode(event); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + reqID, err := reqID(r) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + ctx := application.ContextWithJob(context.Background(), &application.BuildJob{ + ID: reqID, + TargetSource: &github.TargetSource{ + Repository: event.GetRepo(), + Ref: event.GetRef(), + SHA: plumbing.NewHash(event.GetHead()), + }, + TaskName: fmt.Sprintf("%s/push", application.Name), + TargetURL: targetURL(r), + }) + + if err := h.Executor.Execute(ctx, &target.GitHubPush{ + Repo: event.GetRepo(), + Point: event, + }); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } +} + +func reqID(r *http.Request) (uuid.UUID, error) { + deliveryID := go_github.DeliveryID(r) + requestID, err := uuid.Parse(deliveryID) + if err != nil { + msg := fmt.Sprintf("Error: invalid request header `X-GitHub-Delivery`: %+v", deliveryID) + return uuid.New(), errors.Wrap(err, msg) + } + return requestID, nil +} + +func targetURL(r *http.Request) *url.URL { + runtimeURL := &url.URL{ + Scheme: "http", + Host: r.Host, + Path: r.URL.Path, + } + if r.URL.Scheme != "" { + runtimeURL.Scheme = r.URL.Scheme + } + return runtimeURL +} diff --git a/presentation/router/router.go b/presentation/router/router.go index 858b467e..763184a8 100644 --- a/presentation/router/router.go +++ b/presentation/router/router.go @@ -1,16 +1,22 @@ package router import ( + "context" "github.com/duck8823/duci/application" "github.com/duck8823/duci/application/service/docker" + "github.com/duck8823/duci/application/service/executor" "github.com/duck8823/duci/application/service/git" "github.com/duck8823/duci/application/service/github" "github.com/duck8823/duci/application/service/logstore" "github.com/duck8823/duci/application/service/runner" + "github.com/duck8823/duci/domain/model/job" + git2 "github.com/duck8823/duci/domain/model/job/target/git" + github2 "github.com/duck8823/duci/domain/model/job/target/github" "github.com/duck8823/duci/presentation/controller" "github.com/go-chi/chi" "github.com/pkg/errors" "net/http" + "os" ) // New returns handler of application. @@ -34,6 +40,32 @@ func New() (http.Handler, error) { rtr.Get("/logs/{uuid}", logCtrl.ServeHTTP) rtr.Get("/health", healthCtrl.ServeHTTP) + // using new api + // FIXME: where initialize?? + if err := git2.InitializeWithHTTP(func(ctx context.Context, log job.Log) { + for line, err := log.ReadLine(); err == nil; line, err = log.ReadLine() { + println(line.Message) + } + }); err != nil { + return nil, errors.WithStack(err) + } + + if err := github2.Initialize(os.Getenv("GITHUB_TOKEN")); err != nil { + return nil, errors.WithStack(err) + } + + webhook := &controller.WebhookHandler{ + Executor: executor.DefaultExecutorBuilder(). + LogFunc(func(ctx context.Context, log job.Log) { + for line, err := log.ReadLine(); err == nil; line, err = log.ReadLine() { + println(line.Message) + } + }). + Build(), + } + + rtr.Post("/webhook", webhook.ServeHTTP) + return rtr, nil } From 94bf7644a51db613362fe634fa4b116cc6cbacd1 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Thu, 6 Dec 2018 08:26:06 +0900 Subject: [PATCH 030/135] Add new IssueCommentHandler --- .../model/job/target/github/target_point.go | 16 +++ domain/model/job/target/github_push.go | 3 +- presentation/controller/webhook.go | 90 ------------- presentation/controller/webhook/helper.go | 58 +++++++++ presentation/controller/webhook/phrase.go | 22 ++++ presentation/controller/webhook/webhook.go | 123 ++++++++++++++++++ presentation/router/router.go | 3 +- 7 files changed, 223 insertions(+), 92 deletions(-) delete mode 100644 presentation/controller/webhook.go create mode 100644 presentation/controller/webhook/helper.go create mode 100644 presentation/controller/webhook/phrase.go create mode 100644 presentation/controller/webhook/webhook.go diff --git a/domain/model/job/target/github/target_point.go b/domain/model/job/target/github/target_point.go index 40a03911..0720e97c 100644 --- a/domain/model/job/target/github/target_point.go +++ b/domain/model/job/target/github/target_point.go @@ -5,3 +5,19 @@ type TargetPoint interface { GetRef() string GetHead() string } + +// SimpleTargetPoint is a simple implementation for TargetPoint +type SimpleTargetPoint struct { + Ref string + SHA string +} + +// GetRef returns a Ref +func (s *SimpleTargetPoint) GetRef() string { + return s.Ref +} + +// GetHead returns a SHA +func (s *SimpleTargetPoint) GetHead() string { + return s.SHA +} diff --git a/domain/model/job/target/github_push.go b/domain/model/job/target/github_push.go index eefd23c1..64872346 100644 --- a/domain/model/job/target/github_push.go +++ b/domain/model/job/target/github_push.go @@ -2,6 +2,7 @@ package target import ( "context" + "fmt" "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/job/target/git" "github.com/duck8823/duci/domain/model/job/target/github" @@ -32,7 +33,7 @@ func (g *GitHubPush) Prepare() (job.WorkDir, job.Cleanup, error) { if err := cli.Clone(context.Background(), tmpDir, &github.TargetSource{ Repository: g.Repo, - Ref: g.Point.GetRef(), + Ref: fmt.Sprintf("refs/heads/%s", g.Point.GetRef()), SHA: plumbing.NewHash(g.Point.GetHead()), }); err != nil { return "", nil, errors.WithStack(err) diff --git a/presentation/controller/webhook.go b/presentation/controller/webhook.go deleted file mode 100644 index ddf255b3..00000000 --- a/presentation/controller/webhook.go +++ /dev/null @@ -1,90 +0,0 @@ -package controller - -import ( - "context" - "encoding/json" - "fmt" - "github.com/duck8823/duci/application" - "github.com/duck8823/duci/application/service/executor" - "github.com/duck8823/duci/domain/model/job/target" - "github.com/duck8823/duci/domain/model/job/target/github" - go_github "github.com/google/go-github/github" - "github.com/google/uuid" - "github.com/pkg/errors" - "gopkg.in/src-d/go-git.v4/plumbing" - "net/http" - "net/url" -) - -type WebhookHandler struct { - Executor executor.Executor -} - -func (h *WebhookHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - event := r.Header.Get("X-GitHub-Event") - switch event { - case "push": - h.PushEvent(w, r) - default: - msg := fmt.Sprintf("payload event type must be push. but %s", event) - http.Error(w, msg, http.StatusBadRequest) - return - } - - w.WriteHeader(http.StatusOK) -} - -func (h *WebhookHandler) PushEvent(w http.ResponseWriter, r *http.Request) { - event := &go_github.PushEvent{} - if err := json.NewDecoder(r.Body).Decode(event); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - reqID, err := reqID(r) - if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - - ctx := application.ContextWithJob(context.Background(), &application.BuildJob{ - ID: reqID, - TargetSource: &github.TargetSource{ - Repository: event.GetRepo(), - Ref: event.GetRef(), - SHA: plumbing.NewHash(event.GetHead()), - }, - TaskName: fmt.Sprintf("%s/push", application.Name), - TargetURL: targetURL(r), - }) - - if err := h.Executor.Execute(ctx, &target.GitHubPush{ - Repo: event.GetRepo(), - Point: event, - }); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } -} - -func reqID(r *http.Request) (uuid.UUID, error) { - deliveryID := go_github.DeliveryID(r) - requestID, err := uuid.Parse(deliveryID) - if err != nil { - msg := fmt.Sprintf("Error: invalid request header `X-GitHub-Delivery`: %+v", deliveryID) - return uuid.New(), errors.Wrap(err, msg) - } - return requestID, nil -} - -func targetURL(r *http.Request) *url.URL { - runtimeURL := &url.URL{ - Scheme: "http", - Host: r.Host, - Path: r.URL.Path, - } - if r.URL.Scheme != "" { - runtimeURL.Scheme = r.URL.Scheme - } - return runtimeURL -} diff --git a/presentation/controller/webhook/helper.go b/presentation/controller/webhook/helper.go new file mode 100644 index 00000000..6126fdd7 --- /dev/null +++ b/presentation/controller/webhook/helper.go @@ -0,0 +1,58 @@ +package webhook + +import ( + "context" + "fmt" + "github.com/duck8823/duci/domain/model/job/target/github" + go_github "github.com/google/go-github/github" + "github.com/google/uuid" + "github.com/pkg/errors" + "net/http" + "net/url" +) + +func reqID(r *http.Request) (uuid.UUID, error) { + deliveryID := go_github.DeliveryID(r) + requestID, err := uuid.Parse(deliveryID) + if err != nil { + msg := fmt.Sprintf("Error: invalid request header `X-GitHub-Delivery`: %+v", deliveryID) + return uuid.New(), errors.Wrap(err, msg) + } + return requestID, nil +} + +func targetURL(r *http.Request) *url.URL { + runtimeURL := &url.URL{ + Scheme: "http", + Host: r.Host, + Path: r.URL.Path, + } + if r.URL.Scheme != "" { + runtimeURL.Scheme = r.URL.Scheme + } + return runtimeURL +} + +func targetPoint(event *go_github.IssueCommentEvent) (github.TargetPoint, error) { + gh, err := github.GetInstance() + if err != nil { + return nil, errors.WithStack(err) + } + + pr, err := gh.GetPullRequest(context.Background(), event.GetRepo(), event.GetIssue().GetNumber()) + if err != nil { + return nil, errors.WithStack(err) + } + + return &github.SimpleTargetPoint{ + Ref: pr.GetHead().GetRef(), + SHA: pr.GetHead().GetSHA(), + }, nil +} + +func isValidAction(action *string) bool { + if action == nil { + return false + } + return *action == "created" || *action == "edited" +} diff --git a/presentation/controller/webhook/phrase.go b/presentation/controller/webhook/phrase.go new file mode 100644 index 00000000..721a06bd --- /dev/null +++ b/presentation/controller/webhook/phrase.go @@ -0,0 +1,22 @@ +package webhook + +import ( + "github.com/duck8823/duci/domain/model/docker" + "github.com/pkg/errors" + "regexp" + "strings" +) + +type phrase string + +func (p phrase) Command() docker.Command { + return strings.Split(string(p), " ") +} + +func extractBuildPhrase(comment string) (phrase, SkipBuild) { + if !regexp.MustCompile("^ci\\s+[^\\s]+").Match([]byte(comment)) { + return "", SkipBuild(errors.New("Not start with ci.")) + } + phrase := phrase(regexp.MustCompile("^ci\\s+").ReplaceAllString(comment, "")) + return phrase, nil +} diff --git a/presentation/controller/webhook/webhook.go b/presentation/controller/webhook/webhook.go new file mode 100644 index 00000000..ce92f183 --- /dev/null +++ b/presentation/controller/webhook/webhook.go @@ -0,0 +1,123 @@ +package webhook + +import ( + "context" + "encoding/json" + "fmt" + "github.com/duck8823/duci/application" + "github.com/duck8823/duci/application/service/executor" + "github.com/duck8823/duci/domain/model/job/target" + "github.com/duck8823/duci/domain/model/job/target/github" + go_github "github.com/google/go-github/github" + "gopkg.in/src-d/go-git.v4/plumbing" + "net/http" +) + +type SkipBuild error + +type Handler struct { + Executor executor.Executor +} + +func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + event := r.Header.Get("X-GitHub-Event") + switch event { + case "push": + h.PushEvent(w, r) + case "issue_comment": + h.IssueCommentEvent(w, r) + default: + msg := fmt.Sprintf("payload event type must be push or issue_comment. but %s", event) + http.Error(w, msg, http.StatusBadRequest) + return + } +} + +func (h *Handler) PushEvent(w http.ResponseWriter, r *http.Request) { + event := &go_github.PushEvent{} + if err := json.NewDecoder(r.Body).Decode(event); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + reqID, err := reqID(r) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + ctx := application.ContextWithJob(context.Background(), &application.BuildJob{ + ID: reqID, + TargetSource: &github.TargetSource{ + Repository: event.GetRepo(), + Ref: event.GetRef(), + SHA: plumbing.NewHash(event.GetHead()), + }, + TaskName: fmt.Sprintf("%s/push", application.Name), + TargetURL: targetURL(r), + }) + + if err := h.Executor.Execute(ctx, &target.GitHubPush{ + Repo: event.GetRepo(), + Point: event, + }); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusOK) +} + +func (h *Handler) IssueCommentEvent(w http.ResponseWriter, r *http.Request) { + event := &go_github.IssueCommentEvent{} + if err := json.NewDecoder(r.Body).Decode(event); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + if !isValidAction(event.Action) { + w.WriteHeader(http.StatusOK) + w.Write([]byte("{\"message\":\"skip build\"}")) + return + } + + reqID, err := reqID(r) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + pnt, err := targetPoint(event) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + phrase, err := extractBuildPhrase(event.GetComment().GetBody()) + if err != nil { + w.WriteHeader(http.StatusOK) + w.Write([]byte("{\"message\":\"skip build\"}")) + return + } + + ctx := application.ContextWithJob(context.Background(), &application.BuildJob{ + ID: reqID, + TargetSource: &github.TargetSource{ + Repository: event.GetRepo(), + Ref: pnt.GetRef(), + SHA: plumbing.NewHash(pnt.GetHead()), + }, + TaskName: fmt.Sprintf("%s/pr/%s", application.Name, phrase.Command().ToSlice()[0]), + TargetURL: targetURL(r), + }) + + if err := h.Executor.Execute(ctx, &target.GitHubPush{ + Repo: event.GetRepo(), + Point: pnt, + }, phrase.Command()...); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusOK) +} diff --git a/presentation/router/router.go b/presentation/router/router.go index 763184a8..efa31f7f 100644 --- a/presentation/router/router.go +++ b/presentation/router/router.go @@ -13,6 +13,7 @@ import ( git2 "github.com/duck8823/duci/domain/model/job/target/git" github2 "github.com/duck8823/duci/domain/model/job/target/github" "github.com/duck8823/duci/presentation/controller" + webhook2 "github.com/duck8823/duci/presentation/controller/webhook" "github.com/go-chi/chi" "github.com/pkg/errors" "net/http" @@ -54,7 +55,7 @@ func New() (http.Handler, error) { return nil, errors.WithStack(err) } - webhook := &controller.WebhookHandler{ + webhook := &webhook2.Handler{ Executor: executor.DefaultExecutorBuilder(). LogFunc(func(ctx context.Context, log job.Log) { for line, err := log.ReadLine(); err == nil; line, err = log.ReadLine() { From 0afd932f92cae5d677967b1b30dbd77fd7d58774 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Fri, 7 Dec 2018 07:16:58 +0900 Subject: [PATCH 031/135] Add health handler --- presentation/controller/health/health.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 presentation/controller/health/health.go diff --git a/presentation/controller/health/health.go b/presentation/controller/health/health.go new file mode 100644 index 00000000..aa78ed2a --- /dev/null +++ b/presentation/controller/health/health.go @@ -0,0 +1,20 @@ +package health + +import ( + "github.com/duck8823/duci/domain/model/docker" + "net/http" +) + +// Handler of health check. +type Handler struct { + Docker docker.Docker +} + +// ServeHTTP responses a server status +func (c *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if err := c.Docker.Status(); err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + w.WriteHeader(http.StatusOK) +} From d511ed476c31c7c1837fa491157e91e9dfbee586 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Fri, 7 Dec 2018 07:17:42 +0900 Subject: [PATCH 032/135] Add job handler and service --- application/service/job/job.go | 26 ++++++++++++++ presentation/controller/job/job.go | 57 ++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 application/service/job/job.go create mode 100644 presentation/controller/job/job.go diff --git a/application/service/job/job.go b/application/service/job/job.go new file mode 100644 index 00000000..68eb000d --- /dev/null +++ b/application/service/job/job.go @@ -0,0 +1,26 @@ +package job_service + +import ( + . "github.com/duck8823/duci/domain/model/job" + "github.com/pkg/errors" +) + +type Service interface { + FindBy(id ID) (*Job, error) +} + +type serviceImpl struct { + repo Repository +} + +func New() (Service, error) { + return &serviceImpl{}, nil +} + +func (s *serviceImpl) FindBy(id ID) (*Job, error) { + job, err := s.repo.Get(id) + if err != nil { + return nil, errors.WithStack(err) + } + return job, nil +} diff --git a/presentation/controller/job/job.go b/presentation/controller/job/job.go new file mode 100644 index 00000000..4345f4bc --- /dev/null +++ b/presentation/controller/job/job.go @@ -0,0 +1,57 @@ +package job + +import ( + "encoding/json" + "fmt" + "github.com/duck8823/duci/application/service/job" + . "github.com/duck8823/duci/domain/model/job" + "github.com/go-chi/chi" + "github.com/google/uuid" + "github.com/pkg/errors" + "net/http" +) + +type Handler struct { + service job_service.Service +} + +func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", "*") + + id, err := uuid.Parse(chi.URLParam(r, "uuid")) + if err != nil { + http.Error(w, fmt.Sprintf("Error occurred: %s", err.Error()), http.StatusInternalServerError) + return + } + + if err := h.logs(w, ID(id)); err != nil { + http.Error(w, fmt.Sprintf(" Error occurred: %s", err.Error()), http.StatusInternalServerError) + return + } +} + +func (h *Handler) logs(w http.ResponseWriter, id ID) error { + f, ok := w.(http.Flusher) + if !ok { + return errors.New("Streaming unsupported!") + } + + var read int + var job *Job + var err error + for { + job, err = h.service.FindBy(id) + if err != nil { + return errors.WithStack(err) + } + for _, msg := range job.Stream[read:] { + json.NewEncoder(w).Encode(msg) + f.Flush() + read++ + } + if job.Finished { + break + } + } + return nil +} From 08c764d5d35006d42b425ed72467502d40f755fa Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Fri, 7 Dec 2018 07:33:15 +0900 Subject: [PATCH 033/135] Rename files --- presentation/controller/health/{health.go => handler.go} | 0 presentation/controller/job/{job.go => handler.go} | 0 presentation/controller/webhook/{webhook.go => handler.go} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename presentation/controller/health/{health.go => handler.go} (100%) rename presentation/controller/job/{job.go => handler.go} (100%) rename presentation/controller/webhook/{webhook.go => handler.go} (100%) diff --git a/presentation/controller/health/health.go b/presentation/controller/health/handler.go similarity index 100% rename from presentation/controller/health/health.go rename to presentation/controller/health/handler.go diff --git a/presentation/controller/job/job.go b/presentation/controller/job/handler.go similarity index 100% rename from presentation/controller/job/job.go rename to presentation/controller/job/handler.go diff --git a/presentation/controller/webhook/webhook.go b/presentation/controller/webhook/handler.go similarity index 100% rename from presentation/controller/webhook/webhook.go rename to presentation/controller/webhook/handler.go From 4e7a541e16ad30df30bbfe0cfe3804dfeb74c3f2 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Fri, 7 Dec 2018 07:33:58 +0900 Subject: [PATCH 034/135] Error message --- presentation/controller/health.go | 2 +- presentation/controller/health/handler.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/presentation/controller/health.go b/presentation/controller/health.go index 1d0c5945..69707db7 100644 --- a/presentation/controller/health.go +++ b/presentation/controller/health.go @@ -13,7 +13,7 @@ type HealthController struct { // ServeHTTP responses a server status func (c *HealthController) ServeHTTP(w http.ResponseWriter, r *http.Request) { if err := c.Docker.Status(); err != nil { - w.WriteHeader(http.StatusInternalServerError) + http.Error(w, err.Error(), http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) diff --git a/presentation/controller/health/handler.go b/presentation/controller/health/handler.go index aa78ed2a..c2c08b82 100644 --- a/presentation/controller/health/handler.go +++ b/presentation/controller/health/handler.go @@ -13,7 +13,7 @@ type Handler struct { // ServeHTTP responses a server status func (c *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if err := c.Docker.Status(); err != nil { - w.WriteHeader(http.StatusInternalServerError) + http.Error(w, err.Error(), http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) From 06feb3e47d6a4a2bf22635ee973db636b17d05c1 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Fri, 7 Dec 2018 08:45:09 +0900 Subject: [PATCH 035/135] Fix logic to get key of store --- domain/model/job/job.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain/model/job/job.go b/domain/model/job/job.go index 18988378..034f88c1 100644 --- a/domain/model/job/job.go +++ b/domain/model/job/job.go @@ -46,5 +46,5 @@ type ID uuid.UUID // ToSlice returns slice value func (i ID) ToSlice() []byte { - return []byte(i[:]) + return []byte(uuid.UUID(i).String()) } From a59f6185b8baa775183af4e131671ac25780c13c Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Fri, 7 Dec 2018 08:47:03 +0900 Subject: [PATCH 036/135] Fix job modules --- application/service/job/job.go | 9 ++++++++- domain/model/job/repository.go | 2 +- presentation/controller/job/handler.go | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/application/service/job/job.go b/application/service/job/job.go index 68eb000d..3220eed6 100644 --- a/application/service/job/job.go +++ b/application/service/job/job.go @@ -1,7 +1,9 @@ package job_service import ( + "github.com/duck8823/duci/application" . "github.com/duck8823/duci/domain/model/job" + . "github.com/duck8823/duci/infrastructure/job" "github.com/pkg/errors" ) @@ -14,7 +16,12 @@ type serviceImpl struct { } func New() (Service, error) { - return &serviceImpl{}, nil + dataSource, err := NewDataSource(application.Config.Server.DatabasePath) + if err != nil { + return nil, errors.WithStack(err) + } + + return &serviceImpl{repo: dataSource}, nil } func (s *serviceImpl) FindBy(id ID) (*Job, error) { diff --git a/domain/model/job/repository.go b/domain/model/job/repository.go index 1969697c..81148f55 100644 --- a/domain/model/job/repository.go +++ b/domain/model/job/repository.go @@ -4,6 +4,6 @@ package job type Repository interface { Get(ID) (*Job, error) Start(ID) error - Append(ID, *LogLine) error + Append(ID, LogLine) error Finish(ID) error } diff --git a/presentation/controller/job/handler.go b/presentation/controller/job/handler.go index 4345f4bc..fa7524a6 100644 --- a/presentation/controller/job/handler.go +++ b/presentation/controller/job/handler.go @@ -12,7 +12,7 @@ import ( ) type Handler struct { - service job_service.Service + Service job_service.Service } func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { @@ -40,7 +40,7 @@ func (h *Handler) logs(w http.ResponseWriter, id ID) error { var job *Job var err error for { - job, err = h.service.FindBy(id) + job, err = h.Service.FindBy(id) if err != nil { return errors.WithStack(err) } From 45a37f019d7e17c699236fba0266531d58b46b4f Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 8 Dec 2018 00:47:42 +0900 Subject: [PATCH 037/135] Add service functions --- application/service/job/job.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/application/service/job/job.go b/application/service/job/job.go index 3220eed6..b7bfa9d5 100644 --- a/application/service/job/job.go +++ b/application/service/job/job.go @@ -9,6 +9,9 @@ import ( type Service interface { FindBy(id ID) (*Job, error) + Start(id ID) error + Append(id ID, line LogLine) error + Finish(id ID) error } type serviceImpl struct { @@ -31,3 +34,24 @@ func (s *serviceImpl) FindBy(id ID) (*Job, error) { } return job, nil } + +func (s *serviceImpl) Start(id ID) error { + if err := s.repo.Start(id); err != nil { + return errors.WithStack(err) + } + return nil +} + +func (s *serviceImpl) Append(id ID, line LogLine) error { + if err := s.repo.Append(id, line); err != nil { + return errors.WithStack(err) + } + return nil +} + +func (s *serviceImpl) Finish(id ID) error { + if err := s.repo.Finish(id); err != nil { + return errors.WithStack(err) + } + return nil +} From ac676a377a2da5bc0582cca49ca80961a722f506 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 8 Dec 2018 00:48:07 +0900 Subject: [PATCH 038/135] Change interface --- domain/model/job/target/github/github.go | 37 +++++++---------------- domain/model/job/target/github/state.go | 15 ---------- domain/model/job/target/github/status.go | 38 ++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 42 deletions(-) delete mode 100644 domain/model/job/target/github/state.go create mode 100644 domain/model/job/target/github/status.go diff --git a/domain/model/job/target/github/github.go b/domain/model/job/target/github/github.go index 3ca89862..eb5a6551 100644 --- a/domain/model/job/target/github/github.go +++ b/domain/model/job/target/github/github.go @@ -3,11 +3,8 @@ package github import ( "context" go_github "github.com/google/go-github/github" - "github.com/google/uuid" "github.com/pkg/errors" "golang.org/x/oauth2" - "net/url" - "path" ) var instance GitHub @@ -15,7 +12,7 @@ var instance GitHub // GitHub describes a github client. type GitHub interface { GetPullRequest(ctx context.Context, repo Repository, num int) (*go_github.PullRequest, error) - CreateCommitStatus(ctx context.Context, src *TargetSource, state State, description string) error + CreateCommitStatus(ctx context.Context, status CommitStatus) error } type client struct { @@ -64,21 +61,15 @@ func (c *client) GetPullRequest(ctx context.Context, repo Repository, num int) ( } // CreateCommitStatus create commit status to github. -func (c *client) CreateCommitStatus(ctx context.Context, src *TargetSource, state State, description string) error { - // TODO: key must be const - taskName := ctx.Value("TaskName").(string) - if len(description) >= 50 { - description = string([]rune(description)[:46]) + "..." +func (c *client) CreateCommitStatus(ctx context.Context, status CommitStatus) error { + repoStatus := &go_github.RepoStatus{ + Context: go_github.String(status.Context), + Description: go_github.String(status.Description.TrimmedString()), + State: go_github.String(status.State.ToString()), + TargetURL: go_github.String(status.TargetURL.String()), } - status := &go_github.RepoStatus{ - Context: &taskName, - Description: &description, - State: &state, - TargetURL: go_github.String(targetURL(ctx)), - } - - ownerName, repoName, err := RepositoryName(src.GetFullName()).Split() + ownerName, repoName, err := RepositoryName(status.TargetSource.GetFullName()).Split() if err != nil { return errors.WithStack(err) } @@ -87,18 +78,10 @@ func (c *client) CreateCommitStatus(ctx context.Context, src *TargetSource, stat ctx, ownerName, repoName, - src.GetSHA().String(), - status, + status.TargetSource.GetSHA().String(), + repoStatus, ); err != nil { return errors.WithStack(err) } return nil } - -func targetURL(ctx context.Context) string { - // TODO: key must be const - jobID := ctx.Value("uuid").(uuid.UUID) - targetURL := ctx.Value("targetURL").(*url.URL) - targetURL.Path = path.Join(targetURL.Path, "logs", jobID.String()) - return targetURL.String() -} diff --git a/domain/model/job/target/github/state.go b/domain/model/job/target/github/state.go deleted file mode 100644 index fdc365e2..00000000 --- a/domain/model/job/target/github/state.go +++ /dev/null @@ -1,15 +0,0 @@ -package github - -// State represents state of commit status -type State = string - -const ( - // PENDING represents pending state. - PENDING State = "pending" - // SUCCESS represents success state. - SUCCESS State = "success" - // ERROR represents error state. - ERROR State = "error" - // FAILURE represents failure state. - FAILURE State = "failure" -) diff --git a/domain/model/job/target/github/status.go b/domain/model/job/target/github/status.go new file mode 100644 index 00000000..32269e32 --- /dev/null +++ b/domain/model/job/target/github/status.go @@ -0,0 +1,38 @@ +package github + +import "net/url" + +// State represents state of commit status +type State string + +func (s State) ToString() string { + return string(s) +} + +type Description string + +func (d Description) TrimmedString() string { + if len(d) >= 50 { + return string([]rune(d)[:46]) + "..." + } + return string(d) +} + +const ( + // PENDING represents pending state. + PENDING State = "pending" + // SUCCESS represents success state. + SUCCESS State = "success" + // ERROR represents error state. + ERROR State = "error" + // FAILURE represents failure state. + FAILURE State = "failure" +) + +type CommitStatus struct { + TargetSource *TargetSource + State State + Description Description + Context string + TargetURL *url.URL +} From 9ade4dc1f76c6dd867167a7cbd97f4ba5797dc39 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 8 Dec 2018 00:52:55 +0900 Subject: [PATCH 039/135] Using new api --- presentation/router/router.go | 157 +++++++++++++++++++++------------- 1 file changed, 97 insertions(+), 60 deletions(-) diff --git a/presentation/router/router.go b/presentation/router/router.go index efa31f7f..48a5f7f9 100644 --- a/presentation/router/router.go +++ b/presentation/router/router.go @@ -2,105 +2,142 @@ package router import ( "context" + "fmt" "github.com/duck8823/duci/application" - "github.com/duck8823/duci/application/service/docker" "github.com/duck8823/duci/application/service/executor" - "github.com/duck8823/duci/application/service/git" - "github.com/duck8823/duci/application/service/github" - "github.com/duck8823/duci/application/service/logstore" + "github.com/duck8823/duci/application/service/job" "github.com/duck8823/duci/application/service/runner" + "github.com/duck8823/duci/domain/model/docker" "github.com/duck8823/duci/domain/model/job" - git2 "github.com/duck8823/duci/domain/model/job/target/git" - github2 "github.com/duck8823/duci/domain/model/job/target/github" - "github.com/duck8823/duci/presentation/controller" - webhook2 "github.com/duck8823/duci/presentation/controller/webhook" + "github.com/duck8823/duci/domain/model/job/target/git" + "github.com/duck8823/duci/domain/model/job/target/github" + health_controller "github.com/duck8823/duci/presentation/controller/health" + job_controller "github.com/duck8823/duci/presentation/controller/job" + webhook_controller "github.com/duck8823/duci/presentation/controller/webhook" "github.com/go-chi/chi" "github.com/pkg/errors" "net/http" "os" + "time" ) // New returns handler of application. func New() (http.Handler, error) { - dockerService, logstoreService, githubService, err := createCommonServices() - if err != nil { + // FIXME: where initialize?? + if err := git.InitializeWithHTTP(func(ctx context.Context, log job.Log) { + for line, err := log.ReadLine(); err == nil; line, err = log.ReadLine() { + println(line.Message) + } + }); err != nil { return nil, errors.WithStack(err) } - dockerRunner, err := createRunner(logstoreService, githubService, dockerService) - if err != nil { + if err := github.Initialize(os.Getenv("GITHUB_TOKEN")); err != nil { return nil, errors.WithStack(err) } - webhooksCtrl := &controller.WebhooksController{Runner: dockerRunner, GitHub: githubService} - logCtrl := &controller.LogController{LogStore: logstoreService} - healthCtrl := &controller.HealthController{Docker: dockerService} - - rtr := chi.NewRouter() - rtr.Post("/", webhooksCtrl.ServeHTTP) - rtr.Get("/logs/{uuid}", logCtrl.ServeHTTP) - rtr.Get("/health", healthCtrl.ServeHTTP) - - // using new api - // FIXME: where initialize?? - if err := git2.InitializeWithHTTP(func(ctx context.Context, log job.Log) { - for line, err := log.ReadLine(); err == nil; line, err = log.ReadLine() { - println(line.Message) - } - }); err != nil { + gh, err := github.GetInstance() + if err != nil { return nil, errors.WithStack(err) } - if err := github2.Initialize(os.Getenv("GITHUB_TOKEN")); err != nil { + jobService, err := job_service.New() + if err != nil { return nil, errors.WithStack(err) } - webhook := &webhook2.Handler{ + webhook := &webhook_controller.Handler{ Executor: executor.DefaultExecutorBuilder(). + StartFunc(func(ctx context.Context) { + buildJob, err := application.BuildJobFromContext(ctx) + id := job.ID(buildJob.ID) + if err != nil { + _ = jobService.Append(id, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) + return + } + if err := jobService.Start(id); err != nil { + _ = jobService.Append(id, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) + return + } + _ = gh.CreateCommitStatus(ctx, github.CommitStatus{ + TargetSource: buildJob.TargetSource, + State: github.PENDING, + Description: "pending", + Context: buildJob.TaskName, + TargetURL: buildJob.TargetURL, + }) + }). LogFunc(func(ctx context.Context, log job.Log) { + buildJob, err := application.BuildJobFromContext(ctx) + id := job.ID(buildJob.ID) + if err != nil { + _ = jobService.Append(id, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) + return + } for line, err := log.ReadLine(); err == nil; line, err = log.ReadLine() { println(line.Message) + _ = jobService.Append(id, *line) } }). - Build(), - } - - rtr.Post("/webhook", webhook.ServeHTTP) - - return rtr, nil -} + EndFunc(func(ctx context.Context, e error) { + buildJob, err := application.BuildJobFromContext(ctx) + id := job.ID(buildJob.ID) + if err != nil { + _ = jobService.Append(id, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) + return + } + if err := jobService.Finish(id); err != nil { + println(fmt.Sprintf("%+v", err)) + return + } -func createCommonServices() (docker.Service, logstore.Service, github.Service, error) { - dockerService, err := docker.New() - if err != nil { - return nil, nil, nil, errors.WithStack(err) + switch e { + case nil: + _ = gh.CreateCommitStatus(ctx, github.CommitStatus{ + TargetSource: buildJob.TargetSource, + State: github.SUCCESS, + Description: "success", + Context: buildJob.TaskName, + TargetURL: buildJob.TargetURL, + }) + case runner.ErrFailure: + _ = gh.CreateCommitStatus(ctx, github.CommitStatus{ + TargetSource: buildJob.TargetSource, + State: github.FAILURE, + Description: "failure", + Context: buildJob.TaskName, + TargetURL: buildJob.TargetURL, + }) + default: + _ = gh.CreateCommitStatus(ctx, github.CommitStatus{ + TargetSource: buildJob.TargetSource, + State: github.ERROR, + Description: github.Description(fmt.Sprintf("error: %s", e.Error())), + Context: buildJob.TaskName, + TargetURL: buildJob.TargetURL, + }) + } + }). + Build(), } - logstoreService, err := logstore.New() - if err != nil { - return nil, nil, nil, errors.WithStack(err) - } - githubService, err := github.New() - if err != nil { - return nil, nil, nil, errors.WithStack(err) + job := &job_controller.Handler{ + Service: jobService, } - return dockerService, logstoreService, githubService, nil -} - -func createRunner(logstoreService logstore.Service, githubService github.Service, dockerService docker.Service) (runner.Runner, error) { - gitClient, err := git.New() + docker, err := docker.New() if err != nil { return nil, errors.WithStack(err) } - dockerRunner := &runner.DockerRunner{ - BaseWorkDir: application.Config.Server.WorkDir, - Git: gitClient, - GitHub: githubService, - Docker: dockerService, - LogStore: logstoreService, + health := &health_controller.Handler{ + Docker: docker, } - return dockerRunner, nil + rtr := chi.NewRouter() + rtr.Post("/", webhook.ServeHTTP) + rtr.Get("/logs/{uuid}", job.ServeHTTP) + rtr.Get("/health", health.ServeHTTP) + + return rtr, nil } From 1f81e81aed2a6942edbc6deb70dd9c0e61561983 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 8 Dec 2018 01:01:33 +0900 Subject: [PATCH 040/135] Remove old apis --- application/cmd/config.go | 5 +- application/cmd/root.go | 4 +- application/cmd/server.go | 8 +- application/context/context.go | 59 -- application/context/context_test.go | 58 -- application/service/docker/docker.go | 103 --- .../service/docker/mock_docker/docker.go | 112 --- application/service/git/export_test.go | 32 - application/service/git/git.go | 96 -- application/service/git/git_test.go | 307 ------- application/service/git/mock_git/git.go | 47 - application/service/git/progress_logger.go | 24 - .../service/git/progress_logger_test.go | 56 -- application/service/github/alias.go | 16 - application/service/github/export_test.go | 19 - application/service/github/github.go | 109 --- application/service/github/github_test.go | 208 ----- .../service/github/mock_github/github.go | 60 -- application/service/github/repository_name.go | 29 - .../service/github/repository_name_test.go | 74 -- application/service/github/target_source.go | 31 - .../service/github/target_source_test.go | 76 -- application/service/logstore/export_test.go | 13 - .../service/logstore/mock_logstore/store.go | 96 -- application/service/logstore/store.go | 127 --- application/service/logstore/store_test.go | 566 ------------ application/service/runner/export_test.go | 39 - application/service/runner/helper.go | 62 -- .../service/runner/mock_runner/runner.go | 52 -- application/service/runner/runner.go | 188 ---- application/service/runner/runner_test.go | 850 ------------------ data/model/log.go | 15 - infrastructure/docker/docker.go | 148 --- infrastructure/docker/docker_test.go | 595 ------------ infrastructure/docker/export_test.go | 42 - infrastructure/docker/log.go | 92 -- infrastructure/docker/log_test.go | 132 --- infrastructure/docker/mock_docker/docker.go | 119 --- .../docker/mock_docker/third_party.go | 140 --- .../docker/testdata/correct_archive.tar | Bin 2048 -> 0 bytes .../testdata/correct_archive_subdir.tar | Bin 2560 -> 0 bytes infrastructure/docker/testdata/data | 1 - .../docker/testdata/invalid_archive.tar | Bin 1536 -> 0 bytes infrastructure/docker/third_pirty.go | 54 -- infrastructure/logger/export_test.go | 11 - infrastructure/logger/logger.go | 58 -- infrastructure/logger/logger_test.go | 193 ---- infrastructure/store/mock_store/store.go | 84 -- infrastructure/store/store.go | 25 - presentation/controller/health.go | 20 - presentation/controller/health_test.go | 71 -- presentation/controller/logs.go | 59 -- presentation/controller/logs_test.go | 119 --- presentation/controller/webhooks.go | 176 ---- presentation/controller/webhooks_test.go | 390 -------- presentation/router/router.go | 2 +- 56 files changed, 7 insertions(+), 6065 deletions(-) delete mode 100644 application/context/context.go delete mode 100644 application/context/context_test.go delete mode 100644 application/service/docker/docker.go delete mode 100644 application/service/docker/mock_docker/docker.go delete mode 100644 application/service/git/export_test.go delete mode 100644 application/service/git/git.go delete mode 100644 application/service/git/git_test.go delete mode 100644 application/service/git/mock_git/git.go delete mode 100644 application/service/git/progress_logger.go delete mode 100644 application/service/git/progress_logger_test.go delete mode 100644 application/service/github/alias.go delete mode 100644 application/service/github/export_test.go delete mode 100644 application/service/github/github.go delete mode 100644 application/service/github/github_test.go delete mode 100644 application/service/github/mock_github/github.go delete mode 100644 application/service/github/repository_name.go delete mode 100644 application/service/github/repository_name_test.go delete mode 100644 application/service/github/target_source.go delete mode 100644 application/service/github/target_source_test.go delete mode 100644 application/service/logstore/export_test.go delete mode 100644 application/service/logstore/mock_logstore/store.go delete mode 100644 application/service/logstore/store.go delete mode 100644 application/service/logstore/store_test.go delete mode 100644 application/service/runner/export_test.go delete mode 100644 application/service/runner/helper.go delete mode 100644 application/service/runner/mock_runner/runner.go delete mode 100644 application/service/runner/runner.go delete mode 100644 application/service/runner/runner_test.go delete mode 100644 data/model/log.go delete mode 100644 infrastructure/docker/docker.go delete mode 100644 infrastructure/docker/docker_test.go delete mode 100644 infrastructure/docker/export_test.go delete mode 100644 infrastructure/docker/log.go delete mode 100644 infrastructure/docker/log_test.go delete mode 100644 infrastructure/docker/mock_docker/docker.go delete mode 100644 infrastructure/docker/mock_docker/third_party.go delete mode 100644 infrastructure/docker/testdata/correct_archive.tar delete mode 100644 infrastructure/docker/testdata/correct_archive_subdir.tar delete mode 100644 infrastructure/docker/testdata/data delete mode 100644 infrastructure/docker/testdata/invalid_archive.tar delete mode 100644 infrastructure/docker/third_pirty.go delete mode 100644 infrastructure/logger/export_test.go delete mode 100644 infrastructure/logger/logger.go delete mode 100644 infrastructure/logger/logger_test.go delete mode 100644 infrastructure/store/mock_store/store.go delete mode 100644 infrastructure/store/store.go delete mode 100644 presentation/controller/health.go delete mode 100644 presentation/controller/health_test.go delete mode 100644 presentation/controller/logs.go delete mode 100644 presentation/controller/logs_test.go delete mode 100644 presentation/controller/webhooks.go delete mode 100644 presentation/controller/webhooks_test.go diff --git a/application/cmd/config.go b/application/cmd/config.go index b86ca8a1..19529dca 100644 --- a/application/cmd/config.go +++ b/application/cmd/config.go @@ -2,9 +2,8 @@ package cmd import ( "encoding/json" + "fmt" "github.com/duck8823/duci/application" - "github.com/duck8823/duci/infrastructure/logger" - "github.com/google/uuid" "github.com/spf13/cobra" "os" ) @@ -17,7 +16,7 @@ func displayConfig(cmd *cobra.Command, _ []string) { enc := json.NewEncoder(os.Stdout) enc.SetIndent("", " ") if err := enc.Encode(application.Config); err != nil { - logger.Errorf(uuid.New(), "Failed to display config.\n%+v", err) + println(fmt.Sprintf("Failed to display config.\n%+v", err)) os.Exit(1) } } diff --git a/application/cmd/root.go b/application/cmd/root.go index 28225dd9..c5f14e09 100644 --- a/application/cmd/root.go +++ b/application/cmd/root.go @@ -3,8 +3,6 @@ package cmd import ( "fmt" "github.com/duck8823/duci/application" - "github.com/duck8823/duci/infrastructure/logger" - "github.com/google/uuid" "github.com/spf13/cobra" "os" ) @@ -42,7 +40,7 @@ func readConfiguration(cmd *cobra.Command) { } if err := application.Config.Set(configFilePath); err != nil { - logger.Errorf(uuid.New(), "Failed to set configuration.\n%+v", err) + println(fmt.Sprintf("Failed to set configuration.\n%+v", err)) os.Exit(1) } } diff --git a/application/cmd/server.go b/application/cmd/server.go index 8421196f..13c6db1a 100644 --- a/application/cmd/server.go +++ b/application/cmd/server.go @@ -3,9 +3,7 @@ package cmd import ( "github.com/duck8823/duci/application" "github.com/duck8823/duci/application/semaphore" - "github.com/duck8823/duci/infrastructure/logger" "github.com/duck8823/duci/presentation/router" - "github.com/google/uuid" "github.com/spf13/cobra" "net/http" "os" @@ -28,21 +26,21 @@ func runServer(cmd *cobra.Command, _ []string) { readConfiguration(cmd) if err := semaphore.Make(); err != nil { - logger.Errorf(uuid.New(), "Failed to initialize a semaphore.\n%+v", err) + println("Failed to initialize a semaphore.\n%+v", err) os.Exit(1) return } rtr, err := router.New() if err != nil { - logger.Errorf(uuid.New(), "Failed to initialize controllers.\n%+v", err) + println("Failed to initialize controllers.\n%+v", err) os.Exit(1) return } println(logo) if err := http.ListenAndServe(application.Config.Addr(), rtr); err != nil { - logger.Errorf(uuid.New(), "Failed to run server.\n%+v", err) + println("Failed to run server.\n%+v", err) os.Exit(1) return } diff --git a/application/context/context.go b/application/context/context.go deleted file mode 100644 index c17395a0..00000000 --- a/application/context/context.go +++ /dev/null @@ -1,59 +0,0 @@ -package context - -import ( - "context" - "github.com/google/uuid" - "net/url" - "time" -) - -// Context is a context with UUID, TaskName and URL. -type Context interface { - context.Context - UUID() uuid.UUID - TaskName() string - URL() *url.URL -} - -type jobContext struct { - context.Context - uuid uuid.UUID - taskName string - url *url.URL -} - -// New returns a new jobContext. -func New(taskName string, id uuid.UUID, url *url.URL) Context { - return &jobContext{ - Context: context.Background(), - uuid: id, - taskName: taskName, - url: url, - } -} - -// UUID returns UUID from jobContext. -func (c *jobContext) UUID() uuid.UUID { - return c.uuid -} - -// TaskName returns URL from jobContext. -func (c *jobContext) TaskName() string { - return c.taskName -} - -// URL returns task name from jobContext. -func (c *jobContext) URL() *url.URL { - return c.url -} - -// WithTimeout returns copy of parent with timeout and CancelFunc. -func WithTimeout(parent Context, timeout time.Duration) (Context, context.CancelFunc) { - ctx, cancel := context.WithTimeout(parent, timeout) - return &jobContext{ - Context: ctx, - uuid: parent.UUID(), - taskName: parent.TaskName(), - url: parent.URL(), - }, cancel -} diff --git a/application/context/context_test.go b/application/context/context_test.go deleted file mode 100644 index d9163a0a..00000000 --- a/application/context/context_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package context_test - -import ( - ct "context" - "github.com/duck8823/duci/application/context" - "github.com/google/uuid" - "net/url" - "testing" - "time" -) - -func TestContextWithUUID_UUID(t *testing.T) { - // given - ctx := context.New("test/task", uuid.New(), &url.URL{}) - var empty uuid.UUID - - // expect - if ctx.UUID() == empty { - t.Error("UUID() must not empty.") - } -} - -func TestWithTimeout(t *testing.T) { - t.Run("when timeout", func(t *testing.T) { - // when - ctx, cancel := context.WithTimeout(context.New("test/task", uuid.New(), &url.URL{}), 5*time.Millisecond) - defer cancel() - - go func() { - time.Sleep(30 * time.Millisecond) - cancel() - }() - - <-ctx.Done() - - // then - if ctx.Err() != ct.DeadlineExceeded { - t.Errorf("not expected error. wont: %+v, but got %+v", ct.DeadlineExceeded, ctx.Err()) - } - }) - - t.Run("when cancel", func(t *testing.T) { - // when - ctx, cancel := context.WithTimeout(context.New("test/task", uuid.New(), &url.URL{}), 5*time.Millisecond) - defer cancel() - - go func() { - cancel() - }() - - <-ctx.Done() - - // then - if ctx.Err() != ct.Canceled { - t.Errorf("not expected error. wont: %+v, but got %+v", ct.Canceled, ctx.Err()) - } - }) -} diff --git a/application/service/docker/docker.go b/application/service/docker/docker.go deleted file mode 100644 index dfd9f253..00000000 --- a/application/service/docker/docker.go +++ /dev/null @@ -1,103 +0,0 @@ -package docker - -import ( - "context" - "github.com/duck8823/duci/infrastructure/docker" - "github.com/pkg/errors" - "io" -) - -// Log represents a log. -type Log = docker.Log - -// Tag describes a docker tag -type Tag string - -// Dockerfile represents a path to dockerfile -type Dockerfile string - -// RuntimeOptions represents a options -type RuntimeOptions = docker.RuntimeOptions - -// Command describes a docker CMD -type Command []string - -// ContainerID describes a container id of docker -type ContainerID string - -// ExitCode describes a exit code -type ExitCode int64 - -// Service is a interface describe docker service. -type Service interface { - Build(ctx context.Context, file io.Reader, tag Tag, dockerfile Dockerfile) (Log, error) - Run(ctx context.Context, opts RuntimeOptions, tag Tag, cmd Command) (ContainerID, Log, error) - Rm(ctx context.Context, containerID ContainerID) error - Rmi(ctx context.Context, tag Tag) error - ExitCode(ctx context.Context, containerID ContainerID) (ExitCode, error) - Status() error -} - -type serviceImpl struct { - moby docker.Client -} - -// New returns instance of docker service -func New() (Service, error) { - cli, err := docker.New() - if err != nil { - return nil, errors.WithStack(err) - } - return &serviceImpl{moby: cli}, nil -} - -// Build a docker image. -func (s *serviceImpl) Build(ctx context.Context, file io.Reader, tag Tag, dockerfile Dockerfile) (Log, error) { - log, err := s.moby.Build(ctx, file, string(tag), string(dockerfile)) - if err != nil { - return nil, errors.WithStack(err) - } - return log, nil -} - -// Run docker container with command. -func (s *serviceImpl) Run(ctx context.Context, opts RuntimeOptions, tag Tag, cmd Command) (ContainerID, Log, error) { - conID, log, err := s.moby.Run(ctx, opts, string(tag), cmd...) - if err != nil { - return ContainerID(conID), nil, errors.WithStack(err) - } - return ContainerID(conID), log, nil -} - -// Rm remove docker container. -func (s *serviceImpl) Rm(ctx context.Context, conID ContainerID) error { - if err := s.moby.Rm(ctx, string(conID)); err != nil { - return errors.WithStack(err) - } - return nil -} - -// Rmi remove docker image. -func (s *serviceImpl) Rmi(ctx context.Context, tag Tag) error { - if err := s.moby.Rmi(ctx, string(tag)); err != nil { - return errors.WithStack(err) - } - return nil -} - -// ExitCode returns exit code specific container id. -func (s *serviceImpl) ExitCode(ctx context.Context, conID ContainerID) (ExitCode, error) { - code, err := s.moby.ExitCode(ctx, string(conID)) - if err != nil { - return ExitCode(code), errors.WithStack(err) - } - return ExitCode(code), nil -} - -// Status returns error of docker daemon status. -func (s *serviceImpl) Status() error { - if _, err := s.moby.Info(context.Background()); err != nil { - return errors.Wrap(err, "Couldn't connect to Docker daemon.") - } - return nil -} diff --git a/application/service/docker/mock_docker/docker.go b/application/service/docker/mock_docker/docker.go deleted file mode 100644 index 837f4c3b..00000000 --- a/application/service/docker/mock_docker/docker.go +++ /dev/null @@ -1,112 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: application/service/docker/docker.go - -// Package mock_docker is a generated GoMock package. -package mock_docker - -import ( - context "context" - docker "github.com/duck8823/duci/application/service/docker" - gomock "github.com/golang/mock/gomock" - io "io" - reflect "reflect" -) - -// MockService is a mock of Service interface -type MockService struct { - ctrl *gomock.Controller - recorder *MockServiceMockRecorder -} - -// MockServiceMockRecorder is the mock recorder for MockService -type MockServiceMockRecorder struct { - mock *MockService -} - -// NewMockService creates a new mock instance -func NewMockService(ctrl *gomock.Controller) *MockService { - mock := &MockService{ctrl: ctrl} - mock.recorder = &MockServiceMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockService) EXPECT() *MockServiceMockRecorder { - return m.recorder -} - -// Build mocks base method -func (m *MockService) Build(ctx context.Context, file io.Reader, tag docker.Tag, dockerfile docker.Dockerfile) (docker.Log, error) { - ret := m.ctrl.Call(m, "Build", ctx, file, tag, dockerfile) - ret0, _ := ret[0].(docker.Log) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Build indicates an expected call of Build -func (mr *MockServiceMockRecorder) Build(ctx, file, tag, dockerfile interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Build", reflect.TypeOf((*MockService)(nil).Build), ctx, file, tag, dockerfile) -} - -// Run mocks base method -func (m *MockService) Run(ctx context.Context, opts docker.RuntimeOptions, tag docker.Tag, cmd docker.Command) (docker.ContainerID, docker.Log, error) { - ret := m.ctrl.Call(m, "Run", ctx, opts, tag, cmd) - ret0, _ := ret[0].(docker.ContainerID) - ret1, _ := ret[1].(docker.Log) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// Run indicates an expected call of Run -func (mr *MockServiceMockRecorder) Run(ctx, opts, tag, cmd interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Run", reflect.TypeOf((*MockService)(nil).Run), ctx, opts, tag, cmd) -} - -// Rm mocks base method -func (m *MockService) Rm(ctx context.Context, containerID docker.ContainerID) error { - ret := m.ctrl.Call(m, "Rm", ctx, containerID) - ret0, _ := ret[0].(error) - return ret0 -} - -// Rm indicates an expected call of Rm -func (mr *MockServiceMockRecorder) Rm(ctx, containerID interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Rm", reflect.TypeOf((*MockService)(nil).Rm), ctx, containerID) -} - -// Rmi mocks base method -func (m *MockService) Rmi(ctx context.Context, tag docker.Tag) error { - ret := m.ctrl.Call(m, "Rmi", ctx, tag) - ret0, _ := ret[0].(error) - return ret0 -} - -// Rmi indicates an expected call of Rmi -func (mr *MockServiceMockRecorder) Rmi(ctx, tag interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Rmi", reflect.TypeOf((*MockService)(nil).Rmi), ctx, tag) -} - -// ExitCode mocks base method -func (m *MockService) ExitCode(ctx context.Context, containerID docker.ContainerID) (docker.ExitCode, error) { - ret := m.ctrl.Call(m, "ExitCode", ctx, containerID) - ret0, _ := ret[0].(docker.ExitCode) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ExitCode indicates an expected call of ExitCode -func (mr *MockServiceMockRecorder) ExitCode(ctx, containerID interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExitCode", reflect.TypeOf((*MockService)(nil).ExitCode), ctx, containerID) -} - -// Status mocks base method -func (m *MockService) Status() error { - ret := m.ctrl.Call(m, "Status") - ret0, _ := ret[0].(error) - return ret0 -} - -// Status indicates an expected call of Status -func (mr *MockServiceMockRecorder) Status() *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Status", reflect.TypeOf((*MockService)(nil).Status)) -} diff --git a/application/service/git/export_test.go b/application/service/git/export_test.go deleted file mode 100644 index cbfa9297..00000000 --- a/application/service/git/export_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package git - -import ( - "gopkg.in/src-d/go-git.v4" - "gopkg.in/src-d/go-git.v4/plumbing" -) - -func SetPlainCloneFunc(f func(path string, isBare bool, o *git.CloneOptions) (*git.Repository, error)) (reset func()) { - tmp := plainClone - plainClone = f - return func() { - plainClone = tmp - } -} - -type MockTargetSource struct { - URL string - Ref string - SHA plumbing.Hash -} - -func (t *MockTargetSource) GetURL() string { - return t.URL -} - -func (t *MockTargetSource) GetRef() string { - return t.Ref -} - -func (t *MockTargetSource) GetSHA() plumbing.Hash { - return t.SHA -} diff --git a/application/service/git/git.go b/application/service/git/git.go deleted file mode 100644 index 9249fa7f..00000000 --- a/application/service/git/git.go +++ /dev/null @@ -1,96 +0,0 @@ -package git - -import ( - "github.com/duck8823/duci/application" - "github.com/duck8823/duci/application/context" - "github.com/pkg/errors" - "gopkg.in/src-d/go-git.v4" - "gopkg.in/src-d/go-git.v4/plumbing" - "gopkg.in/src-d/go-git.v4/plumbing/transport" - "gopkg.in/src-d/go-git.v4/plumbing/transport/ssh" -) - -var plainClone = git.PlainClone - -// TargetSource is a interface returns clone URL, Ref and SHA for target -type TargetSource interface { - GetURL() string - GetRef() string - GetSHA() plumbing.Hash -} - -// Service describes a git service. -type Service interface { - Clone(ctx context.Context, dir string, src TargetSource) error -} - -type sshGitService struct { - auth transport.AuthMethod -} - -type httpGitService struct{} - -// New returns the Service. -func New() (Service, error) { - if application.Config.GitHub.SSHKeyPath == "" { - return &httpGitService{}, nil - } - auth, err := ssh.NewPublicKeysFromFile("git", application.Config.GitHub.SSHKeyPath, "") - if err != nil { - return nil, err - } - return &sshGitService{auth: auth}, nil -} - -// Clone a repository into the path with target source. -func (s *sshGitService) Clone(ctx context.Context, dir string, src TargetSource) error { - gitRepository, err := plainClone(dir, false, &git.CloneOptions{ - URL: src.GetURL(), - Auth: s.auth, - Progress: &ProgressLogger{ctx.UUID()}, - ReferenceName: plumbing.ReferenceName(src.GetRef()), - Depth: 1, - }) - if err != nil { - return errors.WithStack(err) - } - - if err := checkout(gitRepository, src.GetSHA()); err != nil { - return errors.WithStack(err) - } - return nil -} - -// Clone a repository into the path with target source. -func (s *httpGitService) Clone(ctx context.Context, dir string, src TargetSource) error { - gitRepository, err := plainClone(dir, false, &git.CloneOptions{ - URL: src.GetURL(), - Progress: &ProgressLogger{ctx.UUID()}, - ReferenceName: plumbing.ReferenceName(src.GetRef()), - Depth: 1, - }) - if err != nil { - return errors.WithStack(err) - } - - if err := checkout(gitRepository, src.GetSHA()); err != nil { - return errors.WithStack(err) - } - return nil -} - -func checkout(repo *git.Repository, sha plumbing.Hash) error { - wt, err := repo.Worktree() - if err != nil { - return errors.WithStack(err) - } - - if err := wt.Checkout(&git.CheckoutOptions{ - Hash: sha, - Branch: plumbing.ReferenceName(sha.String()), - Create: true, - }); err != nil { - return errors.WithStack(err) - } - return nil -} diff --git a/application/service/git/git_test.go b/application/service/git/git_test.go deleted file mode 100644 index a108e676..00000000 --- a/application/service/git/git_test.go +++ /dev/null @@ -1,307 +0,0 @@ -package git_test - -import ( - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "encoding/pem" - "fmt" - "github.com/duck8823/duci/application" - "github.com/duck8823/duci/application/context" - "github.com/duck8823/duci/application/service/git" - "github.com/google/uuid" - "github.com/labstack/gommon/random" - "github.com/pkg/errors" - go_git "gopkg.in/src-d/go-git.v4" - "gopkg.in/src-d/go-git.v4/plumbing" - "gopkg.in/src-d/go-git.v4/plumbing/object" - "net/url" - "os" - "path/filepath" - "testing" -) - -func TestNew(t *testing.T) { - t.Run("when without ssh key path", func(t *testing.T) { - // expect - if _, err := git.New(); err != nil { - t.Error("error must not occur") - } - }) - - t.Run("when missing ssh key path", func(t *testing.T) { - // given - application.Config.GitHub.SSHKeyPath = "/path/to/wrong" - - // expect - if _, err := git.New(); err == nil { - t.Error("error must occur") - } - }) -} - -func TestSshGitService_Clone(t *testing.T) { - // setup - path, remove := createTemporaryKey(t) - defer remove() - application.Config.GitHub.SSHKeyPath = path - - t.Run("when failure git clone", func(t *testing.T) { - // given - reset := git.SetPlainCloneFunc(func(_ string, _ bool, _ *go_git.CloneOptions) (*go_git.Repository, error) { - return nil, errors.New("test") - }) - defer reset() - - // and - sut, err := git.New() - if err != nil { - t.Fatalf("error occurred. %+v", err) - } - - // expect - if err := sut.Clone( - context.New("test/task", uuid.New(), &url.URL{}), - "", - &git.MockTargetSource{}, - ); err == nil { - t.Error("error must not nil.") - } - }) - - t.Run("when success git clone", func(t *testing.T) { - // setup - dirStr := fmt.Sprintf("duci_test_%s", random.String(16, random.Alphanumeric)) - tempDir := filepath.Join(os.TempDir(), dirStr) - if err := os.MkdirAll(tempDir, 0700); err != nil { - t.Fatalf("%+v", err) - } - - // and - var hash plumbing.Hash - reset := git.SetPlainCloneFunc(func(_ string, _ bool, _ *go_git.CloneOptions) (*go_git.Repository, error) { - // git init - repo, err := go_git.PlainInit(tempDir, false) - if err != nil { - t.Fatalf("error occur: %+v", err) - } - w, err := repo.Worktree() - if err != nil { - t.Fatalf("error occur: %+v", err) - } - // commit - hash, err = w.Commit("init. commit", &go_git.CommitOptions{ - Author: &object.Signature{}, - }) - if err != nil { - t.Fatalf("error occur: %+v", err) - } - return repo, nil - }) - defer reset() - - // and - sut, err := git.New() - if err != nil { - t.Fatalf("error occurred. %+v", err) - } - - // expect - if err := sut.Clone( - context.New("test/task", uuid.New(), &url.URL{}), - "", - &git.MockTargetSource{ - Ref: "HEAD", - SHA: hash, - }, - ); err != nil { - t.Errorf("error must not occur. but got %+v", err) - } - }) - - t.Run("when failure git checkout", func(t *testing.T) { - // setup - dirStr := fmt.Sprintf("duci_test_%s", random.String(16, random.Alphanumeric)) - tempDir := filepath.Join(os.TempDir(), dirStr) - if err := os.MkdirAll(tempDir, 0700); err != nil { - t.Fatalf("%+v", err) - } - - // and - reset := git.SetPlainCloneFunc(func(_ string, _ bool, _ *go_git.CloneOptions) (*go_git.Repository, error) { - // git init - repo, err := go_git.PlainInit(tempDir, false) - if err != nil { - t.Fatalf("error occur: %+v", err) - } - return repo, nil - }) - defer reset() - - // and - sut, err := git.New() - if err != nil { - t.Fatalf("error occurred. %+v", err) - } - - // expect - if err := sut.Clone( - context.New("test/task", uuid.New(), &url.URL{}), - "", - &git.MockTargetSource{ - Ref: "HEAD", - }, - ); err == nil { - t.Error("error must occur. but got nil") - } - }) -} - -func TestHttpGitService_Clone(t *testing.T) { - // setup - application.Config.GitHub.SSHKeyPath = "" - - t.Run("when failure git clone", func(t *testing.T) { - // given - reset := git.SetPlainCloneFunc(func(_ string, _ bool, _ *go_git.CloneOptions) (*go_git.Repository, error) { - return nil, errors.New("test") - }) - defer reset() - - // and - sut, err := git.New() - if err != nil { - t.Fatalf("error occurred. %+v", err) - } - - // expect - if err := sut.Clone( - context.New("test/task", uuid.New(), &url.URL{}), - "", - &git.MockTargetSource{}, - ); err == nil { - t.Error("error must not nil.") - } - }) - - t.Run("when success git clone", func(t *testing.T) { - // setup - dirStr := fmt.Sprintf("duci_test_%s", random.String(16, random.Alphanumeric)) - tempDir := filepath.Join(os.TempDir(), dirStr) - if err := os.MkdirAll(tempDir, 0700); err != nil { - t.Fatalf("%+v", err) - } - - // and - var hash plumbing.Hash - reset := git.SetPlainCloneFunc(func(_ string, _ bool, _ *go_git.CloneOptions) (*go_git.Repository, error) { - // git init - repo, err := go_git.PlainInit(tempDir, false) - if err != nil { - t.Fatalf("error occur: %+v", err) - } - w, err := repo.Worktree() - if err != nil { - t.Fatalf("error occur: %+v", err) - } - // commit - hash, err = w.Commit("init. commit", &go_git.CommitOptions{ - Author: &object.Signature{}, - }) - if err != nil { - t.Fatalf("error occur: %+v", err) - } - return repo, nil - }) - defer reset() - - // and - sut, err := git.New() - if err != nil { - t.Fatalf("error occurred. %+v", err) - } - - // expect - if err := sut.Clone( - context.New("test/task", uuid.New(), &url.URL{}), - "", - &git.MockTargetSource{ - Ref: "HEAD", - SHA: hash, - }, - ); err != nil { - t.Errorf("error must not occur. but got %+v", err) - } - }) - - t.Run("when failure git checkout", func(t *testing.T) { - // setup - dirStr := fmt.Sprintf("duci_test_%s", random.String(16, random.Alphanumeric)) - tempDir := filepath.Join(os.TempDir(), dirStr) - if err := os.MkdirAll(tempDir, 0700); err != nil { - t.Fatalf("%+v", err) - } - - // and - reset := git.SetPlainCloneFunc(func(_ string, _ bool, _ *go_git.CloneOptions) (*go_git.Repository, error) { - // git init - repo, err := go_git.PlainInit(tempDir, false) - if err != nil { - t.Fatalf("error occur: %+v", err) - } - return repo, nil - }) - defer reset() - - // and - sut, err := git.New() - if err != nil { - t.Fatalf("error occurred. %+v", err) - } - - // expect - if err := sut.Clone( - context.New("test/task", uuid.New(), &url.URL{}), - "", - &git.MockTargetSource{ - Ref: "HEAD", - }, - ); err == nil { - t.Error("error must occur. but got nil") - } - }) -} - -func createTemporaryKey(t *testing.T) (path string, reset func()) { - t.Helper() - - privateKey, err := rsa.GenerateKey(rand.Reader, 256) - if err != nil { - t.Fatalf("error occur: %+v", err) - } - privateKeyDer := x509.MarshalPKCS1PrivateKey(privateKey) - privateKeyBlock := pem.Block{ - Type: "RSA PRIVATE KEY", - Headers: nil, - Bytes: privateKeyDer, - } - privateKeyPem := string(pem.EncodeToMemory(&privateKeyBlock)) - - tempDir := filepath.Join(os.TempDir(), random.String(16, random.Alphanumeric)) - if err := os.MkdirAll(tempDir, 0700); err != nil { - t.Fatalf("error occur: %+v", err) - } - keyPath := filepath.Join(tempDir, "id_rsa") - file, err := os.OpenFile(keyPath, os.O_WRONLY|os.O_CREATE, 0600) - if err != nil { - t.Fatalf("error occur: %+v", err) - } - - if _, err := file.WriteString(privateKeyPem); err != nil { - t.Fatalf("error occur: %+v", err) - } - - return keyPath, func() { - os.RemoveAll(tempDir) - } -} diff --git a/application/service/git/mock_git/git.go b/application/service/git/mock_git/git.go deleted file mode 100644 index 6ed0dbe7..00000000 --- a/application/service/git/mock_git/git.go +++ /dev/null @@ -1,47 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: application/service/git/git.go - -// Package mock_git is a generated GoMock package. -package mock_git - -import ( - context "github.com/duck8823/duci/application/context" - git "github.com/duck8823/duci/application/service/git" - gomock "github.com/golang/mock/gomock" - reflect "reflect" -) - -// MockService is a mock of Git interface -type MockService struct { - ctrl *gomock.Controller - recorder *MockServiceMockRecorder -} - -// MockServiceMockRecorder is the mock recorder for MockService -type MockServiceMockRecorder struct { - mock *MockService -} - -// NewMockService creates a new mock instance -func NewMockService(ctrl *gomock.Controller) *MockService { - mock := &MockService{ctrl: ctrl} - mock.recorder = &MockServiceMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockService) EXPECT() *MockServiceMockRecorder { - return m.recorder -} - -// Clone mocks base method -func (m *MockService) Clone(ctx context.Context, dir string, src git.TargetSource) error { - ret := m.ctrl.Call(m, "Clone", ctx, dir, src) - ret0, _ := ret[0].(error) - return ret0 -} - -// Clone indicates an expected call of Clone -func (mr *MockServiceMockRecorder) Clone(ctx, dir, src interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Clone", reflect.TypeOf((*MockService)(nil).Clone), ctx, dir, src) -} diff --git a/application/service/git/progress_logger.go b/application/service/git/progress_logger.go deleted file mode 100644 index 79b6ca04..00000000 --- a/application/service/git/progress_logger.go +++ /dev/null @@ -1,24 +0,0 @@ -package git - -import ( - "github.com/duck8823/duci/infrastructure/logger" - "github.com/google/uuid" - "regexp" -) - -// Regexp to remove CR or later (inline progress) -var rep = regexp.MustCompile("\r.*$") - -// ProgressLogger is a writer for git progress -type ProgressLogger struct { - uuid uuid.UUID -} - -// Write a log without CR or later. -func (l *ProgressLogger) Write(p []byte) (n int, err error) { - log := rep.ReplaceAllString(string(p), "") - if len(log) > 0 { - logger.Info(l.uuid, log) - } - return 0, nil -} diff --git a/application/service/git/progress_logger_test.go b/application/service/git/progress_logger_test.go deleted file mode 100644 index 03b37fd2..00000000 --- a/application/service/git/progress_logger_test.go +++ /dev/null @@ -1,56 +0,0 @@ -package git_test - -import ( - "github.com/duck8823/duci/application/service/git" - "github.com/duck8823/duci/infrastructure/logger" - "io" - "io/ioutil" - "os" - "regexp" - "strings" - "testing" -) - -var regex = regexp.MustCompile(`\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}`) - -func TestProgressLogger_Write(t *testing.T) { - // setup - reader, writer, err := os.Pipe() - if err != nil { - t.Fatalf("error occurred. %+v", err) - } - defer reader.Close() - - logger.Writer = writer - - // given - progress := &git.ProgressLogger{} - - // when - progress.Write([]byte("hoge\rfuga")) - writer.Close() - - actual := readLogTrimmedTime(t, reader) - expected := "[00000000-0000-0000-0000-000000000000] \033[1m[INFO]\033[0m hoge" - - // then - if actual != expected { - t.Errorf("must remove CR flag or later. wont: %+v, but got: %+v", expected, actual) - } -} - -func readLogTrimmedTime(t *testing.T, reader io.Reader) string { - t.Helper() - - bytes, err := ioutil.ReadAll(reader) - if err != nil { - t.Fatalf("error occurred. %+v", err) - } - - log := string(bytes) - if !regex.MatchString(log) { - t.Fatalf("invalid format. %+v", log) - } - - return strings.TrimRight(regex.ReplaceAllString(log, ""), "\n") -} diff --git a/application/service/github/alias.go b/application/service/github/alias.go deleted file mode 100644 index acf8f9a9..00000000 --- a/application/service/github/alias.go +++ /dev/null @@ -1,16 +0,0 @@ -package github - -import "github.com/google/go-github/github" - -// Repository is a interface to get information of git repository. -type Repository interface { - GetFullName() string - GetSSHURL() string - GetCloneURL() string -} - -// PullRequest is a type alias of github.PullRequest -type PullRequest = github.PullRequest - -// Status is a type alias of github.RepoStatus -type Status = github.RepoStatus diff --git a/application/service/github/export_test.go b/application/service/github/export_test.go deleted file mode 100644 index cb9d885e..00000000 --- a/application/service/github/export_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package github - -type MockRepo struct { - FullName string - SSHURL string - CloneURL string -} - -func (r *MockRepo) GetFullName() string { - return r.FullName -} - -func (r *MockRepo) GetSSHURL() string { - return r.SSHURL -} - -func (r *MockRepo) GetCloneURL() string { - return r.CloneURL -} diff --git a/application/service/github/github.go b/application/service/github/github.go deleted file mode 100644 index deccd917..00000000 --- a/application/service/github/github.go +++ /dev/null @@ -1,109 +0,0 @@ -package github - -import ( - ctx "context" - "github.com/duck8823/duci/application" - "github.com/duck8823/duci/application/context" - "github.com/duck8823/duci/infrastructure/logger" - "github.com/google/go-github/github" - "github.com/pkg/errors" - "golang.org/x/oauth2" - "path" -) - -// State represents state of commit status -type State = string - -const ( - // PENDING represents pending state. - PENDING State = "pending" - // SUCCESS represents success state. - SUCCESS State = "success" - // ERROR represents error state. - ERROR State = "error" - // FAILURE represents failure state. - FAILURE State = "failure" -) - -// Service describes a github service. -type Service interface { - GetPullRequest(ctx context.Context, repository Repository, num int) (*PullRequest, error) - CreateCommitStatus(ctx context.Context, src *TargetSource, state State, description string) error -} - -type serviceImpl struct { - cli *github.Client -} - -// New returns a github service. -func New() (Service, error) { - ts := oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: string(application.Config.GitHub.APIToken)}, - ) - tc := oauth2.NewClient(ctx.Background(), ts) - - return &serviceImpl{github.NewClient(tc)}, nil -} - -// GetPullRequest returns a pull request with specific repository and number. -func (s *serviceImpl) GetPullRequest(ctx context.Context, repository Repository, num int) (*PullRequest, error) { - name := &RepositoryName{repository.GetFullName()} - owner, err := name.Owner() - if err != nil { - return nil, errors.WithStack(err) - } - repo, err := name.Repo() - if err != nil { - return nil, errors.WithStack(err) - } - pr, resp, err := s.cli.PullRequests.Get( - ctx, - owner, - repo, - num, - ) - if err != nil { - logger.Errorf(ctx.UUID(), "Failed to get pull request no. %v on %s: %+v", num, repository.GetFullName(), resp) - return nil, errors.WithStack(err) - } - return pr, nil -} - -// CreateCommitStatus create commit status to github. -func (s *serviceImpl) CreateCommitStatus(ctx context.Context, src *TargetSource, state State, description string) error { - name := &RepositoryName{src.Repo.GetFullName()} - owner, err := name.Owner() - if err != nil { - return errors.WithStack(err) - } - repo, err := name.Repo() - if err != nil { - return errors.WithStack(err) - } - - taskName := ctx.TaskName() - if len(description) >= 50 { - description = string([]rune(description)[:46]) + "..." - } - targetURL := *ctx.URL() - targetURL.Path = path.Join(targetURL.Path, "logs", ctx.UUID().String()) - targetURLStr := targetURL.String() - status := &Status{ - Context: &taskName, - Description: &description, - State: &state, - TargetURL: &targetURLStr, - } - - if _, _, err := s.cli.Repositories.CreateStatus( - ctx, - owner, - repo, - src.SHA.String(), - status, - ); err != nil { - logger.Errorf(ctx.UUID(), "Failed to create commit status: %+v", err) - return errors.WithStack(err) - } - return nil -} diff --git a/application/service/github/github_test.go b/application/service/github/github_test.go deleted file mode 100644 index a8719fb9..00000000 --- a/application/service/github/github_test.go +++ /dev/null @@ -1,208 +0,0 @@ -package github_test - -import ( - "fmt" - "github.com/duck8823/duci/application/context" - "github.com/duck8823/duci/application/service/github" - "github.com/google/uuid" - "gopkg.in/h2non/gock.v1" - "gopkg.in/src-d/go-git.v4/plumbing" - "io/ioutil" - "net/url" - "testing" -) - -func TestService_GetPullRequest(t *testing.T) { - // setup - s, err := github.New() - if err != nil { - t.Fatalf("error occurred. %+v", err) - } - - t.Run("when github server returns status ok", func(t *testing.T) { - // given - repo := &github.MockRepo{ - FullName: "duck8823/duci", - SSHURL: "git@github.com:duck8823/duci.git", - } - num := 5 - var id int64 = 19 - - // and - gock.New("https://api.github.com"). - Get(fmt.Sprintf("/repos/%s/pulls/%d", repo.FullName, num)). - Reply(200). - JSON(&github.PullRequest{ - ID: &id, - }) - defer gock.Clean() - - // when - pr, err := s.GetPullRequest(context.New("test/task", uuid.New(), &url.URL{}), repo, num) - - // then - if err != nil { - t.Fatalf("error occurred. %+v", err) - } - - if pr.GetID() != id { - t.Errorf("id must be equal %+v, but got %+v. \npr=%+v", id, pr.GetID(), pr) - } - }) - - t.Run("when github server returns status not found", func(t *testing.T) { - // given - repo := &github.MockRepo{ - FullName: "duck8823/duci", - SSHURL: "git@github.com:duck8823/duci.git", - } - num := 5 - - // and - gock.New("https://api.github.com"). - Get(fmt.Sprintf("/repos/%s/pulls/%d", repo.FullName, num)). - Reply(404) - defer gock.Clean() - - // when - pr, err := s.GetPullRequest(context.New("test/task", uuid.New(), &url.URL{}), repo, num) - - // then - if err == nil { - t.Error("error must occur") - } - - if pr != nil { - t.Errorf("pr must nil, but got %+v", pr) - } - }) - - t.Run("with invalid repository", func(t *testing.T) { - // given - repo := &github.MockRepo{ - FullName: "", - } - num := 5 - - // expect - if _, err := s.GetPullRequest(context.New("test/task", uuid.New(), &url.URL{}), repo, num); err == nil { - t.Error("error must occurred. but got nil") - } - }) -} - -func TestService_CreateCommitStatus(t *testing.T) { - // setup - s, err := github.New() - if err != nil { - t.Fatalf("error occurred. %+v", err) - } - - t.Run("when github server returns status ok", func(t *testing.T) { - // given - repo := &github.MockRepo{ - FullName: "duck8823/duci", - } - - // and - gock.New("https://api.github.com"). - Post(fmt.Sprintf("/repos/%s/statuses/%s", repo.FullName, "0000000000000000000000000000000000000000")). - Reply(200) - defer gock.Clean() - - // expect - if err := s.CreateCommitStatus( - context.New("test/task", uuid.New(), &url.URL{}), - &github.TargetSource{Repo: repo, SHA: plumbing.Hash{}}, - github.SUCCESS, - "", - ); err != nil { - t.Errorf("error must not occurred: but got %+v", err) - } - }) - - t.Run("when github server returns status not found", func(t *testing.T) { - // given - repo := &github.MockRepo{ - FullName: "duck8823/duci", - } - - // and - gock.New("https://api.github.com"). - Post(fmt.Sprintf("/repos/%s/statuses/%s", repo.FullName, "0000000000000000000000000000000000000000")). - Reply(404) - defer gock.Clean() - - // expect - if err := s.CreateCommitStatus( - context.New("test/task", uuid.New(), &url.URL{}), - &github.TargetSource{Repo: repo, SHA: plumbing.Hash{}}, - github.SUCCESS, - "", - ); err == nil { - t.Error("errot must occred. but got nil") - } - }) - - t.Run("with invalid repository", func(t *testing.T) { - // given - repo := &github.MockRepo{ - FullName: "", - } - - // expect - if err := s.CreateCommitStatus( - context.New("test/task", uuid.New(), &url.URL{}), - &github.TargetSource{Repo: repo, SHA: plumbing.Hash{}}, - github.SUCCESS, - "", - ); err == nil { - t.Error("error must occurred. but got nil") - } - }) - - t.Run("with long description", func(t *testing.T) { - // given - repo := &github.MockRepo{ - FullName: "duck8823/duci", - } - - // and - taskName := "test/task" - description := "123456789012345678901234567890123456789012345678901234567890" - malformedDescription := "1234567890123456789012345678901234567890123456..." - state := github.SUCCESS - requestID := uuid.New() - logUrl := fmt.Sprintf("http://host:8080/logs/%s", requestID.String()) - - gock.New("https://api.github.com"). - Post(fmt.Sprintf("/repos/%s/statuses/%s", repo.FullName, "0000000000000000000000000000000000000000")). - MatchType("json"). - JSON(&github.Status{ - Context: &taskName, - Description: &malformedDescription, - State: &state, - TargetURL: &logUrl, - }). - Reply(404) - defer gock.Clean() - - // expect - if err := s.CreateCommitStatus( - context.New(taskName, requestID, &url.URL{Scheme: "http", Host: "host:8080"}), - &github.TargetSource{Repo: repo, SHA: plumbing.Hash{}}, - state, - description, - ); err == nil { - t.Error("error must occurred. but got nil") - } - - if !gock.IsDone() { - t.Error("request missing...") - for _, req := range gock.GetUnmatchedRequests() { - bytes, _ := ioutil.ReadAll(req.Body) - t.Logf("%+v", string(bytes)) - } - } - }) -} diff --git a/application/service/github/mock_github/github.go b/application/service/github/mock_github/github.go deleted file mode 100644 index 37b521d5..00000000 --- a/application/service/github/mock_github/github.go +++ /dev/null @@ -1,60 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: application/service/github/github_push.go - -// Package mock_github is a generated GoMock package. -package mock_github - -import ( - context "github.com/duck8823/duci/application/context" - github "github.com/duck8823/duci/application/service/github" - gomock "github.com/golang/mock/gomock" - reflect "reflect" -) - -// MockService is a mock of GitHub interface -type MockService struct { - ctrl *gomock.Controller - recorder *MockServiceMockRecorder -} - -// MockServiceMockRecorder is the mock recorder for MockService -type MockServiceMockRecorder struct { - mock *MockService -} - -// NewMockService creates a new mock instance -func NewMockService(ctrl *gomock.Controller) *MockService { - mock := &MockService{ctrl: ctrl} - mock.recorder = &MockServiceMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockService) EXPECT() *MockServiceMockRecorder { - return m.recorder -} - -// GetPullRequest mocks base method -func (m *MockService) GetPullRequest(ctx context.Context, repository github.Repository, num int) (*github.PullRequest, error) { - ret := m.ctrl.Call(m, "GetPullRequest", ctx, repository, num) - ret0, _ := ret[0].(*github.PullRequest) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetPullRequest indicates an expected call of GetPullRequest -func (mr *MockServiceMockRecorder) GetPullRequest(ctx, repository, num interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPullRequest", reflect.TypeOf((*MockService)(nil).GetPullRequest), ctx, repository, num) -} - -// CreateCommitStatus mocks base method -func (m *MockService) CreateCommitStatus(ctx context.Context, src *github.TargetSource, state github.State, description string) error { - ret := m.ctrl.Call(m, "CreateCommitStatus", ctx, src, state, description) - ret0, _ := ret[0].(error) - return ret0 -} - -// CreateCommitStatus indicates an expected call of CreateCommitStatus -func (mr *MockServiceMockRecorder) CreateCommitStatus(ctx, src, state, description interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateCommitStatus", reflect.TypeOf((*MockService)(nil).CreateCommitStatus), ctx, src, state, description) -} diff --git a/application/service/github/repository_name.go b/application/service/github/repository_name.go deleted file mode 100644 index aa803f72..00000000 --- a/application/service/github/repository_name.go +++ /dev/null @@ -1,29 +0,0 @@ -package github - -import ( - "fmt" - "strings" -) - -// RepositoryName is a github repository name. -type RepositoryName struct { - FullName string -} - -// Owner get a repository owner. -func (r *RepositoryName) Owner() (string, error) { - ss := strings.Split(r.FullName, "/") - if len(ss) != 2 { - return "", fmt.Errorf("Invalid repository name: %s ", r.FullName) - } - return ss[0], nil -} - -// Repo get a repository name without owner. -func (r *RepositoryName) Repo() (string, error) { - ss := strings.Split(r.FullName, "/") - if len(ss) != 2 { - return "", fmt.Errorf("Invalid repository name: %s ", r.FullName) - } - return ss[1], nil -} diff --git a/application/service/github/repository_name_test.go b/application/service/github/repository_name_test.go deleted file mode 100644 index afa29875..00000000 --- a/application/service/github/repository_name_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package github_test - -import ( - "github.com/duck8823/duci/application/service/github" - "testing" -) - -func TestRepositoryName_Owner(t *testing.T) { - t.Run("with correct name", func(t *testing.T) { - // given - name := &github.RepositoryName{FullName: "hoge/fuga"} - - // and - expected := "hoge" - - // when - owner, err := name.Owner() - - // then - if err != nil { - t.Fatalf("must not error. %+v", err) - } - if owner != expected { - t.Errorf("owner must be equal %+v, but got %+v", expected, owner) - } - }) - - t.Run("with invalid name", func(t *testing.T) { - // given - name := &github.RepositoryName{FullName: "hoge"} - - // when - _, err := name.Owner() - - // then - if err == nil { - t.Fatalf("must error.") - } - }) -} - -func TestRepositoryName_Repo(t *testing.T) { - t.Run("with correct name", func(t *testing.T) { - // given - name := &github.RepositoryName{FullName: "hoge/fuga"} - - // and - expected := "fuga" - - // when - owner, err := name.Repo() - - // then - if err != nil { - t.Fatalf("must not error. %+v", err) - } - if owner != expected { - t.Errorf("owner must be equal %+v, but got %+v", expected, owner) - } - }) - - t.Run("with invalid name", func(t *testing.T) { - // given - name := &github.RepositoryName{FullName: "hoge"} - - // when - _, err := name.Repo() - - // then - if err == nil { - t.Fatalf("must error.") - } - }) -} diff --git a/application/service/github/target_source.go b/application/service/github/target_source.go deleted file mode 100644 index c25e999a..00000000 --- a/application/service/github/target_source.go +++ /dev/null @@ -1,31 +0,0 @@ -package github - -import ( - "github.com/duck8823/duci/application" - "gopkg.in/src-d/go-git.v4/plumbing" -) - -// TargetSource stores Repo, Ref and SHA for target -type TargetSource struct { - Repo Repository - Ref string - SHA plumbing.Hash -} - -// GetURL returns a clone URL -func (s *TargetSource) GetURL() string { - if application.Config.GitHub.SSHKeyPath != "" { - return s.Repo.GetSSHURL() - } - return s.Repo.GetCloneURL() -} - -// GetRef returns a ref -func (s *TargetSource) GetRef() string { - return s.Ref -} - -// GetSHA returns a hash -func (s *TargetSource) GetSHA() plumbing.Hash { - return s.SHA -} diff --git a/application/service/github/target_source_test.go b/application/service/github/target_source_test.go deleted file mode 100644 index b8179cf4..00000000 --- a/application/service/github/target_source_test.go +++ /dev/null @@ -1,76 +0,0 @@ -package github_test - -import ( - "github.com/duck8823/duci/application" - "github.com/duck8823/duci/application/service/github" - "gopkg.in/src-d/go-git.v4/plumbing" - "testing" -) - -func TestTargetSource_GetURL(t *testing.T) { - t.Run("without ssh key path", func(t *testing.T) { - // given - application.Config.GitHub.SSHKeyPath = "" - - // and - expected := "clone_url" - - sut := github.TargetSource{ - Repo: &github.MockRepo{SSHURL: "ssh_url", CloneURL: expected}, - } - - // expect - if sut.GetURL() != expected { - t.Errorf("url must equal. wont %#v, but got %#v", expected, sut.GetURL()) - } - }) - - t.Run("without ssh key path", func(t *testing.T) { - // given - application.Config.GitHub.SSHKeyPath = "path/to/ssh_key" - - // and - expected := "ssh_url" - - sut := github.TargetSource{ - Repo: &github.MockRepo{SSHURL: expected, CloneURL: "clone_url"}, - } - - // expect - if sut.GetURL() != expected { - t.Errorf("url must equal. wont %#v, but got %#v", expected, sut.GetURL()) - } - }) -} - -func TestTargetSource_GetRef(t *testing.T) { - // given - expected := "ref" - - // and - sut := github.TargetSource{Ref: expected} - - // when - actual := sut.GetRef() - - // expect - if actual != expected { - t.Errorf("must equal. wont %#v, but got %#v", expected, actual) - } -} - -func TestTargetSource_GetSHA(t *testing.T) { - // given - expected := plumbing.NewHash("hello world.") - - // and - sut := github.TargetSource{SHA: expected} - - // when - actual := sut.GetSHA() - - // expect - if actual != expected { - t.Errorf("must equal. wont %#v, but got %#v", expected, actual) - } -} diff --git a/application/service/logstore/export_test.go b/application/service/logstore/export_test.go deleted file mode 100644 index 73d07c15..00000000 --- a/application/service/logstore/export_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package logstore - -import "github.com/duck8823/duci/infrastructure/store" - -type StoreServiceImpl = storeServiceImpl - -func (s *storeServiceImpl) SetDB(db store.Store) (reset func()) { - tmp := s.db - s.db = db - return func() { - s.db = tmp - } -} diff --git a/application/service/logstore/mock_logstore/store.go b/application/service/logstore/mock_logstore/store.go deleted file mode 100644 index 75f89edd..00000000 --- a/application/service/logstore/mock_logstore/store.go +++ /dev/null @@ -1,96 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: application/service/logstore/store.go - -// Package mock_logstore is a generated GoMock package. -package mock_logstore - -import ( - model "github.com/duck8823/duci/data/model" - gomock "github.com/golang/mock/gomock" - uuid "github.com/google/uuid" - reflect "reflect" -) - -// MockService is a mock of Service interface -type MockService struct { - ctrl *gomock.Controller - recorder *MockServiceMockRecorder -} - -// MockServiceMockRecorder is the mock recorder for MockService -type MockServiceMockRecorder struct { - mock *MockService -} - -// NewMockService creates a new mock instance -func NewMockService(ctrl *gomock.Controller) *MockService { - mock := &MockService{ctrl: ctrl} - mock.recorder = &MockServiceMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockService) EXPECT() *MockServiceMockRecorder { - return m.recorder -} - -// Get mocks base method -func (m *MockService) Get(uuid uuid.UUID) (*model.Job, error) { - ret := m.ctrl.Call(m, "Get", uuid) - ret0, _ := ret[0].(*model.Job) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get -func (mr *MockServiceMockRecorder) Get(uuid interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockService)(nil).Get), uuid) -} - -// Append mocks base method -func (m *MockService) Append(uuid uuid.UUID, message model.Message) error { - ret := m.ctrl.Call(m, "Append", uuid, message) - ret0, _ := ret[0].(error) - return ret0 -} - -// Append indicates an expected call of Append -func (mr *MockServiceMockRecorder) Append(uuid, message interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Append", reflect.TypeOf((*MockService)(nil).Append), uuid, message) -} - -// Start mocks base method -func (m *MockService) Start(uuid uuid.UUID) error { - ret := m.ctrl.Call(m, "Start", uuid) - ret0, _ := ret[0].(error) - return ret0 -} - -// Start indicates an expected call of Start -func (mr *MockServiceMockRecorder) Start(uuid interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*MockService)(nil).Start), uuid) -} - -// Finish mocks base method -func (m *MockService) Finish(uuid uuid.UUID) error { - ret := m.ctrl.Call(m, "Finish", uuid) - ret0, _ := ret[0].(error) - return ret0 -} - -// Finish indicates an expected call of Finish -func (mr *MockServiceMockRecorder) Finish(uuid interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Finish", reflect.TypeOf((*MockService)(nil).Finish), uuid) -} - -// Close mocks base method -func (m *MockService) Close() error { - ret := m.ctrl.Call(m, "Close") - ret0, _ := ret[0].(error) - return ret0 -} - -// Close indicates an expected call of Close -func (mr *MockServiceMockRecorder) Close() *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockService)(nil).Close)) -} diff --git a/application/service/logstore/store.go b/application/service/logstore/store.go deleted file mode 100644 index 59aeb5e3..00000000 --- a/application/service/logstore/store.go +++ /dev/null @@ -1,127 +0,0 @@ -package logstore - -import ( - "bytes" - "encoding/json" - "github.com/duck8823/duci/application" - "github.com/duck8823/duci/data/model" - "github.com/duck8823/duci/infrastructure/store" - "github.com/google/uuid" - "github.com/pkg/errors" - "github.com/syndtr/goleveldb/leveldb" -) - -// Level describes a log level. -type Level = string - -// Service is a interface describe store for log. -type Service interface { - Get(uuid uuid.UUID) (*model.Job, error) - Append(uuid uuid.UUID, message model.Message) error - Start(uuid uuid.UUID) error - Finish(uuid uuid.UUID) error - Close() error -} - -type storeServiceImpl struct { - db store.Store -} - -// New returns a implementation of Service interface. -func New() (Service, error) { - database, err := leveldb.OpenFile(application.Config.Server.DatabasePath, nil) - if err != nil { - return nil, errors.WithStack(err) - } - return &storeServiceImpl{database}, nil -} - -// Append a message to store. -func (s *storeServiceImpl) Append(uuid uuid.UUID, message model.Message) error { - job, err := s.findOrInitialize(uuid) - if err != nil { - return errors.WithStack(err) - } - - job.Stream = append(job.Stream, message) - - data, err := json.Marshal(job) - if err != nil { - return errors.WithStack(err) - } - if err := s.db.Put([]byte(uuid.String()), data, nil); err != nil { - return errors.WithStack(err) - } - return nil -} - -func (s *storeServiceImpl) findOrInitialize(uuid uuid.UUID) (*model.Job, error) { - job := &model.Job{} - - data, err := s.db.Get([]byte(uuid.String()), nil) - if err == store.NotFoundError { - return job, nil - } - if err != nil { - return nil, errors.WithStack(err) - } - if err := json.NewDecoder(bytes.NewReader(data)).Decode(job); err != nil { - return nil, errors.WithStack(err) - } - return job, nil -} - -// Get a job from store. -func (s *storeServiceImpl) Get(uuid uuid.UUID) (*model.Job, error) { - data, err := s.db.Get([]byte(uuid.String()), nil) - if err != nil { - return nil, errors.WithStack(err) - } - - job := &model.Job{} - if err := json.NewDecoder(bytes.NewReader(data)).Decode(job); err != nil { - return nil, errors.WithStack(err) - } - return job, nil -} - -// Start stores initialized job to store. -func (s *storeServiceImpl) Start(uuid uuid.UUID) error { - started, _ := json.Marshal(&model.Job{Finished: false}) - if err := s.db.Put([]byte(uuid.String()), started, nil); err != nil { - return errors.WithStack(err) - } - return nil -} - -// Finish stores with finished flag. -func (s *storeServiceImpl) Finish(uuid uuid.UUID) error { - data, err := s.db.Get([]byte(uuid.String()), nil) - if err != nil { - return errors.WithStack(err) - } - - job := &model.Job{} - if err := json.NewDecoder(bytes.NewReader(data)).Decode(job); err != nil { - return errors.WithStack(err) - } - - job.Finished = true - - finished, err := json.Marshal(job) - if err != nil { - return errors.WithStack(err) - } - if err := s.db.Put([]byte(uuid.String()), finished, nil); err != nil { - return errors.WithStack(err) - } - return nil -} - -// Close a data store. -func (s *storeServiceImpl) Close() error { - if err := s.db.Close(); err != nil { - return errors.WithStack(err) - } - return nil -} diff --git a/application/service/logstore/store_test.go b/application/service/logstore/store_test.go deleted file mode 100644 index b944d3b1..00000000 --- a/application/service/logstore/store_test.go +++ /dev/null @@ -1,566 +0,0 @@ -package logstore_test - -import ( - "bytes" - "encoding/json" - "errors" - "github.com/duck8823/duci/application/service/logstore" - "github.com/duck8823/duci/data/model" - "github.com/duck8823/duci/infrastructure/store" - "github.com/duck8823/duci/infrastructure/store/mock_store" - "github.com/golang/mock/gomock" - "github.com/google/go-cmp/cmp" - "github.com/google/uuid" - "testing" - "time" -) - -func TestNewStoreService(t *testing.T) { - // when - actual, err := logstore.New() - - // then - if _, ok := actual.(*logstore.StoreServiceImpl); !ok { - t.Error("must be a Service, but not.") - } - - if err != nil { - t.Errorf("error must not occur, but got %+v", err) - } -} - -func TestStoreServiceImpl_Append(t *testing.T) { - // setup - ctrl := gomock.NewController(t) - mockStore := mock_store.NewMockStore(ctrl) - - service := &logstore.StoreServiceImpl{} - reset := service.SetDB(mockStore) - defer reset() - - t.Run("when store returns correct data", func(t *testing.T) { - // given - jst, err := time.LoadLocation("Asia/Tokyo") - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - - date1 := time.Date(2020, time.April, 1, 12, 3, 00, 00, jst) - date2 := time.Date(1987, time.March, 27, 19, 19, 00, 00, jst) - job := &model.Job{ - Finished: false, - Stream: []model.Message{{Time: date1, Text: "Hello World."}}, - } - storedData, err := json.Marshal(job) - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - - // and - id, err := uuid.NewRandom() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - storedID := []byte(id.String()) - - // and - expected := &model.Job{ - Finished: false, - Stream: []model.Message{ - {Time: date1, Text: "Hello World."}, - {Time: date2, Text: "Hello Testing."}, - }, - } - expectedData, err := json.Marshal(expected) - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - - // and - mockStore.EXPECT(). - Get(gomock.Eq(storedID), gomock.Nil()). - Times(1). - Return(storedData, nil) - mockStore.EXPECT(). - Put(gomock.Eq(storedID), gomock.Eq(expectedData), gomock.Nil()). - Times(1). - Return(nil) - mockStore.EXPECT(). - Put(gomock.Eq(storedID), gomock.Not(expectedData), gomock.Nil()). - Do(func(_ interface{}, data []byte, _ interface{}) { - t.Logf("wont: %s", string(expectedData)) - t.Logf("got: %s", string(data)) - }). - Return(errors.New("must not call this")) - - // expect - if err := service.Append(id, model.Message{Time: date2, Text: "Hello Testing."}); err != nil { - t.Errorf("error must not occur, but got %+v", err) - } - }) - - t.Run("when value not found", func(t *testing.T) { - // given - id, err := uuid.NewRandom() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - storedID := []byte(id.String()) - - // and - expected := &model.Job{ - Finished: false, - Stream: []model.Message{ - {Time: time.Now(), Text: "Hello Testing."}, - }, - } - expectedData, err := json.Marshal(expected) - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - - // and - mockStore.EXPECT(). - Get(gomock.Eq(storedID), gomock.Nil()). - Times(1). - Return(nil, store.NotFoundError) - mockStore.EXPECT(). - Put(gomock.Eq(storedID), gomock.Eq(expectedData), gomock.Nil()). - Times(1). - Return(nil) - mockStore.EXPECT(). - Put(gomock.Eq(storedID), gomock.Not(expectedData), gomock.Nil()). - Do(func(_ interface{}, data []byte, _ interface{}) { - t.Logf("wont: %s", string(expectedData)) - t.Logf("got: %s", string(data)) - }). - Return(errors.New("must not call this")) - - // expect - if err := service.Append(id, expected.Stream[0]); err != nil { - t.Errorf("error must not occur, but got %+v", err) - } - }) - - t.Run("when store.Get returns error", func(t *testing.T) { - // given - id, err := uuid.NewRandom() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - storedID := []byte(id.String()) - - // and - mockStore.EXPECT(). - Get(gomock.Eq(storedID), gomock.Nil()). - Times(1). - Return(nil, errors.New("hello testing")) - - // expect - if err := service.Append(id, model.Message{Text: "Hello Testing."}); err == nil { - t.Error("error must occur, but got nil") - } - }) - - t.Run("when store.Get returns invalid data", func(t *testing.T) { - // given - storedData := []byte("invalid data") - - // and - id, err := uuid.NewRandom() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - storedID := []byte(id.String()) - - // and - mockStore.EXPECT(). - Get(gomock.Eq(storedID), gomock.Nil()). - Times(1). - Return(storedData, nil) - mockStore.EXPECT(). - Put(gomock.Eq(storedID), gomock.Any(), gomock.Nil()). - Times(1). - Do(func(_, _, _ interface{}) { - t.Fatalf("must not call this.") - }) - - // expect - if err := service.Append(id, model.Message{Text: "Hello Testing."}); err == nil { - t.Error("error must occur, but got nil") - } - }) - - t.Run("when store.Put returns invalid data", func(t *testing.T) { - // given - job := &model.Job{ - Finished: false, - Stream: []model.Message{{Time: time.Now(), Text: "Hello World."}}, - } - storedData, err := json.Marshal(job) - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - - // and - id, err := uuid.NewRandom() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - storedID := []byte(id.String()) - - // and - mockStore.EXPECT(). - Get(gomock.Eq(storedID), gomock.Nil()). - Times(1). - Return(storedData, nil) - mockStore.EXPECT(). - Put(gomock.Eq(storedID), gomock.Any(), gomock.Nil()). - Times(1). - Return(errors.New("hello error")) - - // expect - if err := service.Append(id, model.Message{Text: "Hello Testing."}); err == nil { - t.Error("error must occur, but got nil") - } - }) -} - -func TestStoreServiceImpl_Get(t *testing.T) { - // setup - ctrl := gomock.NewController(t) - mockStore := mock_store.NewMockStore(ctrl) - - service := &logstore.StoreServiceImpl{} - reset := service.SetDB(mockStore) - defer reset() - - t.Run("with error", func(t *testing.T) { - // setup - id, err := uuid.NewRandom() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - storedID := []byte(id.String()) - - // given - mockStore.EXPECT(). - Get(gomock.Eq(storedID), gomock.Nil()). - Times(1). - Return(nil, errors.New("hello testing")) - - // when - actual, err := service.Get(id) - - // then - if actual != nil { - t.Errorf("job must be nil, but got %+v", actual) - } - - if err == nil { - t.Error("error must occur, but got nil") - } - }) - - t.Run("with invalid data", func(t *testing.T) { - // given - storedData := []byte("invalid data") - - // and - id, err := uuid.NewRandom() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - storedID := []byte(id.String()) - - // and - mockStore.EXPECT(). - Get(gomock.Eq(storedID), gomock.Nil()). - Times(1). - Return(storedData, nil) - - // when - actual, err := service.Get(id) - - // then - if err == nil { - t.Error("error must occur, but got nil") - } - - if actual != nil { - t.Errorf("job must be nil, but got %+v", err) - } - }) - - t.Run("with stored data", func(t *testing.T) { - // given - expected := &model.Job{ - Finished: false, - Stream: []model.Message{{Time: time.Now(), Text: "Hello World."}}, - } - storedData, err := json.Marshal(expected) - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - - // and - id, err := uuid.NewRandom() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - storedID := []byte(id.String()) - - // and - mockStore.EXPECT(). - Get(gomock.Eq(storedID), gomock.Nil()). - Times(1). - Return(storedData, nil) - - // when - actual, err := service.Get(id) - - // then - if err != nil { - t.Errorf("error must not occur, but got %+v", err) - } - - if !cmp.Equal(actual.Stream[0].Time, expected.Stream[0].Time) { - t.Errorf("wont %+v, but got %+v", expected, actual) - } - }) -} - -func TestStoreServiceImpl_Start(t *testing.T) { - // setup - ctrl := gomock.NewController(t) - mockStore := mock_store.NewMockStore(ctrl) - - service := &logstore.StoreServiceImpl{} - reset := service.SetDB(mockStore) - defer reset() - - t.Run("when put success", func(t *testing.T) { - // given - id, err := uuid.NewRandom() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - storedID := []byte(id.String()) - - // and - expected, err := json.Marshal(&model.Job{Finished: false}) - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - - // and - mockStore.EXPECT(). - Put(gomock.Eq(storedID), gomock.Eq(expected), gomock.Nil()). - Times(1). - Return(nil) - - // when - err = service.Start(id) - - // then - if err != nil { - t.Errorf("error must not occur, but got %+v", err) - } - }) - - t.Run("when put fail", func(t *testing.T) { - // given - id, err := uuid.NewRandom() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - - // and - mockStore.EXPECT(). - Put(gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - Return(errors.New("test error")) - - // when - err = service.Start(id) - - // then - if err == nil { - t.Error("error must occur, but got nil") - } - }) -} - -func TestStoreServiceImpl_Finish(t *testing.T) { - // setup - ctrl := gomock.NewController(t) - mockStore := mock_store.NewMockStore(ctrl) - - service := &logstore.StoreServiceImpl{} - reset := service.SetDB(mockStore) - defer reset() - - t.Run("with error", func(t *testing.T) { - // setup - id, err := uuid.NewRandom() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - storedID := []byte(id.String()) - - // given - mockStore.EXPECT(). - Get(gomock.Eq(storedID), gomock.Nil()). - Times(1). - Return(nil, errors.New("hello testing")) - - // expect - if err := service.Finish(id); err == nil { - t.Error("error must occur, but got nil") - } - }) - - t.Run("with invalid data", func(t *testing.T) { - // given - storedData := []byte("invalid data") - - // and - id, err := uuid.NewRandom() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - storedID := []byte(id.String()) - - // and - mockStore.EXPECT(). - Get(gomock.Eq(storedID), gomock.Nil()). - Times(1). - Return(storedData, nil) - - // expect - if err := service.Finish(id); err == nil { - t.Error("error must occur, but got nil") - } - }) - - t.Run("with stored data", func(t *testing.T) { - // given - given := &model.Job{ - Finished: false, - Stream: []model.Message{{Time: time.Now(), Text: "Hello World."}}, - } - storedData, err := json.Marshal(given) - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - - // and - expected := &model.Job{ - Finished: true, - Stream: given.Stream, - } - expectedData, err := json.Marshal(expected) - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - - // and - id, err := uuid.NewRandom() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - storedID := []byte(id.String()) - - // and - mockStore.EXPECT(). - Get(gomock.Eq(storedID), gomock.Nil()). - Times(1). - Return(storedData, nil) - mockStore.EXPECT(). - Put(gomock.Eq(storedID), gomock.Eq(expectedData), gomock.Nil()). - Times(1) - mockStore.EXPECT(). - Put(gomock.Eq(storedID), gomock.Not(expectedData), gomock.Nil()). - Do(func(_, arg, _ interface{}) { - actual := &model.Job{} - json.NewDecoder(bytes.NewReader(arg.([]byte))).Decode(actual) - t.Fatalf("invalid argument: wont %+v, but got %+v", expected, actual) - }) - - // when - err = service.Finish(id) - - // and - if err != nil { - t.Errorf("error must not occur, but got %+v", err) - } - }) - - t.Run("when failed put", func(t *testing.T) { - // given - given := &model.Job{ - Finished: false, - Stream: []model.Message{{Time: time.Now(), Text: "Hello World."}}, - } - storedData, err := json.Marshal(given) - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - - // and - id, err := uuid.NewRandom() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - storedID := []byte(id.String()) - - // and - mockStore.EXPECT(). - Get(gomock.Eq(storedID), gomock.Nil()). - Times(1). - Return(storedData, nil) - mockStore.EXPECT(). - Put(gomock.Eq(storedID), gomock.Any(), gomock.Nil()). - Times(1). - Return(errors.New("hello testing")) - - // expect - if err := service.Finish(id); err == nil { - t.Error("error must occur, but got nil") - } - }) -} - -func TestStoreServiceImpl_Close(t *testing.T) { - // setup - ctrl := gomock.NewController(t) - mockStore := mock_store.NewMockStore(ctrl) - - service := &logstore.StoreServiceImpl{} - reset := service.SetDB(mockStore) - defer reset() - - t.Run("with error", func(t *testing.T) { - // given - mockStore.EXPECT(). - Close(). - Return(errors.New("hello testing")) - - // expect - if err := service.Close(); err == nil { - t.Errorf("error must not occur, but got %+v", err) - } - }) - - t.Run("without error", func(t *testing.T) { - // given - mockStore.EXPECT(). - Close(). - Return(nil) - - // expect - if err := service.Close(); err != nil { - t.Error("error must occur, but got nil") - } - }) -} diff --git a/application/service/runner/export_test.go b/application/service/runner/export_test.go deleted file mode 100644 index 84d08da7..00000000 --- a/application/service/runner/export_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package runner - -import ( - "github.com/duck8823/duci/infrastructure/docker" - "io" - "time" -) - -type MockRepo struct { - FullName string - SSHURL string - CloneURL string -} - -func (r *MockRepo) GetFullName() string { - return r.FullName -} - -func (r *MockRepo) GetSSHURL() string { - return r.SSHURL -} - -func (r *MockRepo) GetCloneURL() string { - return r.CloneURL -} - -type MockBuildLog struct { -} - -func (l *MockBuildLog) ReadLine() (*docker.LogLine, error) { - return &docker.LogLine{Timestamp: time.Now(), Message: []byte("{\"stream\":\"Hello World,\"}")}, io.EOF -} - -type MockJobLog struct { -} - -func (l *MockJobLog) ReadLine() (*docker.LogLine, error) { - return &docker.LogLine{Timestamp: time.Now(), Message: []byte("Hello World,")}, io.EOF -} diff --git a/application/service/runner/helper.go b/application/service/runner/helper.go deleted file mode 100644 index 2c47f483..00000000 --- a/application/service/runner/helper.go +++ /dev/null @@ -1,62 +0,0 @@ -package runner - -import ( - "bytes" - "github.com/duck8823/duci/application/service/docker" - "github.com/duck8823/duci/infrastructure/archive/tar" - "github.com/pkg/errors" - "gopkg.in/yaml.v2" - "io/ioutil" - "os" - "path/filepath" -) - -// createTarball creates a tar archive -func createTarball(workDir string) (*os.File, error) { - tarFilePath := filepath.Join(workDir, "duci.tar") - writeFile, err := os.OpenFile(tarFilePath, os.O_RDWR|os.O_CREATE, 0600) - if err != nil { - return nil, errors.WithStack(err) - } - defer writeFile.Close() - - if err := tar.Create(workDir, writeFile); err != nil { - return nil, errors.WithStack(err) - } - - readFile, _ := os.Open(tarFilePath) - return readFile, nil -} - -// dockerfilePath returns a path to dockerfile for duci using -func dockerfilePath(workDir string) docker.Dockerfile { - dockerfile := "./Dockerfile" - if exists(filepath.Join(workDir, ".duci/Dockerfile")) { - dockerfile = ".duci/Dockerfile" - } - return docker.Dockerfile(dockerfile) -} - -// exists indicates whether the file exists -func exists(name string) bool { - _, err := os.Stat(name) - return !os.IsNotExist(err) -} - -// runtimeOptions parses a config.yml and returns a docker runtime options -func runtimeOptions(workDir string) (docker.RuntimeOptions, error) { - var opts docker.RuntimeOptions - - if !exists(filepath.Join(workDir, ".duci/config.yml")) { - return opts, nil - } - content, err := ioutil.ReadFile(filepath.Join(workDir, ".duci/config.yml")) - if err != nil { - return opts, errors.WithStack(err) - } - content = []byte(os.ExpandEnv(string(content))) - if err := yaml.NewDecoder(bytes.NewReader(content)).Decode(&opts); err != nil { - return opts, errors.WithStack(err) - } - return opts, nil -} diff --git a/application/service/runner/mock_runner/runner.go b/application/service/runner/mock_runner/runner.go deleted file mode 100644 index 4366493c..00000000 --- a/application/service/runner/mock_runner/runner.go +++ /dev/null @@ -1,52 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: application/service/runner/runner.go - -// Package mock_runner is a generated GoMock package. -package mock_runner - -import ( - context "github.com/duck8823/duci/application/context" - github "github.com/duck8823/duci/application/service/github" - gomock "github.com/golang/mock/gomock" - reflect "reflect" -) - -// MockRunner is a mock of Runner interface -type MockRunner struct { - ctrl *gomock.Controller - recorder *MockRunnerMockRecorder -} - -// MockRunnerMockRecorder is the mock recorder for MockRunner -type MockRunnerMockRecorder struct { - mock *MockRunner -} - -// NewMockRunner creates a new mock instance -func NewMockRunner(ctrl *gomock.Controller) *MockRunner { - mock := &MockRunner{ctrl: ctrl} - mock.recorder = &MockRunnerMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockRunner) EXPECT() *MockRunnerMockRecorder { - return m.recorder -} - -// Run mocks base method -func (m *MockRunner) Run(ctx context.Context, src *github.TargetSource, command ...string) error { - varargs := []interface{}{ctx, src} - for _, a := range command { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "Run", varargs...) - ret0, _ := ret[0].(error) - return ret0 -} - -// Run indicates an expected call of Run -func (mr *MockRunnerMockRecorder) Run(ctx, src interface{}, command ...interface{}) *gomock.Call { - varargs := append([]interface{}{ctx, src}, command...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Run", reflect.TypeOf((*MockRunner)(nil).Run), varargs...) -} diff --git a/application/service/runner/runner.go b/application/service/runner/runner.go deleted file mode 100644 index ecc0919f..00000000 --- a/application/service/runner/runner.go +++ /dev/null @@ -1,188 +0,0 @@ -package runner - -import ( - "bytes" - "github.com/duck8823/duci/application" - "github.com/duck8823/duci/application/context" - "github.com/duck8823/duci/application/semaphore" - "github.com/duck8823/duci/application/service/docker" - "github.com/duck8823/duci/application/service/git" - "github.com/duck8823/duci/application/service/github" - "github.com/duck8823/duci/application/service/logstore" - "github.com/duck8823/duci/data/model" - "github.com/duck8823/duci/infrastructure/logger" - "github.com/labstack/gommon/random" - "github.com/pkg/errors" - "gopkg.in/yaml.v2" - "io" - "io/ioutil" - "os" - "path/filepath" -) - -// ErrFailure is a error describes task failure. -var ErrFailure = errors.New("Task Failure") - -// Runner is a interface describes task runner. -type Runner interface { - Run(ctx context.Context, src *github.TargetSource, command ...string) error -} - -// DockerRunner represents a runner implement for docker. -type DockerRunner struct { - Git git.Service - GitHub github.Service - Docker docker.Service - LogStore logstore.Service - BaseWorkDir string -} - -// Run task in docker container. -func (r *DockerRunner) Run(ctx context.Context, src *github.TargetSource, command ...string) error { - if err := r.LogStore.Start(ctx.UUID()); err != nil { - r.GitHub.CreateCommitStatus(ctx, src, github.ERROR, err.Error()) - return errors.WithStack(err) - } - - errs := make(chan error, 1) - - timeout, cancel := context.WithTimeout(ctx, application.Config.Timeout()) - defer cancel() - - go func() { - semaphore.Acquire() - errs <- r.run(timeout, src, command...) - semaphore.Release() - }() - - select { - case <-timeout.Done(): - r.timeout(timeout, src) - return timeout.Err() - case err := <-errs: - r.finish(ctx, src, err) - return err - } -} - -func (r *DockerRunner) run(ctx context.Context, src *github.TargetSource, command ...string) error { - workDir := filepath.Join(r.BaseWorkDir, random.String(36, random.Alphanumeric)) - - if err := r.Git.Clone(ctx, workDir, src); err != nil { - return errors.WithStack(err) - } - - r.GitHub.CreateCommitStatus(ctx, src, github.PENDING, "started job") - - if err := r.dockerBuild(ctx, workDir, src.Repo); err != nil { - return errors.WithStack(err) - } - - conID, err := r.dockerRun(ctx, workDir, src.Repo, command) - if err != nil { - return errors.WithStack(err) - } - - code, err := r.Docker.ExitCode(ctx, conID) - if err != nil { - return errors.WithStack(err) - } - if err := r.Docker.Rm(ctx, conID); err != nil { - return errors.WithStack(err) - } - if code != 0 { - return ErrFailure - } - - return err -} - -func (r *DockerRunner) dockerBuild(ctx context.Context, dir string, repo github.Repository) error { - tarball, err := createTarball(dir) - if err != nil { - return errors.WithStack(err) - } - defer tarball.Close() - - tag := docker.Tag(repo.GetFullName()) - buildLog, err := r.Docker.Build(ctx, tarball, tag, dockerfilePath(dir)) - if err != nil { - return errors.WithStack(err) - } - if err := r.logAppend(ctx, buildLog); err != nil { - return errors.WithStack(err) - } - return nil -} - -func (r *DockerRunner) dockerRun(ctx context.Context, dir string, repo github.Repository, cmd docker.Command) (docker.ContainerID, error) { - opts, err := runtimeOpts(dir) - if err != nil { - return "", errors.WithStack(err) - } - - tag := docker.Tag(repo.GetFullName()) - conID, runLog, err := r.Docker.Run(ctx, opts, tag, cmd) - if err != nil { - return conID, errors.WithStack(err) - } - if err := r.logAppend(ctx, runLog); err != nil { - return conID, errors.WithStack(err) - } - return conID, nil -} - -func runtimeOpts(workDir string) (docker.RuntimeOptions, error) { - var opts docker.RuntimeOptions - - if !exists(filepath.Join(workDir, ".duci/config.yml")) { - return opts, nil - } - content, err := ioutil.ReadFile(filepath.Join(workDir, ".duci/config.yml")) - if err != nil { - return opts, errors.WithStack(err) - } - content = []byte(os.ExpandEnv(string(content))) - if err := yaml.NewDecoder(bytes.NewReader(content)).Decode(&opts); err != nil { - return opts, errors.WithStack(err) - } - return opts, nil -} - -func (r *DockerRunner) logAppend(ctx context.Context, log docker.Log) error { - for { - line, err := log.ReadLine() - if err != nil && err != io.EOF { - logger.Debugf(ctx.UUID(), "skip read line with error: %s", err.Error()) - continue - } - logger.Info(ctx.UUID(), string(line.Message)) - if err := r.LogStore.Append(ctx.UUID(), model.Message{Time: line.Timestamp, Text: string(line.Message)}); err != nil { - return errors.WithStack(err) - } - if err == io.EOF { - return nil - } - } -} - -func (r *DockerRunner) timeout(ctx context.Context, src *github.TargetSource) { - if ctx.Err() != nil { - logger.Errorf(ctx.UUID(), "%+v", ctx.Err()) - r.GitHub.CreateCommitStatus(ctx, src, github.ERROR, ctx.Err().Error()) - } - r.LogStore.Finish(ctx.UUID()) -} - -func (r *DockerRunner) finish(ctx context.Context, src *github.TargetSource, err error) { - if err == ErrFailure { - logger.Error(ctx.UUID(), err.Error()) - r.GitHub.CreateCommitStatus(ctx, src, github.FAILURE, "failure job") - } else if err != nil { - logger.Errorf(ctx.UUID(), "%+v", err) - r.GitHub.CreateCommitStatus(ctx, src, github.ERROR, err.Error()) - } else { - r.GitHub.CreateCommitStatus(ctx, src, github.SUCCESS, "success") - } - r.LogStore.Finish(ctx.UUID()) -} diff --git a/application/service/runner/runner_test.go b/application/service/runner/runner_test.go deleted file mode 100644 index 0ee760bc..00000000 --- a/application/service/runner/runner_test.go +++ /dev/null @@ -1,850 +0,0 @@ -package runner_test - -import ( - "github.com/duck8823/duci/application" - "github.com/duck8823/duci/application/context" - "github.com/duck8823/duci/application/service/docker" - "github.com/duck8823/duci/application/service/docker/mock_docker" - "github.com/duck8823/duci/application/service/git/mock_git" - "github.com/duck8823/duci/application/service/github" - "github.com/duck8823/duci/application/service/github/mock_github" - "github.com/duck8823/duci/application/service/logstore/mock_logstore" - "github.com/duck8823/duci/application/service/runner" - "github.com/golang/mock/gomock" - "github.com/google/uuid" - "github.com/pkg/errors" - "gopkg.in/src-d/go-git.v4/plumbing" - "net/url" - "os" - "path/filepath" - "testing" - "time" -) - -func TestRunnerImpl_Run_Normal(t *testing.T) { - // setup - ctrl := gomock.NewController(t) - - t.Run("with correct return values", func(t *testing.T) { - t.Run("when Dockerfile in project root", func(t *testing.T) { - // given - mockGitHub := mock_github.NewMockService(ctrl) - mockGitHub.EXPECT().CreateCommitStatus(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(2). - Return(nil) - - // and - mockGit := mock_git.NewMockService(ctrl) - mockGit.EXPECT().Clone(gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - DoAndReturn(func(_ interface{}, dir string, _ interface{}) error { - if err := os.MkdirAll(dir, 0700); err != nil { - return err - } - - dockerfile, err := os.OpenFile(filepath.Join(dir, "Dockerfile"), os.O_RDWR|os.O_CREATE, 0600) - if err != nil { - return err - } - defer dockerfile.Close() - - dockerfile.WriteString("FROM alpine\nENTRYPOINT [\"echo\"]") - - return nil - }) - - // and - mockDocker := mock_docker.NewMockService(ctrl) - mockDocker.EXPECT(). - Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Eq(docker.Dockerfile("./Dockerfile"))). - Times(1). - Return(&runner.MockBuildLog{}, nil) - mockDocker.EXPECT(). - Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Not(docker.Dockerfile("./Dockerfile"))). - Return(nil, errors.New("must not call this")) - mockDocker.EXPECT(). - Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - Return(docker.ContainerID(""), &runner.MockJobLog{}, nil) - mockDocker.EXPECT(). - ExitCode(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(docker.ExitCode(0), nil) - mockDocker.EXPECT(). - Rm(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - - // and - mockLogStore := mock_logstore.NewMockService(ctrl) - mockLogStore.EXPECT(). - Append(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - mockLogStore.EXPECT(). - Start(gomock.Any()). - AnyTimes(). - Return(nil) - mockLogStore.EXPECT(). - Finish(gomock.Any()). - AnyTimes(). - Return(nil) - - r := &runner.DockerRunner{ - BaseWorkDir: filepath.Join(os.TempDir(), "test-runner"), - Git: mockGit, - GitHub: mockGitHub, - Docker: mockDocker, - LogStore: mockLogStore, - } - - // and - repo := &runner.MockRepo{FullName: "duck8823/duci", SSHURL: "git@github.com:duck8823/duci.git"} - - // when - err := r.Run( - context.New("test/task", uuid.New(), &url.URL{}), - &github.TargetSource{Repo: repo, Ref: "master", SHA: plumbing.ZeroHash}, - "Hello World.", - ) - - // then - if err != nil { - t.Errorf("must not error. but: %+v", err) - } - }) - - t.Run("when Dockerfile in sub directory", func(t *testing.T) { - // given - mockGitHub := mock_github.NewMockService(ctrl) - mockGitHub.EXPECT().CreateCommitStatus(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(2). - Return(nil) - - // and - mockGit := mock_git.NewMockService(ctrl) - mockGit.EXPECT().Clone(gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - DoAndReturn(func(_ interface{}, dir string, _ interface{}) error { - if err := os.MkdirAll(filepath.Join(dir, ".duci"), 0700); err != nil { - return err - } - - dockerfile, err := os.OpenFile(filepath.Join(dir, ".duci/Dockerfile"), os.O_RDWR|os.O_CREATE, 0600) - if err != nil { - return err - } - defer dockerfile.Close() - - dockerfile.WriteString("FROM alpine\nENTRYPOINT [\"echo\"]") - - return nil - }) - - // and - mockDocker := mock_docker.NewMockService(ctrl) - mockDocker.EXPECT(). - Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Eq(docker.Dockerfile(".duci/Dockerfile"))). - Return(&runner.MockBuildLog{}, nil) - mockDocker.EXPECT(). - Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Not(docker.Dockerfile(".duci/Dockerfile"))). - Return(nil, errors.New("must not call this")) - mockDocker.EXPECT(). - Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - Return(docker.ContainerID(""), &runner.MockJobLog{}, nil) - mockDocker.EXPECT(). - ExitCode(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(docker.ExitCode(0), nil) - mockDocker.EXPECT(). - Rm(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - - // and - mockLogStore := mock_logstore.NewMockService(ctrl) - mockLogStore.EXPECT(). - Append(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - mockLogStore.EXPECT(). - Start(gomock.Any()). - AnyTimes(). - Return(nil) - mockLogStore.EXPECT(). - Finish(gomock.Any()). - AnyTimes(). - Return(nil) - - r := &runner.DockerRunner{ - BaseWorkDir: filepath.Join(os.TempDir(), "test-runner"), - Git: mockGit, - GitHub: mockGitHub, - Docker: mockDocker, - LogStore: mockLogStore, - } - - // and - repo := &runner.MockRepo{FullName: "duck8823/duci", SSHURL: "git@github.com:duck8823/duci.git"} - - // when - err := r.Run( - context.New("test/task", uuid.New(), &url.URL{}), - &github.TargetSource{Repo: repo, Ref: "master", SHA: plumbing.ZeroHash}, - "Hello World.", - ) - - // then - if err != nil { - t.Errorf("must not error. but: %+v", err) - } - }) - }) - - t.Run("with config file", func(t *testing.T) { - // given - mockGitHub := mock_github.NewMockService(ctrl) - mockGitHub.EXPECT().CreateCommitStatus(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(2). - Return(nil) - - // and - mockGit := mock_git.NewMockService(ctrl) - mockGit.EXPECT().Clone(gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - DoAndReturn(func(_ interface{}, dir string, _ interface{}) error { - if err := os.MkdirAll(filepath.Join(dir, ".duci"), 0700); err != nil { - return err - } - - dockerfile, err := os.OpenFile(filepath.Join(dir, ".duci/config.yml"), os.O_RDWR|os.O_CREATE, 0600) - if err != nil { - return err - } - defer dockerfile.Close() - - dockerfile.WriteString("---\nvolumes:\n - /hello:/hello") - - return nil - }) - - // and - mockDocker := mock_docker.NewMockService(ctrl) - mockDocker.EXPECT(). - Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Return(&runner.MockBuildLog{}, nil) - mockDocker.EXPECT(). - Run(gomock.Any(), gomock.Eq(docker.RuntimeOptions{Volumes: []string{"/hello:/hello"}}), gomock.Any(), gomock.Any()). - Times(1). - Return(docker.ContainerID(""), &runner.MockJobLog{}, nil) - mockDocker.EXPECT(). - Run(gomock.Any(), gomock.Not(docker.RuntimeOptions{Volumes: []string{"/hello:/hello"}}), gomock.Any(), gomock.Any()). - Return(docker.ContainerID(""), nil, errors.New("must not call this")) - mockDocker.EXPECT(). - ExitCode(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(docker.ExitCode(0), nil) - mockDocker.EXPECT(). - Rm(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - - // and - mockLogStore := mock_logstore.NewMockService(ctrl) - mockLogStore.EXPECT(). - Append(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - mockLogStore.EXPECT(). - Start(gomock.Any()). - AnyTimes(). - Return(nil) - mockLogStore.EXPECT(). - Finish(gomock.Any()). - AnyTimes(). - Return(nil) - - r := &runner.DockerRunner{ - BaseWorkDir: filepath.Join(os.TempDir(), "test-runner"), - Git: mockGit, - GitHub: mockGitHub, - Docker: mockDocker, - LogStore: mockLogStore, - } - - // and - repo := &runner.MockRepo{FullName: "duck8823/duci", SSHURL: "git@github.com:duck8823/duci.git"} - - // when - err := r.Run( - context.New("test/task", uuid.New(), &url.URL{}), - &github.TargetSource{Repo: repo, Ref: "master", SHA: plumbing.ZeroHash}, - "Hello World.", - ) - - // then - if err != nil { - t.Errorf("must not error. but: %+v", err) - } - }) -} - -func TestRunnerImpl_Run_NonNormal(t *testing.T) { - // setup - ctrl := gomock.NewController(t) - - t.Run("when failed to git clone", func(t *testing.T) { - // given - mockGitHub := mock_github.NewMockService(ctrl) - mockGitHub.EXPECT().CreateCommitStatus(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(2). - Return(nil) - - // and - mockGit := mock_git.NewMockService(ctrl) - mockGit.EXPECT().Clone(gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - Return(errors.New("error")) - - // and - mockDocker := mock_docker.NewMockService(ctrl) - mockDocker.EXPECT(). - Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(0) - mockDocker.EXPECT(). - Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(0) - mockDocker.EXPECT(). - ExitCode(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(docker.ExitCode(0), nil) - mockDocker.EXPECT(). - Rm(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - - // and - mockLogStore := mock_logstore.NewMockService(ctrl) - mockLogStore.EXPECT(). - Append(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - mockLogStore.EXPECT(). - Start(gomock.Any()). - AnyTimes(). - Return(nil) - mockLogStore.EXPECT(). - Finish(gomock.Any()). - AnyTimes(). - Return(nil) - - r := &runner.DockerRunner{ - BaseWorkDir: filepath.Join(os.TempDir(), "test-runner"), - Git: mockGit, - GitHub: mockGitHub, - Docker: mockDocker, - LogStore: mockLogStore, - } - - // and - repo := &runner.MockRepo{FullName: "duck8823/duci", SSHURL: "git@github.com:duck8823/duci.git"} - - // when - err := r.Run( - context.New("test/task", uuid.New(), &url.URL{}), - &github.TargetSource{Repo: repo, Ref: "master", SHA: plumbing.ZeroHash}, - "Hello World.", - ) - - // then - if err == nil { - t.Error("must occur error") - } - }) - - t.Run("when failed store#$tart", func(t *testing.T) { - // given - mockGitHub := mock_github.NewMockService(ctrl) - mockGitHub.EXPECT().CreateCommitStatus(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(2). - Return(nil) - - // and - mockLogStore := mock_logstore.NewMockService(ctrl) - mockLogStore.EXPECT(). - Start(gomock.Any()). - AnyTimes(). - Return(errors.New("test error")) - - r := &runner.DockerRunner{ - BaseWorkDir: filepath.Join(os.TempDir(), "test-runner"), - GitHub: mockGitHub, - LogStore: mockLogStore, - } - - // and - repo := &runner.MockRepo{FullName: "duck8823/duci", SSHURL: "git@github.com:duck8823/duci.git"} - - // when - err := r.Run( - context.New("test/task", uuid.New(), &url.URL{}), - &github.TargetSource{Repo: repo, Ref: "master", SHA: plumbing.ZeroHash}, - "Hello World.", - ) - - // then - if err == nil { - t.Error("must occur error") - } - }) - - t.Run("when workdir not exists", func(t *testing.T) { - // given - mockGitHub := mock_github.NewMockService(ctrl) - mockGitHub.EXPECT().CreateCommitStatus(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(2). - Return(nil) - - // and - mockGit := mock_git.NewMockService(ctrl) - mockGit.EXPECT().Clone(gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - Return(nil) - - // and - mockDocker := mock_docker.NewMockService(ctrl) - mockDocker.EXPECT(). - Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(0) - mockDocker.EXPECT(). - Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(0) - mockDocker.EXPECT(). - ExitCode(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(docker.ExitCode(0), nil) - mockDocker.EXPECT(). - Rm(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - - // and - mockLogStore := mock_logstore.NewMockService(ctrl) - mockLogStore.EXPECT(). - Append(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - mockLogStore.EXPECT(). - Start(gomock.Any()). - AnyTimes(). - Return(nil) - mockLogStore.EXPECT(). - Finish(gomock.Any()). - AnyTimes(). - Return(nil) - - r := &runner.DockerRunner{ - BaseWorkDir: "/path/to/not/exists/dir", - Git: mockGit, - GitHub: mockGitHub, - Docker: mockDocker, - LogStore: mockLogStore, - } - - // and - repo := &runner.MockRepo{FullName: "duck8823/duci", SSHURL: "git@github.com:duck8823/duci.git"} - - // when - err := r.Run( - context.New("test/task", uuid.New(), &url.URL{}), - &github.TargetSource{Repo: repo, Ref: "master", SHA: plumbing.ZeroHash}, - "Hello World.", - ) - - // then - if err == nil { - t.Error("must occur error") - } - }) - - t.Run("when docker build failure", func(t *testing.T) { - // given - mockGitHub := mock_github.NewMockService(ctrl) - mockGitHub.EXPECT().CreateCommitStatus(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(2). - Return(nil) - - // and - mockGit := mock_git.NewMockService(ctrl) - mockGit.EXPECT().Clone(gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - Return(nil) - - // and - mockDocker := mock_docker.NewMockService(ctrl) - mockDocker.EXPECT(). - Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - Return(nil, errors.New("test")) - mockDocker.EXPECT(). - Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(0) - mockDocker.EXPECT(). - ExitCode(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(docker.ExitCode(0), nil) - mockDocker.EXPECT(). - Rm(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - - // and - mockLogStore := mock_logstore.NewMockService(ctrl) - mockLogStore.EXPECT(). - Append(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - mockLogStore.EXPECT(). - Start(gomock.Any()). - AnyTimes(). - Return(nil) - mockLogStore.EXPECT(). - Finish(gomock.Any()). - AnyTimes(). - Return(nil) - - r := &runner.DockerRunner{ - BaseWorkDir: filepath.Join(os.TempDir(), "test-runner"), - Git: mockGit, - GitHub: mockGitHub, - Docker: mockDocker, - LogStore: mockLogStore, - } - - // and - repo := &runner.MockRepo{FullName: "duck8823/duci", SSHURL: "git@github.com:duck8823/duci.git"} - - // when - err := r.Run( - context.New("test/task", uuid.New(), &url.URL{}), - &github.TargetSource{Repo: repo, Ref: "master", SHA: plumbing.ZeroHash}, - "Hello World.", - ) - - // then - if err == nil { - t.Error("must occur error") - } - }) - - t.Run("when docker run error", func(t *testing.T) { - // given - mockGitHub := mock_github.NewMockService(ctrl) - mockGitHub.EXPECT().CreateCommitStatus(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(2). - Return(nil) - - // and - mockGit := mock_git.NewMockService(ctrl) - mockGit.EXPECT().Clone(gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - Return(nil) - - // and - mockDocker := mock_docker.NewMockService(ctrl) - mockDocker.EXPECT(). - Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - Return(&runner.MockBuildLog{}, nil) - mockDocker.EXPECT(). - Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - Return(docker.ContainerID(""), nil, errors.New("test")) - mockDocker.EXPECT(). - ExitCode(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(docker.ExitCode(0), nil) - mockDocker.EXPECT(). - Rm(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - - // and - mockLogStore := mock_logstore.NewMockService(ctrl) - mockLogStore.EXPECT(). - Append(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - mockLogStore.EXPECT(). - Start(gomock.Any()). - AnyTimes(). - Return(nil) - mockLogStore.EXPECT(). - Finish(gomock.Any()). - AnyTimes(). - Return(nil) - - r := &runner.DockerRunner{ - BaseWorkDir: filepath.Join(os.TempDir(), "test-runner"), - Git: mockGit, - GitHub: mockGitHub, - Docker: mockDocker, - LogStore: mockLogStore, - } - - // and - repo := &runner.MockRepo{FullName: "duck8823/duci", SSHURL: "git@github.com:duck8823/duci.git"} - - // when - err := r.Run( - context.New("test/task", uuid.New(), &url.URL{}), - &github.TargetSource{Repo: repo, Ref: "master", SHA: plumbing.ZeroHash}, - "Hello World.", - ) - - // then - if err == nil { - t.Error("must occur error") - } - }) - - t.Run("when fail to remove container", func(t *testing.T) { - // given - expected := errors.New("test") - - // and - mockGitHub := mock_github.NewMockService(ctrl) - mockGitHub.EXPECT().CreateCommitStatus(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(2). - Return(nil) - - // and - mockGit := mock_git.NewMockService(ctrl) - mockGit.EXPECT().Clone(gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - DoAndReturn(cloneSuccess) - - // and - mockDocker := mock_docker.NewMockService(ctrl) - mockDocker.EXPECT(). - Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Return(&runner.MockBuildLog{}, nil) - mockDocker.EXPECT(). - Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - Return(docker.ContainerID(""), &runner.MockJobLog{}, nil) - mockDocker.EXPECT(). - ExitCode(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(docker.ExitCode(0), nil) - mockDocker.EXPECT(). - Rm(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(expected) - - // and - mockLogStore := mock_logstore.NewMockService(ctrl) - mockLogStore.EXPECT(). - Append(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - mockLogStore.EXPECT(). - Start(gomock.Any()). - AnyTimes(). - Return(nil) - mockLogStore.EXPECT(). - Finish(gomock.Any()). - AnyTimes(). - Return(nil) - - r := &runner.DockerRunner{ - BaseWorkDir: filepath.Join(os.TempDir(), "test-runner"), - Git: mockGit, - GitHub: mockGitHub, - Docker: mockDocker, - LogStore: mockLogStore, - } - - // and - repo := &runner.MockRepo{FullName: "duck8823/duci", SSHURL: "git@github.com:duck8823/duci.git"} - - // when - err := r.Run( - context.New("test/task", uuid.New(), &url.URL{}), - &github.TargetSource{Repo: repo, Ref: "master", SHA: plumbing.ZeroHash}, - "Hello World.", - ) - - // then - if err.Error() != expected.Error() { - t.Errorf("err must be %+v, but got %+v", expected, err) - } - }) - - t.Run("when docker run failure ( with exit code 1 )", func(t *testing.T) { - // given - mockGitHub := mock_github.NewMockService(ctrl) - mockGitHub.EXPECT().CreateCommitStatus(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(2). - Return(nil) - - // and - mockGit := mock_git.NewMockService(ctrl) - mockGit.EXPECT().Clone(gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - DoAndReturn(cloneSuccess) - - // and - mockDocker := mock_docker.NewMockService(ctrl) - mockDocker.EXPECT(). - Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - Return(&runner.MockBuildLog{}, nil) - mockDocker.EXPECT(). - Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - Return(docker.ContainerID(""), &runner.MockJobLog{}, nil) - mockDocker.EXPECT(). - ExitCode(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(docker.ExitCode(1), nil) - mockDocker.EXPECT(). - Rm(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - - // and - mockLogStore := mock_logstore.NewMockService(ctrl) - mockLogStore.EXPECT(). - Append(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - mockLogStore.EXPECT(). - Start(gomock.Any()). - AnyTimes(). - Return(nil) - mockLogStore.EXPECT(). - Finish(gomock.Any()). - AnyTimes(). - Return(nil) - - r := &runner.DockerRunner{ - BaseWorkDir: filepath.Join(os.TempDir(), "test-runner"), - Git: mockGit, - GitHub: mockGitHub, - Docker: mockDocker, - LogStore: mockLogStore, - } - - // and - repo := &runner.MockRepo{FullName: "duck8823/duci", SSHURL: "git@github.com:duck8823/duci.git"} - - // when - err := r.Run( - context.New("test/task", uuid.New(), &url.URL{}), - &github.TargetSource{Repo: repo, Ref: "master", SHA: plumbing.ZeroHash}, - "Hello World.", - ) - - // then - if err != runner.ErrFailure { - t.Errorf("error must be %s, but got %s", runner.ErrFailure, err) - } - }) - - t.Run("when runner timeout", func(t *testing.T) { - // given - mockGitHub := mock_github.NewMockService(ctrl) - mockGitHub.EXPECT().CreateCommitStatus(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(2). - Return(nil) - - // and - mockGit := mock_git.NewMockService(ctrl) - mockGit.EXPECT().Clone(gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - DoAndReturn(cloneSuccess) - - // and - application.Config.Job.Timeout = 1 - defer func() { - application.Config.Job.Timeout = 600 - }() - - mockDocker := mock_docker.NewMockService(ctrl) - mockDocker.EXPECT(). - Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - Return(&runner.MockBuildLog{}, nil) - mockDocker.EXPECT(). - Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - DoAndReturn(func(_, _, _, _ interface{}) (docker.ContainerID, docker.Log, error) { - time.Sleep(10 * time.Second) - return docker.ContainerID("container_id"), &runner.MockJobLog{}, nil - }) - mockDocker.EXPECT(). - ExitCode(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(docker.ExitCode(0), nil) - mockDocker.EXPECT(). - Rm(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - - // and - mockLogStore := mock_logstore.NewMockService(ctrl) - mockLogStore.EXPECT(). - Append(gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - mockLogStore.EXPECT(). - Start(gomock.Any()). - AnyTimes(). - Return(nil) - mockLogStore.EXPECT(). - Finish(gomock.Any()). - AnyTimes(). - Return(nil) - - r := &runner.DockerRunner{ - BaseWorkDir: filepath.Join(os.TempDir(), "test-runner"), - Git: mockGit, - GitHub: mockGitHub, - Docker: mockDocker, - LogStore: mockLogStore, - } - - // and - repo := &runner.MockRepo{FullName: "duck8823/duci", SSHURL: "git@github.com:duck8823/duci.git"} - - // when - err := r.Run( - context.New("test/task", uuid.New(), &url.URL{}), - &github.TargetSource{Repo: repo, Ref: "master", SHA: plumbing.ZeroHash}, - "Hello World.", - ) - - // then - if err.Error() != "context deadline exceeded" { - t.Errorf("error must be runner.ErrFailure, but got %+v", err) - } - }) -} - -func cloneSuccess(_ interface{}, dir string, _ interface{}) error { - if err := os.MkdirAll(dir, 0700); err != nil { - return err - } - - dockerfile, err := os.OpenFile(filepath.Join(dir, "Dockerfile"), os.O_RDWR|os.O_CREATE, 0600) - if err != nil { - return err - } - defer dockerfile.Close() - - dockerfile.WriteString("FROM alpine\nENTRYPOINT [\"echo\"]") - - return nil -} diff --git a/data/model/log.go b/data/model/log.go deleted file mode 100644 index f1ad5e68..00000000 --- a/data/model/log.go +++ /dev/null @@ -1,15 +0,0 @@ -package model - -import "time" - -// Job represents one of execution task. -type Job struct { - Finished bool `json:"finished"` - Stream []Message `json:"stream"` -} - -// Message is a log of job. -type Message struct { - Time time.Time `json:"time"` - Text string `json:"message"` -} diff --git a/infrastructure/docker/docker.go b/infrastructure/docker/docker.go deleted file mode 100644 index b14270a5..00000000 --- a/infrastructure/docker/docker.go +++ /dev/null @@ -1,148 +0,0 @@ -package docker - -import ( - "bufio" - "context" - "fmt" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - moby "github.com/docker/docker/client" - "github.com/pkg/errors" - "io" - "strings" -) - -// RuntimeOptions is a docker options. -type RuntimeOptions struct { - Environments Environments - Volumes Volumes -} - -// Environments represents a docker `-e` option. -type Environments map[string]interface{} - -// ToArray returns string array of environments -func (e Environments) ToArray() []string { - var a []string - for key, val := range e { - a = append(a, fmt.Sprintf("%s=%v", key, val)) - } - return a -} - -// Volumes represents a docker `-v` option. -type Volumes []string - -// ToMap returns map of volumes. -func (v Volumes) ToMap() map[string]struct{} { - m := make(map[string]struct{}) - for _, volume := range v { - key := strings.Split(volume, ":")[0] - m[key] = struct{}{} - } - return m -} - -// Client is a interface of docker client -type Client interface { - Build(ctx context.Context, file io.Reader, tag string, dockerfile string) (Log, error) - Run(ctx context.Context, opts RuntimeOptions, tag string, cmd ...string) (string, Log, error) - Rm(ctx context.Context, containerID string) error - Rmi(ctx context.Context, tag string) error - ExitCode(ctx context.Context, containerID string) (int64, error) - Info(ctx context.Context) (types.Info, error) -} - -type clientImpl struct { - moby Moby -} - -// New returns docker client. -func New() (*clientImpl, error) { - cli, err := moby.NewClientWithOpts(moby.FromEnv) - if err != nil { - return nil, errors.WithStack(err) - } - return &clientImpl{moby: cli}, nil -} - -// Build docker image. -func (c *clientImpl) Build(ctx context.Context, file io.Reader, tag string, dockerfile string) (Log, error) { - opts := types.ImageBuildOptions{ - Tags: []string{tag}, - Dockerfile: dockerfile, - Remove: true, - } - resp, err := c.moby.ImageBuild(ctx, file, opts) - if err != nil { - return nil, errors.WithStack(err) - } - - return &buildLogger{bufio.NewReader(resp.Body)}, nil -} - -// Run id a function create, start container. -func (c *clientImpl) Run(ctx context.Context, opts RuntimeOptions, tag string, cmd ...string) (string, Log, error) { - con, err := c.moby.ContainerCreate(ctx, &container.Config{ - Image: tag, - Env: opts.Environments.ToArray(), - Volumes: opts.Volumes.ToMap(), - Cmd: cmd, - }, &container.HostConfig{ - Binds: opts.Volumes, - }, nil, "") - if err != nil { - return "", nil, errors.WithStack(err) - } - - if err := c.moby.ContainerStart(ctx, con.ID, types.ContainerStartOptions{}); err != nil { - return con.ID, nil, errors.WithStack(err) - } - - log, err := c.moby.ContainerLogs(ctx, con.ID, types.ContainerLogsOptions{ - ShowStdout: true, - ShowStderr: true, - Follow: true, - }) - if err != nil { - return con.ID, nil, errors.WithStack(err) - } - - return con.ID, &runLogger{bufio.NewReader(log)}, nil -} - -// Rm remove docker container. -func (c *clientImpl) Rm(ctx context.Context, containerID string) error { - if err := c.moby.ContainerRemove(ctx, containerID, types.ContainerRemoveOptions{}); err != nil { - return errors.WithStack(err) - } - return nil -} - -// Rmi remove docker image. -func (c *clientImpl) Rmi(ctx context.Context, tag string) error { - if _, err := c.moby.ImageRemove(ctx, tag, types.ImageRemoveOptions{}); err != nil { - return errors.WithStack(err) - } - return nil -} - -// ExitCode wait container until exit and returns exit code. -func (c *clientImpl) ExitCode(ctx context.Context, containerID string) (int64, error) { - body, err := c.moby.ContainerWait(ctx, containerID, container.WaitConditionNotRunning) - select { - case b := <-body: - return b.StatusCode, nil - case e := <-err: - return -1, errors.WithStack(e) - } -} - -// Status returns error when failure get docker status. -func (c *clientImpl) Info(ctx context.Context) (types.Info, error) { - info, err := c.moby.Info(ctx) - if err != nil { - return types.Info{}, errors.WithStack(err) - } - return info, nil -} diff --git a/infrastructure/docker/docker_test.go b/infrastructure/docker/docker_test.go deleted file mode 100644 index 0cbafd0c..00000000 --- a/infrastructure/docker/docker_test.go +++ /dev/null @@ -1,595 +0,0 @@ -package docker_test - -import ( - "bytes" - "fmt" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/duck8823/duci/application/context" - "github.com/duck8823/duci/infrastructure/docker" - "github.com/duck8823/duci/infrastructure/docker/mock_docker" - "github.com/golang/mock/gomock" - "github.com/google/go-cmp/cmp" - "github.com/google/uuid" - "github.com/labstack/gommon/random" - "github.com/pkg/errors" - "io/ioutil" - "net/url" - "os" - "reflect" - "sort" - "strings" - "testing" -) - -func TestNew(t *testing.T) { - t.Run("with wrong docker environment", func(t *testing.T) { - // given - dockerHost := os.Getenv("DOCKER_HOST") - os.Setenv("DOCKER_HOST", "hoge") - defer os.Setenv("DOCKER_HOST", dockerHost) - - // expect - if _, err := docker.New(); err == nil { - t.Errorf("error must occur") - } - }) -} - -func TestClientImpl_Build(t *testing.T) { - // setup - sut, err := docker.New() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - - t.Run("when success image build", func(t *testing.T) { - // given - expected := "hello world" - sr := strings.NewReader(fmt.Sprintf("{\"stream\":\"%s\"}", expected)) - r := ioutil.NopCloser(sr) - - // and - ctrl := gomock.NewController(t) - mockMoby := mock_docker.NewMockMoby(ctrl) - - mockMoby.EXPECT(). - ImageBuild(gomock.Any(), gomock.Any(), gomock.Any()). - Return(types.ImageBuildResponse{Body: r}, nil) - - reset := sut.SetMoby(mockMoby) - defer reset() - - // when - log, err := sut.Build(context.New("test/task", uuid.New(), &url.URL{}), nil, "", "") - - // then - if err != nil { - t.Errorf("error must not occur, but got %+v", err) - } - - // and - line, err := log.ReadLine() - if err != nil { - t.Errorf("error must not occur, but got %+v", err) - } - - // and - if string(line.Message) != expected { - t.Errorf("must be equal. wont %#v, but got %#v", expected, string(line.Message)) - } - }) - - t.Run("when failure image build", func(t *testing.T) { - // given - ctrl := gomock.NewController(t) - mockMoby := mock_docker.NewMockMoby(ctrl) - - mockMoby.EXPECT(). - ImageBuild(gomock.Any(), gomock.Any(), gomock.Any()). - Return(types.ImageBuildResponse{}, errors.New("test error")) - - reset := sut.SetMoby(mockMoby) - defer reset() - - // expect - if _, err := sut.Build( - context.New("test/task", uuid.New(), &url.URL{}), - nil, - "", - "", - ); err == nil { - t.Errorf("error must occur, but got %+v", err) - } - }) -} - -func TestClientImpl_Run(t *testing.T) { - // setup - sut, err := docker.New() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - - t.Run("when failure create container", func(t *testing.T) { - // given - id := random.String(64, random.Alphanumeric, random.Symbols) - - // and - ctrl := gomock.NewController(t) - mockMoby := mock_docker.NewMockMoby(ctrl) - - mockMoby.EXPECT(). - ContainerCreate(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - AnyTimes(). - Return(container.ContainerCreateCreatedBody{ID: id}, errors.New("test error")) - - reset := sut.SetMoby(mockMoby) - defer reset() - - // when - actual, _, err := sut.Run(context.New("test/task", uuid.New(), &url.URL{}), docker.RuntimeOptions{}, "hello-world") - - // then - if actual != "" { - t.Errorf("id must be empty string, but got %+v", actual) - } - - if err == nil { - t.Error("error must occur, but got nil") - } - }) - - t.Run("when success create container", func(t *testing.T) { - t.Run("when failure start container", func(t *testing.T) { - // given - id := random.String(64, random.Alphanumeric, random.Symbols) - - // and - ctrl := gomock.NewController(t) - mockMoby := mock_docker.NewMockMoby(ctrl) - - mockMoby.EXPECT(). - ContainerCreate(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - AnyTimes(). - Return(container.ContainerCreateCreatedBody{ID: id}, nil) - - mockMoby.EXPECT(). - ContainerStart(gomock.Any(), gomock.Any(), gomock.Any()). - Return(errors.New("test error")) - - reset := sut.SetMoby(mockMoby) - defer reset() - - // when - actual, _, err := sut.Run(context.New("test/task", uuid.New(), &url.URL{}), docker.RuntimeOptions{}, "hello-world") - - // then - if actual != id { - t.Errorf("id must be equal %+v, but got %+v", id, actual) - } - - if err == nil { - t.Error("error must occur, but got nil") - } - }) - - t.Run("when success start container", func(t *testing.T) { - t.Run("when failure get log", func(t *testing.T) { - // given - id := random.String(64, random.Alphanumeric, random.Symbols) - - // and - ctrl := gomock.NewController(t) - mockMoby := mock_docker.NewMockMoby(ctrl) - - mockMoby.EXPECT(). - ContainerCreate(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - AnyTimes(). - Return(container.ContainerCreateCreatedBody{ID: id}, nil) - - mockMoby.EXPECT(). - ContainerStart(gomock.Any(), gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - - mockMoby.EXPECT(). - ContainerLogs(gomock.Any(), gomock.Any(), gomock.Any()). - Return(nil, errors.New("test error")) - - reset := sut.SetMoby(mockMoby) - defer reset() - - // when - actual, _, err := sut.Run(context.New("test/task", uuid.New(), &url.URL{}), docker.RuntimeOptions{}, "hello-world") - - // then - if actual != id { - t.Errorf("id must be equal %+v, but got %+v", id, actual) - } - - if err == nil { - t.Error("error must occur, but got nil") - } - }) - - t.Run("when success get log", func(t *testing.T) { - t.Run("with valid log", func(t *testing.T) { - // given - id := random.String(64, random.Alphanumeric, random.Symbols) - - prefix := []byte{1, 0, 0, 0, 1, 1, 1, 1} - msg := "hello test" - log := ioutil.NopCloser(bytes.NewReader(append(prefix, []byte(msg)...))) - - // and - ctrl := gomock.NewController(t) - mockMoby := mock_docker.NewMockMoby(ctrl) - - mockMoby.EXPECT(). - ContainerCreate(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - AnyTimes(). - Return(container.ContainerCreateCreatedBody{ID: id}, nil) - - mockMoby.EXPECT(). - ContainerStart(gomock.Any(), gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - - mockMoby.EXPECT(). - ContainerLogs(gomock.Any(), gomock.Any(), gomock.Any()). - Return(log, nil) - - reset := sut.SetMoby(mockMoby) - defer reset() - - // when - actualID, actualLog, err := sut.Run(context.New("test/task", uuid.New(), &url.URL{}), docker.RuntimeOptions{}, "hello-world") - - // then - if actualID != id { - t.Errorf("id must be equal %+v, but got %+v", id, actualID) - } - - if actualLog == nil { - t.Errorf("log must not nil") - } else { - line, _ := actualLog.ReadLine() - if string(line.Message) != msg { - t.Errorf("message must equal. wont %+v, but got %+v", msg, string(line.Message)) - } - } - - if err != nil { - t.Error("error must occur, but got nil") - } - }) - }) - }) - }) -} - -func TestClientImpl_Rm(t *testing.T) { - // setup - sut, err := docker.New() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - - t.Run("when success removing container", func(t *testing.T) { - // given - conID := random.String(16, random.Alphanumeric, random.Symbols) - - ctrl := gomock.NewController(t) - mockMoby := mock_docker.NewMockMoby(ctrl) - - mockMoby.EXPECT(). - ContainerRemove(gomock.Any(), gomock.Eq(conID), gomock.Any()). - Return(nil) - - reset := sut.SetMoby(mockMoby) - defer reset() - - // expect - if err := sut.Rm(context.New("test/task", uuid.New(), &url.URL{}), conID); err != nil { - t.Errorf("error must not occur, but got %+v", err) - } - }) - - t.Run("when failure removing container", func(t *testing.T) { - // given - conID := random.String(16, random.Alphanumeric, random.Symbols) - - ctrl := gomock.NewController(t) - mockMoby := mock_docker.NewMockMoby(ctrl) - - mockMoby.EXPECT(). - ContainerRemove(gomock.Any(), gomock.Eq(conID), gomock.Any()). - Return(errors.New("test error")) - - reset := sut.SetMoby(mockMoby) - defer reset() - - // expect - if err := sut.Rm(context.New("test/task", uuid.New(), &url.URL{}), conID); err == nil { - t.Error("error must occur, but got nil") - } - }) -} - -func TestClientImpl_Rmi(t *testing.T) { - // setup - sut, err := docker.New() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - - t.Run("when success removing image", func(t *testing.T) { - // given - imageID := random.String(16, random.Alphanumeric, random.Symbols) - - ctrl := gomock.NewController(t) - mockMoby := mock_docker.NewMockMoby(ctrl) - - mockMoby.EXPECT(). - ImageRemove(gomock.Any(), gomock.Eq(imageID), gomock.Any()). - Return(nil, nil) - - reset := sut.SetMoby(mockMoby) - defer reset() - - // expect - if err := sut.Rmi(context.New("test/task", uuid.New(), &url.URL{}), imageID); err != nil { - t.Errorf("error must not occur, but got %+v", err) - } - }) - - t.Run("when failure removing image", func(t *testing.T) { - // given - imageID := random.String(16, random.Alphanumeric, random.Symbols) - - ctrl := gomock.NewController(t) - mockMoby := mock_docker.NewMockMoby(ctrl) - - mockMoby.EXPECT(). - ImageRemove(gomock.Any(), gomock.Eq(imageID), gomock.Any()). - Return(nil, errors.New("test error")) - - reset := sut.SetMoby(mockMoby) - defer reset() - - // expect - if err := sut.Rmi(context.New("test/task", uuid.New(), &url.URL{}), imageID); err == nil { - t.Error("error must occur, but got nil") - } - }) -} - -func TestClientImpl_ExitCode2(t *testing.T) { - // setup - sut, err := docker.New() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - - t.Run("when success removing image", func(t *testing.T) { - // given - imageID := random.String(16, random.Alphanumeric, random.Symbols) - - ctrl := gomock.NewController(t) - mockMoby := mock_docker.NewMockMoby(ctrl) - - mockMoby.EXPECT(). - ImageRemove(gomock.Any(), gomock.Eq(imageID), gomock.Any()). - Return(nil, nil) - - reset := sut.SetMoby(mockMoby) - defer reset() - - // expect - if err := sut.Rmi(context.New("test/task", uuid.New(), &url.URL{}), imageID); err != nil { - t.Errorf("error must not occur, but got %+v", err) - } - }) - - t.Run("when failure removing image", func(t *testing.T) { - // given - imageID := random.String(16, random.Alphanumeric, random.Symbols) - - ctrl := gomock.NewController(t) - mockMoby := mock_docker.NewMockMoby(ctrl) - - mockMoby.EXPECT(). - ImageRemove(gomock.Any(), gomock.Eq(imageID), gomock.Any()). - Return(nil, errors.New("test error")) - - reset := sut.SetMoby(mockMoby) - defer reset() - - // expect - if err := sut.Rmi(context.New("test/task", uuid.New(), &url.URL{}), imageID); err == nil { - t.Error("error must occur, but got nil") - } - }) -} - -func TestClientImpl_ExitCode(t *testing.T) { - // setup - sut, err := docker.New() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - - t.Run("with exit code 0", func(t *testing.T) { - // given - exitCode := int64(19) - - body := make(chan container.ContainerWaitOKBody, 1) - err := make(chan error, 1) - - // and - body <- container.ContainerWaitOKBody{StatusCode: exitCode} - - // and - conID := random.String(16, random.Alphanumeric, random.Symbols) - - ctrl := gomock.NewController(t) - mockMoby := mock_docker.NewMockMoby(ctrl) - - mockMoby.EXPECT(). - ContainerWait(gomock.Any(), gomock.Eq(conID), gomock.Any()). - Return(body, err) - - reset := sut.SetMoby(mockMoby) - defer reset() - - // when - if code, _ := sut.ExitCode(context.New("test/task", uuid.New(), &url.URL{}), conID); code != exitCode { - t.Errorf("code must equal %+v, but got %+v", exitCode, code) - } - }) - - t.Run("with error", func(t *testing.T) { - // given - body := make(chan container.ContainerWaitOKBody, 1) - err := make(chan error, 1) - - // and - err <- errors.New("test error") - - // and - conID := random.String(16, random.Alphanumeric, random.Symbols) - - ctrl := gomock.NewController(t) - mockMoby := mock_docker.NewMockMoby(ctrl) - - mockMoby.EXPECT(). - ContainerWait(gomock.Any(), gomock.Eq(conID), gomock.Any()). - Return(body, err) - - reset := sut.SetMoby(mockMoby) - defer reset() - - // when - if _, actualErr := sut.ExitCode(context.New("test/task", uuid.New(), &url.URL{}), conID); actualErr == nil { - t.Error("error must occur but got nil") - } - }) -} - -func TestClientImpl_Info(t *testing.T) { - // setup - sut, err := docker.New() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - - t.Run("without error", func(t *testing.T) { - // given - expected := types.Info{ID: uuid.New().String()} - - // and - ctrl := gomock.NewController(t) - mockMoby := mock_docker.NewMockMoby(ctrl) - - mockMoby.EXPECT(). - Info(gomock.Any()). - Return(expected, nil) - - reset := sut.SetMoby(mockMoby) - defer reset() - - // when - actual, err := sut.Info(context.New("test", uuid.New(), nil)) - - // then - if !cmp.Equal(actual, expected) { - t.Errorf("must be equal. %+v", cmp.Diff(actual, expected)) - } - - if err != nil { - t.Errorf("error must not occur, but got %+v", err) - } - }) - - t.Run("with error", func(t *testing.T) { - // given - ctrl := gomock.NewController(t) - mockMoby := mock_docker.NewMockMoby(ctrl) - - mockMoby.EXPECT(). - Info(gomock.Any()). - Return(types.Info{}, errors.New("test")) - - reset := sut.SetMoby(mockMoby) - defer reset() - - // expect - if _, err := sut.Info(context.New("test", uuid.New(), nil)); err == nil { - t.Error("error must occur, but got nil") - } - }) -} - -func TestEnvironments_ToArray(t *testing.T) { - var empty []string - for _, testcase := range []struct { - in docker.Environments - expected []string - }{ - { - in: docker.Environments{}, - expected: empty, - }, - { - in: docker.Environments{ - "int": 19, - "string": "hello", - }, - expected: []string{ - "int=19", - "string=hello", - }, - }, - } { - // when - actual := testcase.in.ToArray() - expected := testcase.expected - sort.Strings(actual) - sort.Strings(expected) - - // then - if !reflect.DeepEqual(actual, expected) { - t.Errorf("must be equal. actual=%+v, wont=%+v", actual, expected) - } - } -} - -func TestVolumes_Volumes(t *testing.T) { - for _, testcase := range []struct { - in docker.Volumes - expected map[string]struct{} - }{ - { - in: docker.Volumes{}, - expected: make(map[string]struct{}), - }, - { - in: docker.Volumes{ - "/hoge/fuga:/hoge/hoge", - }, - expected: map[string]struct{}{ - "/hoge/fuga": {}, - }, - }, - } { - // when - actual := testcase.in.ToMap() - expected := testcase.expected - - // then - if !reflect.DeepEqual(actual, expected) { - t.Errorf("must be equal. actual=%+v, wont=%+v", actual, expected) - } - } -} diff --git a/infrastructure/docker/export_test.go b/infrastructure/docker/export_test.go deleted file mode 100644 index 26473089..00000000 --- a/infrastructure/docker/export_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package docker - -import ( - "bufio" - "time" -) - -func SetNowFunc(f func() time.Time) (reset func()) { - tmp := now - now = f - return func() { - now = tmp - } -} - -type BuildLogger = buildLogger - -func (l *buildLogger) SetReader(r *bufio.Reader) (reset func()) { - tmp := l.reader - l.reader = r - return func() { - l.reader = tmp - } -} - -type RunLogger = runLogger - -func (l *runLogger) SetReader(r *bufio.Reader) (reset func()) { - tmp := l.reader - l.reader = r - return func() { - l.reader = tmp - } -} - -func (c *clientImpl) SetMoby(m Moby) (reset func()) { - tmp := c.moby - c.moby = m - return func() { - c.moby = tmp - } -} diff --git a/infrastructure/docker/log.go b/infrastructure/docker/log.go deleted file mode 100644 index 399098c8..00000000 --- a/infrastructure/docker/log.go +++ /dev/null @@ -1,92 +0,0 @@ -package docker - -import ( - "bufio" - "bytes" - "encoding/json" - "fmt" - "github.com/pkg/errors" - "io" - "time" -) - -var now = time.Now - -// Log is a interface represents docker log. -type Log interface { - ReadLine() (*LogLine, error) -} - -// LogLine stores timestamp and a line. -type LogLine struct { - Timestamp time.Time - Message []byte -} - -type buildLogger struct { - reader *bufio.Reader -} - -// ReadLine returns LogLine. -func (l *buildLogger) ReadLine() (*LogLine, error) { - for { - line, _, readErr := l.reader.ReadLine() - msg := extractMessage(line) - if readErr == io.EOF { - return &LogLine{Timestamp: now(), Message: msg}, readErr - } - if readErr != nil { - return nil, errors.WithStack(readErr) - } - - if len(msg) == 0 { - continue - } - - return &LogLine{Timestamp: now(), Message: msg}, readErr - } -} - -type runLogger struct { - reader *bufio.Reader -} - -// ReadLine returns LogLine. -func (l *runLogger) ReadLine() (*LogLine, error) { - for { - line, _, readErr := l.reader.ReadLine() - if readErr != nil && readErr != io.EOF { - return nil, errors.WithStack(readErr) - } - - messages, err := trimPrefix(line) - if err != nil { - return nil, errors.WithStack(err) - } - - // prevent to CR - progress := bytes.Split(messages, []byte{'\r'}) - return &LogLine{Timestamp: now(), Message: progress[0]}, readErr - } -} - -func extractMessage(line []byte) []byte { - s := &struct { - Stream string `json:"stream"` - }{} - json.NewDecoder(bytes.NewReader(line)).Decode(s) - return []byte(s.Stream) -} - -func trimPrefix(line []byte) ([]byte, error) { - if len(line) < 8 { - return []byte{}, nil - } - - // detect logstore prefix - // see https://godoc.org/github.com/docker/docker/client#Client.ContainerLogs - if !((line[0] == 1 || line[0] == 2) && (line[1] == 0 && line[2] == 0 && line[3] == 0)) { - return nil, fmt.Errorf("invalid logstore prefix: %+v", line[:7]) - } - return line[8:], nil -} diff --git a/infrastructure/docker/log_test.go b/infrastructure/docker/log_test.go deleted file mode 100644 index be5a239f..00000000 --- a/infrastructure/docker/log_test.go +++ /dev/null @@ -1,132 +0,0 @@ -package docker_test - -import ( - "bufio" - "bytes" - "github.com/duck8823/duci/infrastructure/docker" - "reflect" - "strings" - "testing" - "time" -) - -func TestBuildLogger_ReadLine(t *testing.T) { - // given - jst, err := time.LoadLocation("Asia/Tokyo") - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - date := time.Date(2020, time.December, 4, 4, 32, 12, 3, jst) - - resetNowFunc := docker.SetNowFunc(func() time.Time { - return date - }) - defer resetNowFunc() - - // and - reader := bufio.NewReader(strings.NewReader("{\"stream\":\"Hello World.\"}")) - logger := &docker.BuildLogger{} - reset := logger.SetReader(reader) - defer reset() - - // and - expected := &docker.LogLine{Timestamp: date, Message: []byte("Hello World.")} - - // when - actual, err := logger.ReadLine() - - // then - if err != nil { - t.Errorf("error must not occur, but got %+v", err) - } - - // and - if !reflect.DeepEqual(expected, actual) { - t.Errorf("must be equal: wont %+v, but got %+v", expected, actual) - } -} - -func TestRunLogger_ReadLine(t *testing.T) { - // setup - jst, err := time.LoadLocation("Asia/Tokyo") - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - date := time.Date(2020, time.December, 4, 4, 32, 12, 3, jst) - - resetNowFunc := docker.SetNowFunc(func() time.Time { - return date - }) - defer resetNowFunc() - - t.Run("with correct format", func(t *testing.T) { - // given - prefix := []byte{1, 0, 0, 0, 9, 9, 9, 9} - reader := bufio.NewReader(bytes.NewReader(append(prefix, 'H', 'e', 'l', 'l', 'o'))) - logger := &docker.RunLogger{} - reset := logger.SetReader(reader) - defer reset() - - // and - expected := &docker.LogLine{Timestamp: date, Message: []byte("Hello")} - - // when - actual, err := logger.ReadLine() - - // then - if err != nil { - t.Errorf("error must not occur, but got %+v", err) - } - - // and - if !reflect.DeepEqual(expected, actual) { - t.Errorf("must be equal: wont %+v, but got %+v", expected, actual) - } - }) - - t.Run("with invalid format", func(t *testing.T) { - // given - prefix := []byte{0, 0, 0, 0, 9, 9, 9, 9} - reader := bufio.NewReader(bytes.NewReader(append(prefix, 'H', 'e', 'l', 'l', 'o'))) - logger := &docker.RunLogger{} - reset := logger.SetReader(reader) - defer reset() - - // when - actual, err := logger.ReadLine() - - // then - if err == nil { - t.Error("error must occur, but got nil") - } - - // and - if actual != nil { - t.Errorf("must be equal: wont nil, but got %+v", actual) - } - }) - - t.Run("when too short", func(t *testing.T) { - // given - reader := bufio.NewReader(bytes.NewReader([]byte{'H', 'e', 'l', 'l', 'o'})) - logger := &docker.RunLogger{} - reset := logger.SetReader(reader) - defer reset() - - // and - expected := &docker.LogLine{Timestamp: date, Message: []byte{}} - - // when - actual, err := logger.ReadLine() - - // then - if err != nil { - t.Errorf("error must not occur, but got %+v", err) - } - - // and - if !reflect.DeepEqual(expected, actual) { - t.Errorf("must be equal: wont %+v, but got %+v", expected, actual) - } - }) -} diff --git a/infrastructure/docker/mock_docker/docker.go b/infrastructure/docker/mock_docker/docker.go deleted file mode 100644 index 2747d6d3..00000000 --- a/infrastructure/docker/mock_docker/docker.go +++ /dev/null @@ -1,119 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: infrastructure/docker/docker.go - -// Package mock_docker is a generated GoMock package. -package mock_docker - -import ( - context "context" - types "github.com/docker/docker/api/types" - docker "github.com/duck8823/duci/infrastructure/docker" - gomock "github.com/golang/mock/gomock" - io "io" - reflect "reflect" -) - -// MockClient is a mock of Client interface -type MockClient struct { - ctrl *gomock.Controller - recorder *MockClientMockRecorder -} - -// MockClientMockRecorder is the mock recorder for MockClient -type MockClientMockRecorder struct { - mock *MockClient -} - -// NewMockClient creates a new mock instance -func NewMockClient(ctrl *gomock.Controller) *MockClient { - mock := &MockClient{ctrl: ctrl} - mock.recorder = &MockClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockClient) EXPECT() *MockClientMockRecorder { - return m.recorder -} - -// Build mocks base method -func (m *MockClient) Build(ctx context.Context, file io.Reader, tag, dockerfile string) (docker.Log, error) { - ret := m.ctrl.Call(m, "Build", ctx, file, tag, dockerfile) - ret0, _ := ret[0].(docker.Log) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Build indicates an expected call of Build -func (mr *MockClientMockRecorder) Build(ctx, file, tag, dockerfile interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Build", reflect.TypeOf((*MockClient)(nil).Build), ctx, file, tag, dockerfile) -} - -// Run mocks base method -func (m *MockClient) Run(ctx context.Context, opts docker.RuntimeOptions, tag string, cmd ...string) (string, docker.Log, error) { - varargs := []interface{}{ctx, opts, tag} - for _, a := range cmd { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "Run", varargs...) - ret0, _ := ret[0].(string) - ret1, _ := ret[1].(docker.Log) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// Run indicates an expected call of Run -func (mr *MockClientMockRecorder) Run(ctx, opts, tag interface{}, cmd ...interface{}) *gomock.Call { - varargs := append([]interface{}{ctx, opts, tag}, cmd...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Run", reflect.TypeOf((*MockClient)(nil).Run), varargs...) -} - -// Rm mocks base method -func (m *MockClient) Rm(ctx context.Context, containerID string) error { - ret := m.ctrl.Call(m, "Rm", ctx, containerID) - ret0, _ := ret[0].(error) - return ret0 -} - -// Rm indicates an expected call of Rm -func (mr *MockClientMockRecorder) Rm(ctx, containerID interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Rm", reflect.TypeOf((*MockClient)(nil).Rm), ctx, containerID) -} - -// Rmi mocks base method -func (m *MockClient) Rmi(ctx context.Context, tag string) error { - ret := m.ctrl.Call(m, "Rmi", ctx, tag) - ret0, _ := ret[0].(error) - return ret0 -} - -// Rmi indicates an expected call of Rmi -func (mr *MockClientMockRecorder) Rmi(ctx, tag interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Rmi", reflect.TypeOf((*MockClient)(nil).Rmi), ctx, tag) -} - -// ExitCode mocks base method -func (m *MockClient) ExitCode(ctx context.Context, containerID string) (int64, error) { - ret := m.ctrl.Call(m, "ExitCode", ctx, containerID) - ret0, _ := ret[0].(int64) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ExitCode indicates an expected call of ExitCode -func (mr *MockClientMockRecorder) ExitCode(ctx, containerID interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExitCode", reflect.TypeOf((*MockClient)(nil).ExitCode), ctx, containerID) -} - -// Info mocks base method -func (m *MockClient) Info(ctx context.Context) (types.Info, error) { - ret := m.ctrl.Call(m, "Info", ctx) - ret0, _ := ret[0].(types.Info) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Info indicates an expected call of Info -func (mr *MockClientMockRecorder) Info(ctx interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Info", reflect.TypeOf((*MockClient)(nil).Info), ctx) -} diff --git a/infrastructure/docker/mock_docker/third_party.go b/infrastructure/docker/mock_docker/third_party.go deleted file mode 100644 index 2837d0c5..00000000 --- a/infrastructure/docker/mock_docker/third_party.go +++ /dev/null @@ -1,140 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: infrastructure/docker/third_pirty.go - -// Package mock_docker is a generated GoMock package. -package mock_docker - -import ( - context "context" - types "github.com/docker/docker/api/types" - container "github.com/docker/docker/api/types/container" - network "github.com/docker/docker/api/types/network" - gomock "github.com/golang/mock/gomock" - io "io" - reflect "reflect" -) - -// MockMoby is a mock of Moby interface -type MockMoby struct { - ctrl *gomock.Controller - recorder *MockMobyMockRecorder -} - -// MockMobyMockRecorder is the mock recorder for MockMoby -type MockMobyMockRecorder struct { - mock *MockMoby -} - -// NewMockMoby creates a new mock instance -func NewMockMoby(ctrl *gomock.Controller) *MockMoby { - mock := &MockMoby{ctrl: ctrl} - mock.recorder = &MockMobyMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockMoby) EXPECT() *MockMobyMockRecorder { - return m.recorder -} - -// ImageBuild mocks base method -func (m *MockMoby) ImageBuild(ctx context.Context, buildContext io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) { - ret := m.ctrl.Call(m, "ImageBuild", ctx, buildContext, options) - ret0, _ := ret[0].(types.ImageBuildResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ImageBuild indicates an expected call of ImageBuild -func (mr *MockMobyMockRecorder) ImageBuild(ctx, buildContext, options interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ImageBuild", reflect.TypeOf((*MockMoby)(nil).ImageBuild), ctx, buildContext, options) -} - -// ContainerCreate mocks base method -func (m *MockMoby) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (container.ContainerCreateCreatedBody, error) { - ret := m.ctrl.Call(m, "ContainerCreate", ctx, config, hostConfig, networkingConfig, containerName) - ret0, _ := ret[0].(container.ContainerCreateCreatedBody) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ContainerCreate indicates an expected call of ContainerCreate -func (mr *MockMobyMockRecorder) ContainerCreate(ctx, config, hostConfig, networkingConfig, containerName interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContainerCreate", reflect.TypeOf((*MockMoby)(nil).ContainerCreate), ctx, config, hostConfig, networkingConfig, containerName) -} - -// ContainerStart mocks base method -func (m *MockMoby) ContainerStart(ctx context.Context, containerID string, options types.ContainerStartOptions) error { - ret := m.ctrl.Call(m, "ContainerStart", ctx, containerID, options) - ret0, _ := ret[0].(error) - return ret0 -} - -// ContainerStart indicates an expected call of ContainerStart -func (mr *MockMobyMockRecorder) ContainerStart(ctx, containerID, options interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContainerStart", reflect.TypeOf((*MockMoby)(nil).ContainerStart), ctx, containerID, options) -} - -// ContainerLogs mocks base method -func (m *MockMoby) ContainerLogs(ctx context.Context, container string, options types.ContainerLogsOptions) (io.ReadCloser, error) { - ret := m.ctrl.Call(m, "ContainerLogs", ctx, container, options) - ret0, _ := ret[0].(io.ReadCloser) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ContainerLogs indicates an expected call of ContainerLogs -func (mr *MockMobyMockRecorder) ContainerLogs(ctx, container, options interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContainerLogs", reflect.TypeOf((*MockMoby)(nil).ContainerLogs), ctx, container, options) -} - -// ContainerRemove mocks base method -func (m *MockMoby) ContainerRemove(ctx context.Context, containerID string, options types.ContainerRemoveOptions) error { - ret := m.ctrl.Call(m, "ContainerRemove", ctx, containerID, options) - ret0, _ := ret[0].(error) - return ret0 -} - -// ContainerRemove indicates an expected call of ContainerRemove -func (mr *MockMobyMockRecorder) ContainerRemove(ctx, containerID, options interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContainerRemove", reflect.TypeOf((*MockMoby)(nil).ContainerRemove), ctx, containerID, options) -} - -// ImageRemove mocks base method -func (m *MockMoby) ImageRemove(ctx context.Context, imageID string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) { - ret := m.ctrl.Call(m, "ImageRemove", ctx, imageID, options) - ret0, _ := ret[0].([]types.ImageDeleteResponseItem) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ImageRemove indicates an expected call of ImageRemove -func (mr *MockMobyMockRecorder) ImageRemove(ctx, imageID, options interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ImageRemove", reflect.TypeOf((*MockMoby)(nil).ImageRemove), ctx, imageID, options) -} - -// ContainerWait mocks base method -func (m *MockMoby) ContainerWait(ctx context.Context, containerID string, condition container.WaitCondition) (<-chan container.ContainerWaitOKBody, <-chan error) { - ret := m.ctrl.Call(m, "ContainerWait", ctx, containerID, condition) - ret0, _ := ret[0].(<-chan container.ContainerWaitOKBody) - ret1, _ := ret[1].(<-chan error) - return ret0, ret1 -} - -// ContainerWait indicates an expected call of ContainerWait -func (mr *MockMobyMockRecorder) ContainerWait(ctx, containerID, condition interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContainerWait", reflect.TypeOf((*MockMoby)(nil).ContainerWait), ctx, containerID, condition) -} - -// Info mocks base method -func (m *MockMoby) Info(ctx context.Context) (types.Info, error) { - ret := m.ctrl.Call(m, "Info", ctx) - ret0, _ := ret[0].(types.Info) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Info indicates an expected call of Info -func (mr *MockMobyMockRecorder) Info(ctx interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Info", reflect.TypeOf((*MockMoby)(nil).Info), ctx) -} diff --git a/infrastructure/docker/testdata/correct_archive.tar b/infrastructure/docker/testdata/correct_archive.tar deleted file mode 100644 index 81c54d189084b5d1eaf49bdb70f7b8d401152c4b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2048 zcmZ?CPtHy)O3TbiWuO@_FfcGPF;QRu(&lESVA{Y4!UqZgfti7Vp|P=vfr+W1ftk62 zfuXU9nJI&U0nJ>5WN>M5Nn#PuX(^@2*%lT?#z;~qOrWx~G!zk34#X!A&lwmfph^y2 zo?DQ=uR>x@L1td6RZe0_YHnLbQ5naz?(og1Sd)PENi;cz#h%ik^Bb*WmTZ TsLMt}U^E0qLtr!nNC^P|9#STZ diff --git a/infrastructure/docker/testdata/correct_archive_subdir.tar b/infrastructure/docker/testdata/correct_archive_subdir.tar deleted file mode 100644 index 8f2344fa20751f427417201c79fe6bc724cca229..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2560 zcmeH^JqyAx5Qa1NSKOAZCTWt2t3_Oj;Nl<-rA@Ik80p9VH@3y0Shs*;ZaMCQ%bVv7 zi$1Sb$Y~HlVj%!Mvm7&Fe5h?}2%u5K2^W-60faIha|FVvs_A&&c3ESkSq}Aj&7!3@ z?OItb4Q+q=$18tW{iabk_@9`(R!v!Hl@B};oPvAERJOGoGJ{14} diff --git a/infrastructure/docker/testdata/data b/infrastructure/docker/testdata/data deleted file mode 100644 index bdd51cc2..00000000 --- a/infrastructure/docker/testdata/data +++ /dev/null @@ -1 +0,0 @@ -hello-world \ No newline at end of file diff --git a/infrastructure/docker/testdata/invalid_archive.tar b/infrastructure/docker/testdata/invalid_archive.tar deleted file mode 100644 index 8c7df4eb60a14af54d0902a6455bf84cb5f504cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1536 zcmZ=M&CRW3pe-;kFfcPQQD6Yl=4Pf~8pwpvKqio5Xl!g~0+cp4F;y@yG%__XWl%7n zt+ODemll^K76F}>QktA?VPRy9%g*wQ)YKeYl0b2=H{hO9z@u_hYBU5!Ltr!n21N(} E0G6&5lK=n! diff --git a/infrastructure/docker/third_pirty.go b/infrastructure/docker/third_pirty.go deleted file mode 100644 index 6b7ad5d1..00000000 --- a/infrastructure/docker/third_pirty.go +++ /dev/null @@ -1,54 +0,0 @@ -package docker - -import ( - "context" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/network" - "io" -) - -// Moby is a interface of docker client -// see also github.com/moby/moby/client -type Moby interface { - ImageBuild( - ctx context.Context, - buildContext io.Reader, - options types.ImageBuildOptions, - ) (types.ImageBuildResponse, error) - ContainerCreate( - ctx context.Context, - config *container.Config, - hostConfig *container.HostConfig, - networkingConfig *network.NetworkingConfig, - containerName string, - ) (container.ContainerCreateCreatedBody, error) - ContainerStart( - ctx context.Context, - containerID string, - options types.ContainerStartOptions, - ) error - ContainerLogs( - ctx context.Context, - container string, - options types.ContainerLogsOptions, - ) (io.ReadCloser, error) - ContainerRemove( - ctx context.Context, - containerID string, - options types.ContainerRemoveOptions, - ) error - ImageRemove( - ctx context.Context, - imageID string, - options types.ImageRemoveOptions, - ) ([]types.ImageDeleteResponseItem, error) - ContainerWait( - ctx context.Context, - containerID string, - condition container.WaitCondition, - ) (<-chan container.ContainerWaitOKBody, <-chan error) - Info( - ctx context.Context, - ) (types.Info, error) -} diff --git a/infrastructure/logger/export_test.go b/infrastructure/logger/export_test.go deleted file mode 100644 index 13c4f7c2..00000000 --- a/infrastructure/logger/export_test.go +++ /dev/null @@ -1,11 +0,0 @@ -package logger - -import "time" - -func SetNowFunc(f func() time.Time) (reset func()) { - tmp := now - now = f - return func() { - now = tmp - } -} diff --git a/infrastructure/logger/logger.go b/infrastructure/logger/logger.go deleted file mode 100644 index c351f523..00000000 --- a/infrastructure/logger/logger.go +++ /dev/null @@ -1,58 +0,0 @@ -package logger - -import ( - "fmt" - "github.com/google/uuid" - "io" - "os" - "time" -) - -var ( - timeFormat = "2006-01-02 15:04:05.000" - // Writer is a log writer. default is os.Stdout. - Writer io.Writer = os.Stdout - now = time.Now -) - -// Debug logs with the Debug severity. -func Debug(uuid uuid.UUID, message string) { - if len(message) < 1 || message[len(message)-1] != '\n' { - message += "\n" - } - Writer.Write([]byte(fmt.Sprintf("[%s] %s \033[36;1m[DEBUG]\033[0m %s", uuid, now().Format(timeFormat), message))) -} - -// Debugf logs with the Debug severity. -func Debugf(uuid uuid.UUID, format string, args ...interface{}) { - message := fmt.Sprintf(format, args...) - Debug(uuid, message) -} - -// Info logs with the Info severity. -func Info(uuid uuid.UUID, message string) { - if len(message) < 1 || message[len(message)-1] != '\n' { - message += "\n" - } - Writer.Write([]byte(fmt.Sprintf("[%s] %s \033[1m[INFO]\033[0m %s", uuid, now().Format(timeFormat), message))) -} - -// Infof logs with the Info severity. -func Infof(uuid uuid.UUID, format string, args ...interface{}) { - message := fmt.Sprintf(format, args...) - Info(uuid, message) -} - -// Error logs with the Error severity. -func Error(uuid uuid.UUID, message string) { - if len(message) < 1 || message[len(message)-1] != '\n' { - message += "\n" - } - Writer.Write([]byte(fmt.Sprintf("[%s] %s \033[41;1m[ERROR]\033[0m %s", uuid, now().Format(timeFormat), message))) -} - -// Errorf logs with the Error severity. -func Errorf(uuid uuid.UUID, format string, args ...interface{}) { - message := fmt.Sprintf(format, args...) - Error(uuid, message) -} diff --git a/infrastructure/logger/logger_test.go b/infrastructure/logger/logger_test.go deleted file mode 100644 index 06b2e0ea..00000000 --- a/infrastructure/logger/logger_test.go +++ /dev/null @@ -1,193 +0,0 @@ -package logger_test - -import ( - "github.com/duck8823/duci/infrastructure/logger" - "github.com/google/uuid" - "io" - "io/ioutil" - "os" - "strings" - "testing" - "time" -) - -var ( - reader io.ReadCloser - writer io.WriteCloser -) - -func TestDebug(t *testing.T) { - // setup - initLogger(t) - - // and - jst, err := time.LoadLocation("Asia/Tokyo") - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - reset := logger.SetNowFunc(func() time.Time { - return time.Date(1987, time.March, 27, 19, 19, 00, 00, jst) - }) - defer reset() - - // when - logger.Debug(uuid.UUID{}, "Hello World.") - - actual := readLog(t) - expected := "[00000000-0000-0000-0000-000000000000] 1987-03-27 19:19:00.000 \033[36;1m[DEBUG]\033[0m Hello World." - - // then - if actual != expected { - t.Errorf("wrong logstore. wont: \"%+v\", got: \"%+v\"", expected, actual) - } -} - -func TestDebugf(t *testing.T) { - // setup - initLogger(t) - - // and - jst, err := time.LoadLocation("Asia/Tokyo") - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - logger.SetNowFunc(func() time.Time { - return time.Date(1987, time.March, 27, 19, 19, 00, 00, jst) - }) - defer logger.SetNowFunc(time.Now) - - // when - logger.Debugf(uuid.UUID{}, "Hello %s.", "World") - - actual := readLog(t) - expected := "[00000000-0000-0000-0000-000000000000] 1987-03-27 19:19:00.000 \033[36;1m[DEBUG]\033[0m Hello World." - - // then - if actual != expected { - t.Errorf("wrong logstore. wont: \"%+v\", got: \"%+v\"", expected, actual) - } -} - -func TestInfo(t *testing.T) { - // setup - initLogger(t) - - // and - jst, err := time.LoadLocation("Asia/Tokyo") - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - logger.SetNowFunc(func() time.Time { - return time.Date(1987, time.March, 27, 19, 19, 00, 00, jst) - }) - defer logger.SetNowFunc(time.Now) - - // when - logger.Info(uuid.UUID{}, "Hello World.") - - actual := readLog(t) - expected := "[00000000-0000-0000-0000-000000000000] 1987-03-27 19:19:00.000 \033[1m[INFO]\033[0m Hello World." - - // then - if actual != expected { - t.Errorf("wrong logstore. wont: \"%+v\", got: \"%+v\"", expected, actual) - } -} - -func TestInfof(t *testing.T) { - // setup - initLogger(t) - - // and - jst, err := time.LoadLocation("Asia/Tokyo") - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - logger.SetNowFunc(func() time.Time { - return time.Date(1987, time.March, 27, 19, 19, 00, 00, jst) - }) - defer logger.SetNowFunc(time.Now) - - // when - logger.Infof(uuid.UUID{}, "Hello %s.", "World") - - actual := readLog(t) - expected := "[00000000-0000-0000-0000-000000000000] 1987-03-27 19:19:00.000 \033[1m[INFO]\033[0m Hello World." - - // then - if actual != expected { - t.Errorf("wrong logstore. wont: \"%+v\", got: \"%+v\"", expected, actual) - } -} - -func TestError(t *testing.T) { - // setup - initLogger(t) - - // and - jst, err := time.LoadLocation("Asia/Tokyo") - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - logger.SetNowFunc(func() time.Time { - return time.Date(1987, time.March, 27, 19, 19, 00, 00, jst) - }) - defer logger.SetNowFunc(time.Now) - - // when - logger.Error(uuid.UUID{}, "Hello World.") - - actual := readLog(t) - expected := "[00000000-0000-0000-0000-000000000000] 1987-03-27 19:19:00.000 \033[41;1m[ERROR]\033[0m Hello World." - - // then - if actual != expected { - t.Errorf("wrong logstore. wont: \"%+v\", got: \"%+v\"", expected, actual) - } -} - -func TestErrorf(t *testing.T) { - // setup - initLogger(t) - - // and - jst, err := time.LoadLocation("Asia/Tokyo") - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - logger.SetNowFunc(func() time.Time { - return time.Date(1987, time.March, 27, 19, 19, 00, 00, jst) - }) - defer logger.SetNowFunc(time.Now) - - // when - logger.Errorf(uuid.UUID{}, "Hello %s.", "World") - - actual := readLog(t) - expected := "[00000000-0000-0000-0000-000000000000] 1987-03-27 19:19:00.000 \033[41;1m[ERROR]\033[0m Hello World." - - // then - if actual != expected { - t.Errorf("wrong logstore. wont: \"%+v\", got: \"%+v\"", expected, actual) - } -} - -func initLogger(t *testing.T) { - t.Helper() - - reader, writer, _ = os.Pipe() - - logger.Writer = writer -} - -func readLog(t *testing.T) string { - t.Helper() - - writer.Close() - log, err := ioutil.ReadAll(reader) - if err != nil { - t.Error() - } - - return strings.TrimRight(string(log), "\n") -} diff --git a/infrastructure/store/mock_store/store.go b/infrastructure/store/mock_store/store.go deleted file mode 100644 index 900174ad..00000000 --- a/infrastructure/store/mock_store/store.go +++ /dev/null @@ -1,84 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: infrastructure/store/store.go - -// Package mock_store is a generated GoMock package. -package mock_store - -import ( - store "github.com/duck8823/duci/infrastructure/store" - gomock "github.com/golang/mock/gomock" - reflect "reflect" -) - -// MockStore is a mock of Store interface -type MockStore struct { - ctrl *gomock.Controller - recorder *MockStoreMockRecorder -} - -// MockStoreMockRecorder is the mock recorder for MockStore -type MockStoreMockRecorder struct { - mock *MockStore -} - -// NewMockStore creates a new mock instance -func NewMockStore(ctrl *gomock.Controller) *MockStore { - mock := &MockStore{ctrl: ctrl} - mock.recorder = &MockStoreMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockStore) EXPECT() *MockStoreMockRecorder { - return m.recorder -} - -// Get mocks base method -func (m *MockStore) Get(key []byte, ro *store.ReadOptions) ([]byte, error) { - ret := m.ctrl.Call(m, "Get", key, ro) - ret0, _ := ret[0].([]byte) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get -func (mr *MockStoreMockRecorder) Get(key, ro interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockStore)(nil).Get), key, ro) -} - -// Has mocks base method -func (m *MockStore) Has(key []byte, ro *store.ReadOptions) (bool, error) { - ret := m.ctrl.Call(m, "Has", key, ro) - ret0, _ := ret[0].(bool) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Has indicates an expected call of Has -func (mr *MockStoreMockRecorder) Has(key, ro interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Has", reflect.TypeOf((*MockStore)(nil).Has), key, ro) -} - -// Put mocks base method -func (m *MockStore) Put(key, value []byte, wo *store.WriteOptions) error { - ret := m.ctrl.Call(m, "Put", key, value, wo) - ret0, _ := ret[0].(error) - return ret0 -} - -// Put indicates an expected call of Put -func (mr *MockStoreMockRecorder) Put(key, value, wo interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Put", reflect.TypeOf((*MockStore)(nil).Put), key, value, wo) -} - -// Close mocks base method -func (m *MockStore) Close() error { - ret := m.ctrl.Call(m, "Close") - ret0, _ := ret[0].(error) - return ret0 -} - -// Close indicates an expected call of Close -func (mr *MockStoreMockRecorder) Close() *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockStore)(nil).Close)) -} diff --git a/infrastructure/store/store.go b/infrastructure/store/store.go deleted file mode 100644 index c14e9d0b..00000000 --- a/infrastructure/store/store.go +++ /dev/null @@ -1,25 +0,0 @@ -package store - -import ( - leveldb_errors "github.com/syndtr/goleveldb/leveldb/errors" - "github.com/syndtr/goleveldb/leveldb/opt" -) - -var ( - // NotFoundError is a leveldb/errors.ErrNotFound - NotFoundError = leveldb_errors.ErrNotFound -) - -// ReadOptions is a type alias of leveldb/opt.ReadOptions -type ReadOptions = opt.ReadOptions - -// WriteOptions is a type alias of leveldb/opt.WriteOptions -type WriteOptions = opt.WriteOptions - -// Store is a interface represents key-value store. -type Store interface { - Get(key []byte, ro *ReadOptions) (value []byte, err error) - Has(key []byte, ro *ReadOptions) (ret bool, err error) - Put(key, value []byte, wo *WriteOptions) error - Close() error -} diff --git a/presentation/controller/health.go b/presentation/controller/health.go deleted file mode 100644 index 69707db7..00000000 --- a/presentation/controller/health.go +++ /dev/null @@ -1,20 +0,0 @@ -package controller - -import ( - "github.com/duck8823/duci/application/service/docker" - "net/http" -) - -// HealthController is a handler of health check. -type HealthController struct { - Docker docker.Service -} - -// ServeHTTP responses a server status -func (c *HealthController) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if err := c.Docker.Status(); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - w.WriteHeader(http.StatusOK) -} diff --git a/presentation/controller/health_test.go b/presentation/controller/health_test.go deleted file mode 100644 index 7f87c34c..00000000 --- a/presentation/controller/health_test.go +++ /dev/null @@ -1,71 +0,0 @@ -package controller_test - -import ( - "github.com/duck8823/duci/application/service/docker/mock_docker" - "github.com/duck8823/duci/presentation/controller" - "github.com/golang/mock/gomock" - "github.com/pkg/errors" - "net/http/httptest" - "testing" -) - -func TestHealthCheckController_ServeHTTP(t *testing.T) { - t.Run("without error", func(t *testing.T) { - // given - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - mockService := mock_docker.NewMockService(ctrl) - mockService.EXPECT(). - Status(). - Return(nil) - - handler := &controller.HealthController{Docker: mockService} - - // and - s := httptest.NewServer(handler) - defer s.Close() - - // and - req := httptest.NewRequest("GET", "/health", nil) - rec := httptest.NewRecorder() - - // when - handler.ServeHTTP(rec, req) - - // then - if rec.Code != 200 { - t.Errorf("status code must be 200, but got %+v", rec.Code) - } - }) - - t.Run("with error", func(t *testing.T) { - // given - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - mockService := mock_docker.NewMockService(ctrl) - mockService.EXPECT(). - Status(). - Return(errors.New("test")) - - handler := &controller.HealthController{Docker: mockService} - - // and - s := httptest.NewServer(handler) - defer s.Close() - - // and - req := httptest.NewRequest("GET", "/health", nil) - rec := httptest.NewRecorder() - - // when - handler.ServeHTTP(rec, req) - - // then - if rec.Code != 500 { - t.Errorf("status code must be 500, but got %+v", rec.Code) - } - }) - -} diff --git a/presentation/controller/logs.go b/presentation/controller/logs.go deleted file mode 100644 index ff15cc5d..00000000 --- a/presentation/controller/logs.go +++ /dev/null @@ -1,59 +0,0 @@ -package controller - -import ( - "encoding/json" - "fmt" - "github.com/duck8823/duci/application/service/logstore" - "github.com/duck8823/duci/data/model" - "github.com/go-chi/chi" - "github.com/google/uuid" - "github.com/pkg/errors" - "net/http" -) - -// LogController is a handler of stored log. -type LogController struct { - LogStore logstore.Service -} - -// ServeHTTP responses a log of specific uuid. -func (c *LogController) ServeHTTP(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Access-Control-Allow-Origin", "*") - flusher, ok := w.(http.Flusher) - if !ok { - http.Error(w, "Streaming unsupported!", http.StatusInternalServerError) - return - } - - id, err := uuid.Parse(chi.URLParam(r, "uuid")) - if err != nil { - http.Error(w, fmt.Sprintf("Error occurred: %s", err.Error()), http.StatusInternalServerError) - return - } - - if err := c.logs(w, flusher, id); err != nil { - http.Error(w, fmt.Sprintf("Sorry, Error occurred: %s", err.Error()), http.StatusInternalServerError) - return - } -} - -func (c *LogController) logs(w http.ResponseWriter, f http.Flusher, id uuid.UUID) error { - var read int - var job *model.Job - var err error - for { - job, err = c.LogStore.Get(id) - if err != nil { - return errors.WithStack(err) - } - for _, msg := range job.Stream[read:] { - json.NewEncoder(w).Encode(msg) - f.Flush() - read++ - } - if job.Finished { - break - } - } - return nil -} diff --git a/presentation/controller/logs_test.go b/presentation/controller/logs_test.go deleted file mode 100644 index c96ae0ef..00000000 --- a/presentation/controller/logs_test.go +++ /dev/null @@ -1,119 +0,0 @@ -package controller_test - -import ( - ctx "context" - "github.com/duck8823/duci/application/service/logstore/mock_logstore" - "github.com/duck8823/duci/data/model" - "github.com/duck8823/duci/presentation/controller" - "github.com/go-chi/chi" - "github.com/golang/mock/gomock" - "github.com/google/uuid" - "github.com/pkg/errors" - "net/http/httptest" - "testing" - "time" -) - -func TestLogsController_ServeHTTP(t *testing.T) { - t.Run("with valid uuid", func(t *testing.T) { - // setup - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - mockService := mock_logstore.NewMockService(ctrl) - handler := &controller.LogController{LogStore: mockService} - - // given - id, err := uuid.NewRandom() - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - - t.Run("when service returns error", func(t *testing.T) { - // and - mockService.EXPECT(). - Get(gomock.Eq(id)). - Return(nil, errors.New("hello error")) - - // and - s := httptest.NewServer(handler) - defer s.Close() - - // and - chiCtx := chi.NewRouteContext() - chiCtx.URLParams.Add("uuid", id.String()) - - req := httptest.NewRequest("GET", "/", nil). - WithContext(ctx.WithValue(ctx.Background(), chi.RouteCtxKey, chiCtx)) - rec := httptest.NewRecorder() - - // when - handler.ServeHTTP(rec, req) - - // then - if rec.Code != 500 { - t.Errorf("status must equal %+v, but got %+v", 500, rec.Code) - } - }) - - t.Run("when service returns correct job", func(t *testing.T) { - // and - job := &model.Job{ - Finished: true, - Stream: []model.Message{{ - Time: time.Now(), - Text: "Hello World", - }}, - } - - mockService.EXPECT(). - Get(gomock.Eq(id)). - Return(job, nil) - - // and - s := httptest.NewServer(handler) - defer s.Close() - - // and - chiCtx := chi.NewRouteContext() - chiCtx.URLParams.Add("uuid", id.String()) - - req := httptest.NewRequest("GET", "/", nil). - WithContext(ctx.WithValue(ctx.Background(), chi.RouteCtxKey, chiCtx)) - rec := httptest.NewRecorder() - - // when - handler.ServeHTTP(rec, req) - - // then - if rec.Code != 200 { - t.Errorf("status must equal %+v, but got %+v", 200, rec.Code) - } - }) - }) - - t.Run("with invalid uuid", func(t *testing.T) { - // setup - handler := &controller.LogController{} - - // given - s := httptest.NewServer(handler) - defer s.Close() - - // and - chiCtx := chi.NewRouteContext() - chiCtx.URLParams.Add("uuid", "invalid_uuid") - - req := httptest.NewRequest("GET", "/", nil). - WithContext(ctx.WithValue(ctx.Background(), chi.RouteCtxKey, chiCtx)) - rec := httptest.NewRecorder() - - // when - handler.ServeHTTP(rec, req) - - // then - if rec.Code != 500 { - t.Errorf("status must equal %+v, but got %+v", 500, rec.Code) - } - }) -} diff --git a/presentation/controller/webhooks.go b/presentation/controller/webhooks.go deleted file mode 100644 index 72824a8a..00000000 --- a/presentation/controller/webhooks.go +++ /dev/null @@ -1,176 +0,0 @@ -package controller - -import ( - "encoding/json" - "fmt" - "github.com/duck8823/duci/application" - "github.com/duck8823/duci/application/context" - "github.com/duck8823/duci/application/service/github" - "github.com/duck8823/duci/application/service/runner" - "github.com/duck8823/duci/infrastructure/logger" - go_github "github.com/google/go-github/github" - "github.com/google/uuid" - "github.com/pkg/errors" - "gopkg.in/src-d/go-git.v4/plumbing" - "net/http" - "net/url" - "regexp" - "strings" -) - -// ErrSkipBuild is a error of build skip. -var ErrSkipBuild = errors.New("build skip") - -// WebhooksController is a handler of webhook. -type WebhooksController struct { - Runner runner.Runner - GitHub github.Service -} - -// Command represents docker command. -type Command []string - -// ServeHTTP receive webhook. -func (c *WebhooksController) ServeHTTP(w http.ResponseWriter, r *http.Request) { - requestID, err := requestID(r) - if err != nil { - logger.Error(requestID, err.Error()) - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - - // Trigger build - githubEvent := r.Header.Get("X-GitHub-Event") - switch githubEvent { - case "issue_comment": - c.runWithIssueCommentEvent(requestID, w, r) - case "push": - c.runWithPushEvent(requestID, w, r) - default: - message := fmt.Sprintf("payload event type must be issue_comment or push. but %s", githubEvent) - logger.Error(requestID, message) - http.Error(w, message, http.StatusInternalServerError) - return - } - - // Response - w.WriteHeader(http.StatusOK) -} - -func (c *WebhooksController) runWithIssueCommentEvent(requestID uuid.UUID, w http.ResponseWriter, r *http.Request) { - ctx, src, command, err := c.parseIssueComment(requestID, r) - if err == ErrSkipBuild { - logger.Info(requestID, "skip build") - w.WriteHeader(http.StatusOK) - w.Write([]byte(err.Error())) - return - } else if err != nil { - logger.Errorf(requestID, "%+v", err) - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - go c.run(ctx, src, command...) -} - -func (c *WebhooksController) parseIssueComment(requestID uuid.UUID, r *http.Request) (context.Context, *github.TargetSource, Command, error) { - event := &go_github.IssueCommentEvent{} - if err := json.NewDecoder(r.Body).Decode(event); err != nil { - return nil, nil, nil, errors.WithStack(err) - } - - cmd, err := command(event) - if err != nil { - return nil, nil, nil, errors.Cause(err) - } - ctx := context.New(fmt.Sprintf("%s/pr/%s", application.Name, cmd[0]), requestID, runtimeURL(r)) - - src, err := c.targetSource(ctx, *event) - if err != nil { - return nil, nil, nil, errors.WithStack(err) - } - - return ctx, src, cmd, err -} - -func (c *WebhooksController) targetSource(ctx context.Context, event go_github.IssueCommentEvent) (*github.TargetSource, error) { - pr, err := c.GitHub.GetPullRequest(ctx, event.GetRepo(), event.GetIssue().GetNumber()) - if err != nil { - return nil, errors.WithStack(err) - } - - src := &github.TargetSource{ - Repo: event.GetRepo(), - Ref: fmt.Sprintf("refs/heads/%s", pr.GetHead().GetRef()), - SHA: plumbing.NewHash(pr.GetHead().GetSHA()), - } - return src, nil -} - -func (c *WebhooksController) runWithPushEvent(requestID uuid.UUID, w http.ResponseWriter, r *http.Request) { - event := &go_github.PushEvent{} - if err := json.NewDecoder(r.Body).Decode(event); err != nil { - logger.Errorf(requestID, "%+v", err) - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - sha := event.GetHeadCommit().GetID() - if len(sha) == 0 { - logger.Info(requestID, "skip build: could not get head commit") - w.WriteHeader(http.StatusOK) - w.Write([]byte("skip build")) - return - } - - ctx := context.New(fmt.Sprintf("%s/push", application.Name), requestID, runtimeURL(r)) - go c.run(ctx, &github.TargetSource{Repo: event.GetRepo(), Ref: event.GetRef(), SHA: plumbing.NewHash(sha)}) -} - -func (c *WebhooksController) run(ctx context.Context, src *github.TargetSource, cmd ...string) { - if err := c.Runner.Run(ctx, src); err != nil { - logger.Errorf(ctx.UUID(), "error occur: %+v", err) - } -} - -func requestID(r *http.Request) (uuid.UUID, error) { - deliveryID := go_github.DeliveryID(r) - requestID, err := uuid.Parse(deliveryID) - if err != nil { - msg := fmt.Sprintf("Error: invalid request header `X-GitHub-Delivery`: %+v", deliveryID) - return uuid.New(), errors.Wrap(err, msg) - } - return requestID, nil -} - -func runtimeURL(r *http.Request) *url.URL { - runtimeURL := &url.URL{ - Scheme: "http", - Host: r.Host, - Path: r.URL.Path, - } - if r.URL.Scheme != "" { - runtimeURL.Scheme = r.URL.Scheme - } - return runtimeURL -} - -func command(event *go_github.IssueCommentEvent) (Command, error) { - if !isValidAction(event.Action) { - return Command{}, ErrSkipBuild - } - - if !regexp.MustCompile("^ci\\s+[^\\s]+").Match([]byte(event.Comment.GetBody())) { - return Command{}, ErrSkipBuild - } - phrase := regexp.MustCompile("^ci\\s+").ReplaceAllString(event.Comment.GetBody(), "") - command := strings.Split(phrase, " ") - return command, nil -} - -func isValidAction(action *string) bool { - if action == nil { - return false - } - return *action == "created" || *action == "edited" -} diff --git a/presentation/controller/webhooks_test.go b/presentation/controller/webhooks_test.go deleted file mode 100644 index d9174c12..00000000 --- a/presentation/controller/webhooks_test.go +++ /dev/null @@ -1,390 +0,0 @@ -package controller_test - -import ( - "bytes" - "encoding/json" - "github.com/duck8823/duci/application/service/github/mock_github" - "github.com/duck8823/duci/application/service/runner/mock_runner" - "github.com/duck8823/duci/presentation/controller" - "github.com/golang/mock/gomock" - "github.com/google/go-github/github" - "github.com/google/uuid" - "github.com/pkg/errors" - "io" - "net/http/httptest" - "strings" - "testing" -) - -func TestWebhooksController_ServeHTTP(t *testing.T) { - // setup - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - t.Run("with correct payload", func(t *testing.T) { - // given - requestID, _ := uuid.NewRandom() - - t.Run("when issue_comment", func(t *testing.T) { - // given - event := "issue_comment" - - t.Run("when github service returns no error", func(t *testing.T) { - // given - runner := mock_runner.NewMockRunner(ctrl) - runner.EXPECT().Run(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() - - githubService := mock_github.NewMockService(ctrl) - githubService.EXPECT().GetPullRequest(gomock.Any(), gomock.Any(), gomock.Any()). - AnyTimes(). - Return(&github.PullRequest{ - Head: &github.PullRequestBranch{ - SHA: new(string), - }, - }, nil) - githubService.EXPECT().CreateCommitStatus(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - - // and - handler := &controller.WebhooksController{Runner: runner, GitHub: githubService} - - s := httptest.NewServer(handler) - defer s.Close() - - t.Run("with valid action", func(t *testing.T) { - actions := []string{"created", "edited"} - for _, action := range actions { - // and - payload := createIssueCommentPayload(t, action, "ci test") - - req := httptest.NewRequest("POST", "/", payload) - req.Header.Set("X-GitHub-Delivery", requestID.String()) - req.Header.Set("X-GitHub-Event", event) - rec := httptest.NewRecorder() - - // when - handler.ServeHTTP(rec, req) - - // then - if rec.Code != 200 { - t.Errorf("status must equal %+v, but got %+v", 200, rec.Code) - } - } - }) - - t.Run("with invalid action", func(t *testing.T) { - actions := []string{"deleted", "foo", ""} - for _, action := range actions { - t.Run(action, func(t *testing.T) { - // given - body := createIssueCommentPayload(t, action, "ci test") - - // and - req := httptest.NewRequest("POST", "/", body) - req.Header.Set("X-GitHub-Delivery", requestID.String()) - req.Header.Set("X-GitHub-Event", event) - rec := httptest.NewRecorder() - - // when - handler.ServeHTTP(rec, req) - - // then - if rec.Code != 200 { - t.Errorf("status must equal %+v, but got %+v", 200, rec.Code) - } - - if rec.Body.String() != "build skip" { - t.Errorf("body must equal %+v, but got %+v", "build skip", rec.Body.String()) - } - }) - } - }) - }) - - t.Run("when github service return error", func(t *testing.T) { - // given - runner := mock_runner.NewMockRunner(ctrl) - runner.EXPECT().Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(0) - - githubService := mock_github.NewMockService(ctrl) - githubService.EXPECT().GetPullRequest(gomock.Any(), gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil, errors.New("error occur")) - githubService.EXPECT().CreateCommitStatus(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - - // and - handler := &controller.WebhooksController{Runner: runner, GitHub: githubService} - - s := httptest.NewServer(handler) - defer s.Close() - - // and - payload := createIssueCommentPayload(t, "created", "ci test") - - req := httptest.NewRequest("POST", "/", payload) - req.Header.Set("X-GitHub-Delivery", requestID.String()) - req.Header.Set("X-GitHub-Event", event) - rec := httptest.NewRecorder() - - // when - handler.ServeHTTP(rec, req) - - // then - if rec.Code != 500 { - t.Errorf("status must equal %+v, but got %+v", 500, rec.Code) - } - }) - }) - - t.Run("when push", func(t *testing.T) { - // setup - githubService := mock_github.NewMockService(ctrl) - githubService.EXPECT().GetPullRequest(gomock.Any(), gomock.Any(), gomock.Any()). - AnyTimes(). - Return(&github.PullRequest{ - Head: &github.PullRequestBranch{ - SHA: new(string), - }, - }, nil) - githubService.EXPECT().CreateCommitStatus(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - - t.Run("with head_commit.id", func(t *testing.T) { - // given - runner := mock_runner.NewMockRunner(ctrl) - runner.EXPECT().Run(gomock.Any(), gomock.Any()).Times(1) - - // and - handler := &controller.WebhooksController{Runner: runner, GitHub: githubService} - - s := httptest.NewServer(handler) - defer s.Close() - - // and - payload := createPushPayload(t, "test/repo", "master", "sha") - - req := httptest.NewRequest("POST", "/", payload) - req.Header.Set("X-GitHub-Delivery", requestID.String()) - req.Header.Set("X-GitHub-Event", "push") - rec := httptest.NewRecorder() - - // when - handler.ServeHTTP(rec, req) - - // then - if rec.Code != 200 { - t.Errorf("status must equal %+v, but got %+v", 200, rec.Code) - } - }) - - t.Run("without head_commit.id", func(t *testing.T) { - // given - runner := mock_runner.NewMockRunner(ctrl) - runner.EXPECT().Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(0) - - // and - handler := &controller.WebhooksController{Runner: runner, GitHub: githubService} - - s := httptest.NewServer(handler) - defer s.Close() - - // and - payload := createPushPayload(t, "test/repo", "master", "") - - req := httptest.NewRequest("POST", "/", payload) - req.Header.Set("X-GitHub-Delivery", requestID.String()) - req.Header.Set("X-GitHub-Event", "push") - rec := httptest.NewRecorder() - - // when - handler.ServeHTTP(rec, req) - - // then - if rec.Code != 200 { - t.Errorf("status must equal %+v, but got %+v", 200, rec.Code) - } - }) - }) - }) - - t.Run("with invalid payload", func(t *testing.T) { - // setup - runner := mock_runner.NewMockRunner(ctrl) - runner.EXPECT().Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(0) - - // and - githubService := mock_github.NewMockService(ctrl) - githubService.EXPECT().GetPullRequest(gomock.Any(), gomock.Any(), gomock.Any()). - AnyTimes(). - Return(&github.PullRequest{ - Head: &github.PullRequestBranch{ - SHA: new(string), - }, - }, nil) - githubService.EXPECT().CreateCommitStatus(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - AnyTimes(). - Return(nil) - - // and - handler := &controller.WebhooksController{Runner: runner, GitHub: githubService} - - s := httptest.NewServer(handler) - defer s.Close() - - t.Run("with invalid `X-GitHub-Event` header", func(t *testing.T) { - // given - body := createIssueCommentPayload(t, "created", "ci test") - - // and - requestID, _ := uuid.NewRandom() - - req := httptest.NewRequest("POST", "/", body) - req.Header.Set("X-GitHub-Delivery", requestID.String()) - req.Header.Set("X-GitHub-Event", "hogefuga") - rec := httptest.NewRecorder() - - // when - handler.ServeHTTP(rec, req) - - // then - if rec.Code != 500 { - t.Errorf("status must equal %+v, but got %+v", 500, rec.Code) - } - }) - - t.Run("with invalid `X-GitHub-Delivery` header", func(t *testing.T) { - // given - body := createIssueCommentPayload(t, "created", "ci test") - - // and - req := httptest.NewRequest("POST", "/", body) - req.Header.Set("X-GitHub-Delivery", "hogefuga") - req.Header.Set("X-GitHub-Event", "push") - rec := httptest.NewRecorder() - - // when - handler.ServeHTTP(rec, req) - - // then - if rec.Code != 400 { - t.Errorf("status must equal %+v, but got %+v", 400, rec.Code) - } - }) - - t.Run("with issue_comment", func(t *testing.T) { - // given - event := "issue_comment" - requestID, _ := uuid.NewRandom() - - t.Run("without comment started ci", func(t *testing.T) { - // given - body := createIssueCommentPayload(t, "created", "test") - - // and - req := httptest.NewRequest("POST", "/", body) - req.Header.Set("X-GitHub-Delivery", requestID.String()) - req.Header.Set("X-GitHub-Event", event) - rec := httptest.NewRecorder() - - // when - handler.ServeHTTP(rec, req) - - // then - if rec.Code != 200 { - t.Errorf("status must equal %+v, but got %+v", 200, rec.Code) - } - - if rec.Body.String() != "build skip" { - t.Errorf("body must equal %+v, but got %+v", "build skip", rec.Body.String()) - } - }) - - t.Run("with invalid body", func(t *testing.T) { - // given - body := strings.NewReader("Invalid JSON format.") - - // and - req := httptest.NewRequest("POST", "/", body) - req.Header.Set("X-GitHub-Delivery", requestID.String()) - req.Header.Set("X-GitHub-Event", event) - rec := httptest.NewRecorder() - - // when - handler.ServeHTTP(rec, req) - - // then - if rec.Code != 500 { - t.Errorf("status must equal %+v, but got %+v", 500, rec.Code) - } - }) - }) - - t.Run("with push", func(t *testing.T) { - // given - event := "push" - requestID, _ := uuid.NewRandom() - - t.Run("with invalid body", func(t *testing.T) { - // given - body := strings.NewReader("Invalid JSON format.") - - // and - req := httptest.NewRequest("POST", "/", body) - req.Header.Set("X-GitHub-Delivery", requestID.String()) - req.Header.Set("X-GitHub-Event", event) - rec := httptest.NewRecorder() - - // when - handler.ServeHTTP(rec, req) - - // then - if rec.Code != 500 { - t.Errorf("status must equal %+v, but got %+v", 500, rec.Code) - } - }) - }) - }) -} - -func createIssueCommentPayload(t *testing.T, action, comment string) io.Reader { - t.Helper() - - event := &github.IssueCommentEvent{ - Repo: &github.Repository{}, - Action: &action, - Issue: &github.Issue{ - Number: new(int), - }, - Comment: &github.IssueComment{ - Body: &comment, - }, - } - payload, err := json.Marshal(event) - if err != nil { - t.Fatalf("error occurred. %+v", err) - } - return bytes.NewReader(payload) -} - -func createPushPayload(t *testing.T, repoName, ref string, sha string) io.Reader { - t.Helper() - - event := github.PushEvent{ - Repo: &github.PushEventRepository{ - FullName: &repoName, - }, - Ref: &ref, - HeadCommit: &github.PushEventCommit{ - ID: &sha, - }, - } - payload, err := json.Marshal(event) - if err != nil { - t.Fatalf("error occurred: %+v", err) - } - return bytes.NewReader(payload) -} diff --git a/presentation/router/router.go b/presentation/router/router.go index 48a5f7f9..49dec31a 100644 --- a/presentation/router/router.go +++ b/presentation/router/router.go @@ -6,11 +6,11 @@ import ( "github.com/duck8823/duci/application" "github.com/duck8823/duci/application/service/executor" "github.com/duck8823/duci/application/service/job" - "github.com/duck8823/duci/application/service/runner" "github.com/duck8823/duci/domain/model/docker" "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/job/target/git" "github.com/duck8823/duci/domain/model/job/target/github" + "github.com/duck8823/duci/domain/model/runner" health_controller "github.com/duck8823/duci/presentation/controller/health" job_controller "github.com/duck8823/duci/presentation/controller/job" webhook_controller "github.com/duck8823/duci/presentation/controller/webhook" From 318322dc2bc184ce6f5c1b98b21ad466d612f63f Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 8 Dec 2018 07:13:02 +0900 Subject: [PATCH 041/135] Change repository api --- application/service/job/job.go | 34 ++++++++++++++-- domain/model/job/job.go | 11 +---- domain/model/job/repository.go | 10 +++-- infrastructure/job/data_source.go | 68 +++++-------------------------- 4 files changed, 47 insertions(+), 76 deletions(-) diff --git a/application/service/job/job.go b/application/service/job/job.go index b7bfa9d5..e5031910 100644 --- a/application/service/job/job.go +++ b/application/service/job/job.go @@ -28,7 +28,7 @@ func New() (Service, error) { } func (s *serviceImpl) FindBy(id ID) (*Job, error) { - job, err := s.repo.Get(id) + job, err := s.repo.FindBy(id) if err != nil { return nil, errors.WithStack(err) } @@ -36,22 +36,48 @@ func (s *serviceImpl) FindBy(id ID) (*Job, error) { } func (s *serviceImpl) Start(id ID) error { - if err := s.repo.Start(id); err != nil { + job := Job{ID: id, Finished: false} + if err := s.repo.Save(job); err != nil { return errors.WithStack(err) } return nil } func (s *serviceImpl) Append(id ID, line LogLine) error { - if err := s.repo.Append(id, line); err != nil { + job, err := s.findOrInitialize(id) + if err != nil { + return errors.WithStack(err) + } + job.AppendLog(line) + + if err := s.repo.Save(*job); err != nil { return errors.WithStack(err) } + return nil } +func (s *serviceImpl) findOrInitialize(id ID) (*Job, error) { + job, err := s.repo.FindBy(id) + if err == NotFound { + return &Job{ID: id, Finished: false}, nil + } else if err != nil { + return nil, errors.WithStack(err) + } + + return job, nil +} + func (s *serviceImpl) Finish(id ID) error { - if err := s.repo.Finish(id); err != nil { + job, err := s.repo.FindBy(id) + if err != nil { return errors.WithStack(err) } + job.Finish() + + if err := s.repo.Save(*job); err != nil { + return errors.WithStack(err) + } + return nil } diff --git a/domain/model/job/job.go b/domain/model/job/job.go index 034f88c1..147f59c6 100644 --- a/domain/model/job/job.go +++ b/domain/model/job/job.go @@ -1,7 +1,6 @@ package job import ( - "bytes" "encoding/json" "github.com/google/uuid" "github.com/pkg/errors" @@ -9,6 +8,7 @@ import ( // Job represents a task type Job struct { + ID ID Finished bool `json:"finished"` Stream []LogLine `json:"stream"` } @@ -32,15 +32,6 @@ func (j *Job) ToBytes() ([]byte, error) { return data, nil } -// NewJob returns unmarshal Job instance -func NewJob(data []byte) (*Job, error) { - job := &Job{} - if err := json.NewDecoder(bytes.NewReader(data)).Decode(job); err != nil { - return nil, errors.WithStack(err) - } - return job, nil -} - // ID is the identifier of job type ID uuid.UUID diff --git a/domain/model/job/repository.go b/domain/model/job/repository.go index 81148f55..072c8568 100644 --- a/domain/model/job/repository.go +++ b/domain/model/job/repository.go @@ -1,9 +1,11 @@ package job +import "errors" + +var NotFound = errors.New("job not found") + // Repository is Job Repository type Repository interface { - Get(ID) (*Job, error) - Start(ID) error - Append(ID, LogLine) error - Finish(ID) error + FindBy(ID) (*Job, error) + Save(Job) error } diff --git a/infrastructure/job/data_source.go b/infrastructure/job/data_source.go index ee14bf2e..afa02511 100644 --- a/infrastructure/job/data_source.go +++ b/infrastructure/job/data_source.go @@ -1,6 +1,8 @@ package job import ( + "bytes" + "encoding/json" . "github.com/duck8823/duci/domain/model/job" "github.com/pkg/errors" "github.com/syndtr/goleveldb/leveldb" @@ -18,78 +20,28 @@ func NewDataSource(path string) (*dataSource, error) { return &dataSource{db}, nil } -func (d *dataSource) Get(id ID) (*Job, error) { - data, err := d.db.Get(id.ToSlice(), nil) - if err != nil { - return nil, errors.WithStack(err) - } - - job, err := NewJob(data) - if err != nil { - return nil, errors.WithStack(err) - } - return job, nil -} - -func (d *dataSource) Start(id ID) error { - data, _ := (&Job{Finished: false}).ToBytes() - if err := d.db.Put(id.ToSlice(), data, nil); err != nil { - return errors.WithStack(err) - } - return nil -} - -func (d *dataSource) Append(id ID, line LogLine) error { - job, err := d.findOrInitialize(id) - if err != nil { - return errors.WithStack(err) - } - - job.AppendLog(line) - - data, err := job.ToBytes() - if err != nil { - return errors.WithStack(err) - } - if err := d.db.Put(id.ToSlice(), data, nil); err != nil { - return errors.WithStack(err) - } - return nil -} - -func (d *dataSource) findOrInitialize(id ID) (*Job, error) { +func (d *dataSource) FindBy(id ID) (*Job, error) { data, err := d.db.Get(id.ToSlice(), nil) if err == leveldb.ErrNotFound { - return &Job{}, nil + return nil, NotFound } else if err != nil { return nil, errors.WithStack(err) } - job, err := NewJob(data) - if err != nil { + job := &Job{} + if err := json.NewDecoder(bytes.NewReader(data)).Decode(job); err != nil { return nil, errors.WithStack(err) } + job.ID = id return job, nil } -func (d *dataSource) Finish(id ID) error { - data, err := d.db.Get(id.ToSlice(), nil) - if err != nil { - return errors.WithStack(err) - } - - job, err := NewJob(data) - if err != nil { - return errors.WithStack(err) - } - - job.Finish() - - finished, err := job.ToBytes() +func (d *dataSource) Save(job Job) error { + data, err := job.ToBytes() if err != nil { return errors.WithStack(err) } - if err := d.db.Put(id.ToSlice(), finished, nil); err != nil { + if err := d.db.Put(job.ID.ToSlice(), data, nil); err != nil { return errors.WithStack(err) } return nil From 5a8eec37647576d5380a982a9fc3de4b9edf9462 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 8 Dec 2018 07:22:53 +0900 Subject: [PATCH 042/135] Change type of build job --- application/context.go | 10 +++++----- presentation/controller/webhook/helper.go | 7 ++++--- presentation/router/router.go | 17 +++++++---------- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/application/context.go b/application/context.go index a1e86b3c..04d79830 100644 --- a/application/context.go +++ b/application/context.go @@ -3,15 +3,15 @@ package application import ( "context" "fmt" + "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/job/target/github" - "github.com/google/uuid" "net/url" ) var ctxKey = "duci_job" type BuildJob struct { - ID uuid.UUID + ID job.ID TargetSource *github.TargetSource TaskName string TargetURL *url.URL @@ -24,9 +24,9 @@ func ContextWithJob(parent context.Context, job *BuildJob) context.Context { // BuildJobFromContext extract BuildJob from context func BuildJobFromContext(ctx context.Context) (*BuildJob, error) { - job := ctx.Value(ctxKey) - if job == nil { + val := ctx.Value(ctxKey) + if val == nil { return nil, fmt.Errorf("context value '%s' should not be null", ctxKey) } - return ctx.Value(ctxKey).(*BuildJob), nil + return val.(*BuildJob), nil } diff --git a/presentation/controller/webhook/helper.go b/presentation/controller/webhook/helper.go index 6126fdd7..cdc2fd86 100644 --- a/presentation/controller/webhook/helper.go +++ b/presentation/controller/webhook/helper.go @@ -3,6 +3,7 @@ package webhook import ( "context" "fmt" + "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/job/target/github" go_github "github.com/google/go-github/github" "github.com/google/uuid" @@ -11,14 +12,14 @@ import ( "net/url" ) -func reqID(r *http.Request) (uuid.UUID, error) { +func reqID(r *http.Request) (job.ID, error) { deliveryID := go_github.DeliveryID(r) requestID, err := uuid.Parse(deliveryID) if err != nil { msg := fmt.Sprintf("Error: invalid request header `X-GitHub-Delivery`: %+v", deliveryID) - return uuid.New(), errors.Wrap(err, msg) + return job.ID{}, errors.Wrap(err, msg) } - return requestID, nil + return job.ID(requestID), nil } func targetURL(r *http.Request) *url.URL { diff --git a/presentation/router/router.go b/presentation/router/router.go index 49dec31a..4a438889 100644 --- a/presentation/router/router.go +++ b/presentation/router/router.go @@ -50,13 +50,12 @@ func New() (http.Handler, error) { Executor: executor.DefaultExecutorBuilder(). StartFunc(func(ctx context.Context) { buildJob, err := application.BuildJobFromContext(ctx) - id := job.ID(buildJob.ID) if err != nil { - _ = jobService.Append(id, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) + _ = jobService.Append(buildJob.ID, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) return } - if err := jobService.Start(id); err != nil { - _ = jobService.Append(id, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) + if err := jobService.Start(buildJob.ID); err != nil { + _ = jobService.Append(buildJob.ID, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) return } _ = gh.CreateCommitStatus(ctx, github.CommitStatus{ @@ -69,24 +68,22 @@ func New() (http.Handler, error) { }). LogFunc(func(ctx context.Context, log job.Log) { buildJob, err := application.BuildJobFromContext(ctx) - id := job.ID(buildJob.ID) if err != nil { - _ = jobService.Append(id, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) + _ = jobService.Append(buildJob.ID, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) return } for line, err := log.ReadLine(); err == nil; line, err = log.ReadLine() { println(line.Message) - _ = jobService.Append(id, *line) + _ = jobService.Append(buildJob.ID, *line) } }). EndFunc(func(ctx context.Context, e error) { buildJob, err := application.BuildJobFromContext(ctx) - id := job.ID(buildJob.ID) if err != nil { - _ = jobService.Append(id, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) + _ = jobService.Append(buildJob.ID, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) return } - if err := jobService.Finish(id); err != nil { + if err := jobService.Finish(buildJob.ID); err != nil { println(fmt.Sprintf("%+v", err)) return } From d1a5c576f1d2f01c6dd6c3d14a424525f5151856 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 8 Dec 2018 09:24:40 +0900 Subject: [PATCH 043/135] Run asynchronously --- presentation/controller/webhook/handler.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/presentation/controller/webhook/handler.go b/presentation/controller/webhook/handler.go index ce92f183..b28bf488 100644 --- a/presentation/controller/webhook/handler.go +++ b/presentation/controller/webhook/handler.go @@ -111,13 +111,10 @@ func (h *Handler) IssueCommentEvent(w http.ResponseWriter, r *http.Request) { TargetURL: targetURL(r), }) - if err := h.Executor.Execute(ctx, &target.GitHubPush{ + go h.Executor.Execute(ctx, &target.GitHubPush{ Repo: event.GetRepo(), Point: pnt, - }, phrase.Command()...); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } + }, phrase.Command()...) w.WriteHeader(http.StatusOK) } From 1de7127b415ff6de757bd24c9e0cd5bd7fdf3c5c Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sun, 9 Dec 2018 16:04:37 +0900 Subject: [PATCH 044/135] Add application initialize --- application/cmd/server.go | 7 +++++++ application/config.go | 5 +++++ application/initialize.go | 29 +++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 application/initialize.go diff --git a/application/cmd/server.go b/application/cmd/server.go index 13c6db1a..4d779e30 100644 --- a/application/cmd/server.go +++ b/application/cmd/server.go @@ -1,6 +1,7 @@ package cmd import ( + "fmt" "github.com/duck8823/duci/application" "github.com/duck8823/duci/application/semaphore" "github.com/duck8823/duci/presentation/router" @@ -25,6 +26,12 @@ var ( func runServer(cmd *cobra.Command, _ []string) { readConfiguration(cmd) + if err := application.Initialize(); err != nil { + println(fmt.Sprintf("Failed to initialize a semaphore.\n%+v", err)) + os.Exit(1) + return + } + if err := semaphore.Make(); err != nil { println("Failed to initialize a semaphore.\n%+v", err) os.Exit(1) diff --git a/application/config.go b/application/config.go index 4cf98726..ee60165b 100644 --- a/application/config.go +++ b/application/config.go @@ -31,6 +31,11 @@ func (s maskString) MarshalJSON() ([]byte, error) { return []byte(`"***"`), nil } +// ToString returns unmasked string. +func (s maskString) ToString() string { + return string(s) +} + // Configuration of application. type Configuration struct { Server *Server `yaml:"server" json:"server"` diff --git a/application/initialize.go b/application/initialize.go new file mode 100644 index 00000000..3c24753e --- /dev/null +++ b/application/initialize.go @@ -0,0 +1,29 @@ +package application + +import ( + "context" + "github.com/duck8823/duci/application/service/job" + "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/job/target/git" + "github.com/duck8823/duci/domain/model/job/target/github" + "github.com/pkg/errors" +) + +func Initialize() error { + if err := git.InitializeWithHTTP(func(ctx context.Context, log job.Log) { + for line, err := log.ReadLine(); err == nil; line, err = log.ReadLine() { + println(line.Message) + } + }); err != nil { + return errors.WithStack(err) + } + + if err := github.Initialize(Config.GitHub.APIToken.ToString()); err != nil { + return errors.WithStack(err) + } + + if err := job_service.Initialize(Config.Server.DatabasePath); err != nil { + return errors.WithStack(err) + } + return nil +} From d15fc04acbd0d153d3ef1a7ee189c59bd7a44c99 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sun, 9 Dec 2018 16:04:53 +0900 Subject: [PATCH 045/135] Fix print message --- application/cmd/server.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/application/cmd/server.go b/application/cmd/server.go index 4d779e30..4edb1428 100644 --- a/application/cmd/server.go +++ b/application/cmd/server.go @@ -33,21 +33,21 @@ func runServer(cmd *cobra.Command, _ []string) { } if err := semaphore.Make(); err != nil { - println("Failed to initialize a semaphore.\n%+v", err) + println(fmt.Sprintf("Failed to initialize a semaphore.\n%+v", err)) os.Exit(1) return } rtr, err := router.New() if err != nil { - println("Failed to initialize controllers.\n%+v", err) + println(fmt.Sprintf("Failed to initialize controllers.\n%+v", err)) os.Exit(1) return } println(logo) if err := http.ListenAndServe(application.Config.Addr(), rtr); err != nil { - println("Failed to run server.\n%+v", err) + println(fmt.Sprintf("Failed to run server.\n%+v", err)) os.Exit(1) return } From 4bc5090a0fcbb3a747e8bc7d20c55c8ed1b85f2f Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sun, 9 Dec 2018 16:06:55 +0900 Subject: [PATCH 046/135] Add duci struct --- .gitignore | 2 +- application/duci/duci.go | 112 +++++++++++++++++++ application/service/job/job.go | 23 +++- presentation/controller/health/handler.go | 19 +++- presentation/controller/job/handler.go | 21 ++-- presentation/controller/webhook/handler.go | 25 +++-- presentation/router/router.go | 123 ++------------------- 7 files changed, 186 insertions(+), 139 deletions(-) create mode 100644 application/duci/duci.go diff --git a/.gitignore b/.gitignore index fb75cd87..7ecc2efb 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,6 @@ vendor # app /config.yml release-notes.txt -duci +/duci duci.exe dist \ No newline at end of file diff --git a/application/duci/duci.go b/application/duci/duci.go new file mode 100644 index 00000000..2d61e1c0 --- /dev/null +++ b/application/duci/duci.go @@ -0,0 +1,112 @@ +package duci + +import ( + "context" + "fmt" + "github.com/duck8823/duci/application" + "github.com/duck8823/duci/application/service/executor" + "github.com/duck8823/duci/application/service/job" + "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/job/target/github" + "github.com/duck8823/duci/domain/model/runner" + "github.com/pkg/errors" + "time" +) + +type duci struct { + executor.Executor + jobService job_service.Service + github github.GitHub +} + +func New() (*duci, error) { + jobService, err := job_service.GetInstance() + if err != nil { + return nil, errors.WithStack(err) + } + github, err := github.GetInstance() + if err != nil { + return nil, errors.WithStack(err) + } + duci := &duci{ + jobService: jobService, + github: github, + } + duci.Executor = executor.DefaultExecutorBuilder(). + StartFunc(duci.Start). + EndFunc(duci.End). + LogFunc(duci.AppendLog). + Build() + + return duci, nil +} + +func (d *duci) Start(ctx context.Context) { + buildJob, err := application.BuildJobFromContext(ctx) + if err != nil { + _ = d.jobService.Append(buildJob.ID, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) + return + } + if err := d.jobService.Start(buildJob.ID); err != nil { + _ = d.jobService.Append(buildJob.ID, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) + return + } + _ = d.github.CreateCommitStatus(ctx, github.CommitStatus{ + TargetSource: buildJob.TargetSource, + State: github.PENDING, + Description: "pending", + Context: buildJob.TaskName, + TargetURL: buildJob.TargetURL, + }) +} + +func (d *duci) AppendLog(ctx context.Context, log job.Log) { + buildJob, err := application.BuildJobFromContext(ctx) + if err != nil { + _ = d.jobService.Append(buildJob.ID, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) + return + } + for line, err := log.ReadLine(); err == nil; line, err = log.ReadLine() { + println(line.Message) + _ = d.jobService.Append(buildJob.ID, *line) + } +} + +func (d *duci) End(ctx context.Context, e error) { + buildJob, err := application.BuildJobFromContext(ctx) + if err != nil { + _ = d.jobService.Append(buildJob.ID, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) + return + } + if err := d.jobService.Finish(buildJob.ID); err != nil { + println(fmt.Sprintf("%+v", err)) + return + } + + switch e { + case nil: + _ = d.github.CreateCommitStatus(ctx, github.CommitStatus{ + TargetSource: buildJob.TargetSource, + State: github.SUCCESS, + Description: "success", + Context: buildJob.TaskName, + TargetURL: buildJob.TargetURL, + }) + case runner.ErrFailure: + _ = d.github.CreateCommitStatus(ctx, github.CommitStatus{ + TargetSource: buildJob.TargetSource, + State: github.FAILURE, + Description: "failure", + Context: buildJob.TaskName, + TargetURL: buildJob.TargetURL, + }) + default: + _ = d.github.CreateCommitStatus(ctx, github.CommitStatus{ + TargetSource: buildJob.TargetSource, + State: github.ERROR, + Description: github.Description(fmt.Sprintf("error: %s", e.Error())), + Context: buildJob.TaskName, + TargetURL: buildJob.TargetURL, + }) + } +} diff --git a/application/service/job/job.go b/application/service/job/job.go index e5031910..27c2493c 100644 --- a/application/service/job/job.go +++ b/application/service/job/job.go @@ -1,7 +1,6 @@ package job_service import ( - "github.com/duck8823/duci/application" . "github.com/duck8823/duci/domain/model/job" . "github.com/duck8823/duci/infrastructure/job" "github.com/pkg/errors" @@ -14,17 +13,31 @@ type Service interface { Finish(id ID) error } +var instance *serviceImpl + type serviceImpl struct { repo Repository } -func New() (Service, error) { - dataSource, err := NewDataSource(application.Config.Server.DatabasePath) +func Initialize(path string) error { + if instance != nil { + return errors.New("instance already initialized.") + } + + dataSource, err := NewDataSource(path) if err != nil { - return nil, errors.WithStack(err) + return errors.WithStack(err) } - return &serviceImpl{repo: dataSource}, nil + instance = &serviceImpl{repo: dataSource} + return nil +} + +func GetInstance() (Service, error) { + if instance == nil { + return nil, errors.New("instance still not initialized.") + } + return instance, nil } func (s *serviceImpl) FindBy(id ID) (*Job, error) { diff --git a/presentation/controller/health/handler.go b/presentation/controller/health/handler.go index c2c08b82..5b7b0694 100644 --- a/presentation/controller/health/handler.go +++ b/presentation/controller/health/handler.go @@ -2,17 +2,26 @@ package health import ( "github.com/duck8823/duci/domain/model/docker" + "github.com/pkg/errors" "net/http" ) -// Handler of health check. -type Handler struct { - Docker docker.Docker +// handler of health check. +type handler struct { + docker docker.Docker +} + +func NewHandler() (*handler, error) { + docker, err := docker.New() + if err != nil { + return nil, errors.WithStack(err) + } + return &handler{docker: docker}, nil } // ServeHTTP responses a server status -func (c *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if err := c.Docker.Status(); err != nil { +func (c *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if err := c.docker.Status(); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } diff --git a/presentation/controller/job/handler.go b/presentation/controller/job/handler.go index fa7524a6..d7b0c19a 100644 --- a/presentation/controller/job/handler.go +++ b/presentation/controller/job/handler.go @@ -11,11 +11,19 @@ import ( "net/http" ) -type Handler struct { - Service job_service.Service +type handler struct { + service job_service.Service } -func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { +func NewHandler() (*handler, error) { + service, err := job_service.GetInstance() + if err != nil { + return nil, errors.WithStack(err) + } + return &handler{service: service}, nil +} + +func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") id, err := uuid.Parse(chi.URLParam(r, "uuid")) @@ -30,17 +38,16 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } -func (h *Handler) logs(w http.ResponseWriter, id ID) error { +func (h *handler) logs(w http.ResponseWriter, id ID) error { f, ok := w.(http.Flusher) if !ok { return errors.New("Streaming unsupported!") } + // TODO: add timeout var read int - var job *Job - var err error for { - job, err = h.Service.FindBy(id) + job, err := h.service.FindBy(id) if err != nil { return errors.WithStack(err) } diff --git a/presentation/controller/webhook/handler.go b/presentation/controller/webhook/handler.go index b28bf488..92dccf43 100644 --- a/presentation/controller/webhook/handler.go +++ b/presentation/controller/webhook/handler.go @@ -5,21 +5,32 @@ import ( "encoding/json" "fmt" "github.com/duck8823/duci/application" + "github.com/duck8823/duci/application/duci" "github.com/duck8823/duci/application/service/executor" "github.com/duck8823/duci/domain/model/job/target" "github.com/duck8823/duci/domain/model/job/target/github" go_github "github.com/google/go-github/github" + "github.com/pkg/errors" "gopkg.in/src-d/go-git.v4/plumbing" "net/http" ) type SkipBuild error -type Handler struct { - Executor executor.Executor +type handler struct { + executor executor.Executor } -func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { +func NewHandler() (*handler, error) { + executor, err := duci.New() + if err != nil { + return nil, errors.WithStack(err) + } + + return &handler{executor: executor}, nil +} + +func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { event := r.Header.Get("X-GitHub-Event") switch event { case "push": @@ -33,7 +44,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } -func (h *Handler) PushEvent(w http.ResponseWriter, r *http.Request) { +func (h *handler) PushEvent(w http.ResponseWriter, r *http.Request) { event := &go_github.PushEvent{} if err := json.NewDecoder(r.Body).Decode(event); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) @@ -57,7 +68,7 @@ func (h *Handler) PushEvent(w http.ResponseWriter, r *http.Request) { TargetURL: targetURL(r), }) - if err := h.Executor.Execute(ctx, &target.GitHubPush{ + if err := h.executor.Execute(ctx, &target.GitHubPush{ Repo: event.GetRepo(), Point: event, }); err != nil { @@ -68,7 +79,7 @@ func (h *Handler) PushEvent(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) } -func (h *Handler) IssueCommentEvent(w http.ResponseWriter, r *http.Request) { +func (h *handler) IssueCommentEvent(w http.ResponseWriter, r *http.Request) { event := &go_github.IssueCommentEvent{} if err := json.NewDecoder(r.Body).Decode(event); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) @@ -111,7 +122,7 @@ func (h *Handler) IssueCommentEvent(w http.ResponseWriter, r *http.Request) { TargetURL: targetURL(r), }) - go h.Executor.Execute(ctx, &target.GitHubPush{ + go h.executor.Execute(ctx, &target.GitHubPush{ Repo: event.GetRepo(), Point: pnt, }, phrase.Command()...) diff --git a/presentation/router/router.go b/presentation/router/router.go index 4a438889..b2f4cbea 100644 --- a/presentation/router/router.go +++ b/presentation/router/router.go @@ -1,140 +1,35 @@ package router import ( - "context" - "fmt" - "github.com/duck8823/duci/application" - "github.com/duck8823/duci/application/service/executor" - "github.com/duck8823/duci/application/service/job" - "github.com/duck8823/duci/domain/model/docker" - "github.com/duck8823/duci/domain/model/job" - "github.com/duck8823/duci/domain/model/job/target/git" - "github.com/duck8823/duci/domain/model/job/target/github" - "github.com/duck8823/duci/domain/model/runner" - health_controller "github.com/duck8823/duci/presentation/controller/health" - job_controller "github.com/duck8823/duci/presentation/controller/job" - webhook_controller "github.com/duck8823/duci/presentation/controller/webhook" + "github.com/duck8823/duci/presentation/controller/health" + "github.com/duck8823/duci/presentation/controller/job" + "github.com/duck8823/duci/presentation/controller/webhook" "github.com/go-chi/chi" "github.com/pkg/errors" "net/http" - "os" - "time" ) // New returns handler of application. func New() (http.Handler, error) { - // FIXME: where initialize?? - if err := git.InitializeWithHTTP(func(ctx context.Context, log job.Log) { - for line, err := log.ReadLine(); err == nil; line, err = log.ReadLine() { - println(line.Message) - } - }); err != nil { - return nil, errors.WithStack(err) - } - - if err := github.Initialize(os.Getenv("GITHUB_TOKEN")); err != nil { - return nil, errors.WithStack(err) - } - - gh, err := github.GetInstance() + webhookHandler, err := webhook.NewHandler() if err != nil { return nil, errors.WithStack(err) } - jobService, err := job_service.New() + jobHandler, err := job.NewHandler() if err != nil { return nil, errors.WithStack(err) } - webhook := &webhook_controller.Handler{ - Executor: executor.DefaultExecutorBuilder(). - StartFunc(func(ctx context.Context) { - buildJob, err := application.BuildJobFromContext(ctx) - if err != nil { - _ = jobService.Append(buildJob.ID, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) - return - } - if err := jobService.Start(buildJob.ID); err != nil { - _ = jobService.Append(buildJob.ID, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) - return - } - _ = gh.CreateCommitStatus(ctx, github.CommitStatus{ - TargetSource: buildJob.TargetSource, - State: github.PENDING, - Description: "pending", - Context: buildJob.TaskName, - TargetURL: buildJob.TargetURL, - }) - }). - LogFunc(func(ctx context.Context, log job.Log) { - buildJob, err := application.BuildJobFromContext(ctx) - if err != nil { - _ = jobService.Append(buildJob.ID, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) - return - } - for line, err := log.ReadLine(); err == nil; line, err = log.ReadLine() { - println(line.Message) - _ = jobService.Append(buildJob.ID, *line) - } - }). - EndFunc(func(ctx context.Context, e error) { - buildJob, err := application.BuildJobFromContext(ctx) - if err != nil { - _ = jobService.Append(buildJob.ID, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) - return - } - if err := jobService.Finish(buildJob.ID); err != nil { - println(fmt.Sprintf("%+v", err)) - return - } - - switch e { - case nil: - _ = gh.CreateCommitStatus(ctx, github.CommitStatus{ - TargetSource: buildJob.TargetSource, - State: github.SUCCESS, - Description: "success", - Context: buildJob.TaskName, - TargetURL: buildJob.TargetURL, - }) - case runner.ErrFailure: - _ = gh.CreateCommitStatus(ctx, github.CommitStatus{ - TargetSource: buildJob.TargetSource, - State: github.FAILURE, - Description: "failure", - Context: buildJob.TaskName, - TargetURL: buildJob.TargetURL, - }) - default: - _ = gh.CreateCommitStatus(ctx, github.CommitStatus{ - TargetSource: buildJob.TargetSource, - State: github.ERROR, - Description: github.Description(fmt.Sprintf("error: %s", e.Error())), - Context: buildJob.TaskName, - TargetURL: buildJob.TargetURL, - }) - } - }). - Build(), - } - - job := &job_controller.Handler{ - Service: jobService, - } - - docker, err := docker.New() + healthHandler, err := health.NewHandler() if err != nil { return nil, errors.WithStack(err) } - health := &health_controller.Handler{ - Docker: docker, - } - rtr := chi.NewRouter() - rtr.Post("/", webhook.ServeHTTP) - rtr.Get("/logs/{uuid}", job.ServeHTTP) - rtr.Get("/health", health.ServeHTTP) + rtr.Post("/", webhookHandler.ServeHTTP) + rtr.Get("/logs/{uuid}", jobHandler.ServeHTTP) + rtr.Get("/health", healthHandler.ServeHTTP) return rtr, nil } From 3a954a298939c1c8ac6d571134364df9836ab4f0 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sun, 9 Dec 2018 16:55:02 +0900 Subject: [PATCH 047/135] Change error type to variable --- presentation/controller/webhook/handler.go | 7 +++++-- presentation/controller/webhook/phrase.go | 5 ++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/presentation/controller/webhook/handler.go b/presentation/controller/webhook/handler.go index 92dccf43..5e0351a0 100644 --- a/presentation/controller/webhook/handler.go +++ b/presentation/controller/webhook/handler.go @@ -15,7 +15,7 @@ import ( "net/http" ) -type SkipBuild error +var SkipBuild = errors.New("Skip build") type handler struct { executor executor.Executor @@ -105,10 +105,13 @@ func (h *handler) IssueCommentEvent(w http.ResponseWriter, r *http.Request) { } phrase, err := extractBuildPhrase(event.GetComment().GetBody()) - if err != nil { + if err == SkipBuild { w.WriteHeader(http.StatusOK) w.Write([]byte("{\"message\":\"skip build\"}")) return + } else if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return } ctx := application.ContextWithJob(context.Background(), &application.BuildJob{ diff --git a/presentation/controller/webhook/phrase.go b/presentation/controller/webhook/phrase.go index 721a06bd..71ccdaab 100644 --- a/presentation/controller/webhook/phrase.go +++ b/presentation/controller/webhook/phrase.go @@ -2,7 +2,6 @@ package webhook import ( "github.com/duck8823/duci/domain/model/docker" - "github.com/pkg/errors" "regexp" "strings" ) @@ -13,9 +12,9 @@ func (p phrase) Command() docker.Command { return strings.Split(string(p), " ") } -func extractBuildPhrase(comment string) (phrase, SkipBuild) { +func extractBuildPhrase(comment string) (phrase, error) { if !regexp.MustCompile("^ci\\s+[^\\s]+").Match([]byte(comment)) { - return "", SkipBuild(errors.New("Not start with ci.")) + return "", SkipBuild } phrase := phrase(regexp.MustCompile("^ci\\s+").ReplaceAllString(comment, "")) return phrase, nil From 7f1efa0c038ea5299703e1db45c7a9f9c304938a Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sun, 9 Dec 2018 17:12:47 +0900 Subject: [PATCH 048/135] Add comment to public functions and variables --- application/cmd/root.go | 1 + application/context.go | 1 + application/duci/duci.go | 4 ++++ application/initialize.go | 1 + application/service/job/job.go | 7 +++++++ infrastructure/job/data_source.go | 3 +++ presentation/controller/health/handler.go | 2 +- presentation/controller/job/handler.go | 2 ++ presentation/controller/webhook/handler.go | 5 +++++ presentation/controller/webhook/phrase.go | 1 + 10 files changed, 26 insertions(+), 1 deletion(-) diff --git a/application/cmd/root.go b/application/cmd/root.go index c5f14e09..daf30e7e 100644 --- a/application/cmd/root.go +++ b/application/cmd/root.go @@ -13,6 +13,7 @@ func init() { rootCmd.AddCommand(serverCmd, configCmd, healthCmd, versionCmd) } +// Execute command func Execute(args []string) { rootCmd.SetArgs(args) if err := rootCmd.Execute(); err != nil { diff --git a/application/context.go b/application/context.go index 04d79830..a4b16dd7 100644 --- a/application/context.go +++ b/application/context.go @@ -10,6 +10,7 @@ import ( var ctxKey = "duci_job" +// BuildJob represents once of job type BuildJob struct { ID job.ID TargetSource *github.TargetSource diff --git a/application/duci/duci.go b/application/duci/duci.go index 2d61e1c0..cdda7a6e 100644 --- a/application/duci/duci.go +++ b/application/duci/duci.go @@ -19,6 +19,7 @@ type duci struct { github github.GitHub } +// New returns duci instance func New() (*duci, error) { jobService, err := job_service.GetInstance() if err != nil { @@ -41,6 +42,7 @@ func New() (*duci, error) { return duci, nil } +// Start represents a function of start job func (d *duci) Start(ctx context.Context) { buildJob, err := application.BuildJobFromContext(ctx) if err != nil { @@ -60,6 +62,7 @@ func (d *duci) Start(ctx context.Context) { }) } +// AppendLog is a function that print and store log func (d *duci) AppendLog(ctx context.Context, log job.Log) { buildJob, err := application.BuildJobFromContext(ctx) if err != nil { @@ -72,6 +75,7 @@ func (d *duci) AppendLog(ctx context.Context, log job.Log) { } } +// End represents a function func (d *duci) End(ctx context.Context, e error) { buildJob, err := application.BuildJobFromContext(ctx) if err != nil { diff --git a/application/initialize.go b/application/initialize.go index 3c24753e..2dd8dbb6 100644 --- a/application/initialize.go +++ b/application/initialize.go @@ -9,6 +9,7 @@ import ( "github.com/pkg/errors" ) +// Initialize singleton instances that are needed by application func Initialize() error { if err := git.InitializeWithHTTP(func(ctx context.Context, log job.Log) { for line, err := log.ReadLine(); err == nil; line, err = log.ReadLine() { diff --git a/application/service/job/job.go b/application/service/job/job.go index 27c2493c..0defda38 100644 --- a/application/service/job/job.go +++ b/application/service/job/job.go @@ -6,6 +6,7 @@ import ( "github.com/pkg/errors" ) +// Service represents job service type Service interface { FindBy(id ID) (*Job, error) Start(id ID) error @@ -19,6 +20,7 @@ type serviceImpl struct { repo Repository } +// Initialize implementation of job service func Initialize(path string) error { if instance != nil { return errors.New("instance already initialized.") @@ -33,6 +35,7 @@ func Initialize(path string) error { return nil } +// GetInstance returns job service func GetInstance() (Service, error) { if instance == nil { return nil, errors.New("instance still not initialized.") @@ -40,6 +43,7 @@ func GetInstance() (Service, error) { return instance, nil } +// FindBy returns job is found by ID func (s *serviceImpl) FindBy(id ID) (*Job, error) { job, err := s.repo.FindBy(id) if err != nil { @@ -48,6 +52,7 @@ func (s *serviceImpl) FindBy(id ID) (*Job, error) { return job, nil } +// Start store empty job func (s *serviceImpl) Start(id ID) error { job := Job{ID: id, Finished: false} if err := s.repo.Save(job); err != nil { @@ -56,6 +61,7 @@ func (s *serviceImpl) Start(id ID) error { return nil } +// Append log to job func (s *serviceImpl) Append(id ID, line LogLine) error { job, err := s.findOrInitialize(id) if err != nil { @@ -81,6 +87,7 @@ func (s *serviceImpl) findOrInitialize(id ID) (*Job, error) { return job, nil } +// Finish store finished job func (s *serviceImpl) Finish(id ID) error { job, err := s.repo.FindBy(id) if err != nil { diff --git a/infrastructure/job/data_source.go b/infrastructure/job/data_source.go index afa02511..4b36377f 100644 --- a/infrastructure/job/data_source.go +++ b/infrastructure/job/data_source.go @@ -12,6 +12,7 @@ type dataSource struct { db LevelDB } +// NewDataSource returns job data source func NewDataSource(path string) (*dataSource, error) { db, err := leveldb.OpenFile(path, nil) if err != nil { @@ -20,6 +21,7 @@ func NewDataSource(path string) (*dataSource, error) { return &dataSource{db}, nil } +// FindBy returns job found by ID func (d *dataSource) FindBy(id ID) (*Job, error) { data, err := d.db.Get(id.ToSlice(), nil) if err == leveldb.ErrNotFound { @@ -36,6 +38,7 @@ func (d *dataSource) FindBy(id ID) (*Job, error) { return job, nil } +// Save store job to data source func (d *dataSource) Save(job Job) error { data, err := job.ToBytes() if err != nil { diff --git a/presentation/controller/health/handler.go b/presentation/controller/health/handler.go index 5b7b0694..a2e2586e 100644 --- a/presentation/controller/health/handler.go +++ b/presentation/controller/health/handler.go @@ -6,11 +6,11 @@ import ( "net/http" ) -// handler of health check. type handler struct { docker docker.Docker } +// NewHandler returns implement of health check handler func NewHandler() (*handler, error) { docker, err := docker.New() if err != nil { diff --git a/presentation/controller/job/handler.go b/presentation/controller/job/handler.go index d7b0c19a..5fca9d4b 100644 --- a/presentation/controller/job/handler.go +++ b/presentation/controller/job/handler.go @@ -15,6 +15,7 @@ type handler struct { service job_service.Service } +// NewHandler returns implement of job func NewHandler() (*handler, error) { service, err := job_service.GetInstance() if err != nil { @@ -23,6 +24,7 @@ func NewHandler() (*handler, error) { return &handler{service: service}, nil } +// ServeHTTP responses log stream func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") diff --git a/presentation/controller/webhook/handler.go b/presentation/controller/webhook/handler.go index 5e0351a0..889caba7 100644 --- a/presentation/controller/webhook/handler.go +++ b/presentation/controller/webhook/handler.go @@ -15,12 +15,14 @@ import ( "net/http" ) +// SkipBuild represents error of skip build var SkipBuild = errors.New("Skip build") type handler struct { executor executor.Executor } +// NewHandler returns a implement of webhook handler func NewHandler() (*handler, error) { executor, err := duci.New() if err != nil { @@ -30,6 +32,7 @@ func NewHandler() (*handler, error) { return &handler{executor: executor}, nil } +// ServeHTTP receives github event func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { event := r.Header.Get("X-GitHub-Event") switch event { @@ -44,6 +47,7 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } +// PushEvent receives github push event func (h *handler) PushEvent(w http.ResponseWriter, r *http.Request) { event := &go_github.PushEvent{} if err := json.NewDecoder(r.Body).Decode(event); err != nil { @@ -79,6 +83,7 @@ func (h *handler) PushEvent(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) } +// IssueCommentEvent receives github issue comment event func (h *handler) IssueCommentEvent(w http.ResponseWriter, r *http.Request) { event := &go_github.IssueCommentEvent{} if err := json.NewDecoder(r.Body).Decode(event); err != nil { diff --git a/presentation/controller/webhook/phrase.go b/presentation/controller/webhook/phrase.go index 71ccdaab..c11d129f 100644 --- a/presentation/controller/webhook/phrase.go +++ b/presentation/controller/webhook/phrase.go @@ -8,6 +8,7 @@ import ( type phrase string +// Command returns command of docker func (p phrase) Command() docker.Command { return strings.Split(string(p), " ") } From 17bb89b65a4efa5b67b25023fc478f1db8e51f16 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sun, 9 Dec 2018 21:53:21 +0900 Subject: [PATCH 049/135] s/ToString/String/ --- application/config.go | 2 +- application/initialize.go | 2 +- domain/model/docker/docker.go | 12 ++++++------ domain/model/docker/types.go | 6 +++--- domain/model/job/target.go | 2 +- domain/model/job/target/github/github.go | 2 +- domain/model/job/target/github/status.go | 2 +- domain/model/runner/helper.go | 10 +++++----- 8 files changed, 19 insertions(+), 19 deletions(-) diff --git a/application/config.go b/application/config.go index ee60165b..edbbf044 100644 --- a/application/config.go +++ b/application/config.go @@ -32,7 +32,7 @@ func (s maskString) MarshalJSON() ([]byte, error) { } // ToString returns unmasked string. -func (s maskString) ToString() string { +func (s maskString) String() string { return string(s) } diff --git a/application/initialize.go b/application/initialize.go index 2dd8dbb6..21f7ea1f 100644 --- a/application/initialize.go +++ b/application/initialize.go @@ -19,7 +19,7 @@ func Initialize() error { return errors.WithStack(err) } - if err := github.Initialize(Config.GitHub.APIToken.ToString()); err != nil { + if err := github.Initialize(Config.GitHub.APIToken.String()); err != nil { return errors.WithStack(err) } diff --git a/domain/model/docker/docker.go b/domain/model/docker/docker.go index fdf719ce..aad54ede 100644 --- a/domain/model/docker/docker.go +++ b/domain/model/docker/docker.go @@ -36,8 +36,8 @@ func New() (Docker, error) { // Build a docker image. func (c *client) Build(ctx context.Context, file io.Reader, tag Tag, dockerfile Dockerfile) (Log, error) { opts := types.ImageBuildOptions{ - Tags: []string{tag.ToString()}, - Dockerfile: dockerfile.ToString(), + Tags: []string{tag.String()}, + Dockerfile: dockerfile.String(), Remove: true, } resp, err := c.moby.ImageBuild(ctx, file, opts) @@ -51,7 +51,7 @@ func (c *client) Build(ctx context.Context, file io.Reader, tag Tag, dockerfile // Run docker container with command. func (c *client) Run(ctx context.Context, opts RuntimeOptions, tag Tag, cmd Command) (ContainerID, Log, error) { con, err := c.moby.ContainerCreate(ctx, &container.Config{ - Image: tag.ToString(), + Image: tag.String(), Env: opts.Environments.ToArray(), Volumes: opts.Volumes.ToMap(), Cmd: cmd.ToSlice(), @@ -80,7 +80,7 @@ func (c *client) Run(ctx context.Context, opts RuntimeOptions, tag Tag, cmd Comm // RemoveContainer remove docker container. func (c *client) RemoveContainer(ctx context.Context, conID ContainerID) error { - if err := c.moby.ContainerRemove(ctx, conID.ToString(), types.ContainerRemoveOptions{}); err != nil { + if err := c.moby.ContainerRemove(ctx, conID.String(), types.ContainerRemoveOptions{}); err != nil { return errors.WithStack(err) } return nil @@ -88,7 +88,7 @@ func (c *client) RemoveContainer(ctx context.Context, conID ContainerID) error { // RemoveImage remove docker image. func (c *client) RemoveImage(ctx context.Context, tag Tag) error { - if _, err := c.moby.ImageRemove(ctx, tag.ToString(), types.ImageRemoveOptions{}); err != nil { + if _, err := c.moby.ImageRemove(ctx, tag.String(), types.ImageRemoveOptions{}); err != nil { return errors.WithStack(err) } return nil @@ -96,7 +96,7 @@ func (c *client) RemoveImage(ctx context.Context, tag Tag) error { // ExitCode returns exit code specific container id. func (c *client) ExitCode(ctx context.Context, conID ContainerID) (ExitCode, error) { - body, err := c.moby.ContainerWait(ctx, conID.ToString(), container.WaitConditionNotRunning) + body, err := c.moby.ContainerWait(ctx, conID.String(), container.WaitConditionNotRunning) select { case b := <-body: return ExitCode(b.StatusCode), nil diff --git a/domain/model/docker/types.go b/domain/model/docker/types.go index 9495a103..2b13d5d2 100644 --- a/domain/model/docker/types.go +++ b/domain/model/docker/types.go @@ -4,7 +4,7 @@ package docker type Tag string // ToString return string value -func (t Tag) ToString() string { +func (t Tag) String() string { return string(t) } @@ -20,7 +20,7 @@ func (c Command) ToSlice() []string { type Dockerfile string // ToString returns string value -func (d Dockerfile) ToString() string { +func (d Dockerfile) String() string { return string(d) } @@ -28,7 +28,7 @@ func (d Dockerfile) ToString() string { type ContainerID string // ToString returns string value -func (c ContainerID) ToString() string { +func (c ContainerID) String() string { return string(c) } diff --git a/domain/model/job/target.go b/domain/model/job/target.go index 26c615b7..356b6616 100644 --- a/domain/model/job/target.go +++ b/domain/model/job/target.go @@ -6,7 +6,7 @@ type Target interface { type WorkDir string -func (w WorkDir) ToString() string { +func (w WorkDir) String() string { return string(w) } diff --git a/domain/model/job/target/github/github.go b/domain/model/job/target/github/github.go index eb5a6551..6f4ca288 100644 --- a/domain/model/job/target/github/github.go +++ b/domain/model/job/target/github/github.go @@ -65,7 +65,7 @@ func (c *client) CreateCommitStatus(ctx context.Context, status CommitStatus) er repoStatus := &go_github.RepoStatus{ Context: go_github.String(status.Context), Description: go_github.String(status.Description.TrimmedString()), - State: go_github.String(status.State.ToString()), + State: go_github.String(status.State.String()), TargetURL: go_github.String(status.TargetURL.String()), } diff --git a/domain/model/job/target/github/status.go b/domain/model/job/target/github/status.go index 32269e32..946e2d2d 100644 --- a/domain/model/job/target/github/status.go +++ b/domain/model/job/target/github/status.go @@ -5,7 +5,7 @@ import "net/url" // State represents state of commit status type State string -func (s State) ToString() string { +func (s State) String() string { return string(s) } diff --git a/domain/model/runner/helper.go b/domain/model/runner/helper.go index 09a897ee..ee28eb07 100644 --- a/domain/model/runner/helper.go +++ b/domain/model/runner/helper.go @@ -14,14 +14,14 @@ import ( // createTarball creates a tar archive func createTarball(workDir job.WorkDir) (*os.File, error) { - tarFilePath := filepath.Join(workDir.ToString(), "duci.tar") + tarFilePath := filepath.Join(workDir.String(), "duci.tar") writeFile, err := os.OpenFile(tarFilePath, os.O_RDWR|os.O_CREATE, 0600) if err != nil { return nil, errors.WithStack(err) } defer writeFile.Close() - if err := tar.Create(workDir.ToString(), writeFile); err != nil { + if err := tar.Create(workDir.String(), writeFile); err != nil { return nil, errors.WithStack(err) } @@ -32,7 +32,7 @@ func createTarball(workDir job.WorkDir) (*os.File, error) { // dockerfilePath returns a path to dockerfile for duci using func dockerfilePath(workDir job.WorkDir) Dockerfile { dockerfile := "./Dockerfile" - if exists(filepath.Join(workDir.ToString(), ".duci/Dockerfile")) { + if exists(filepath.Join(workDir.String(), ".duci/Dockerfile")) { dockerfile = ".duci/Dockerfile" } return Dockerfile(dockerfile) @@ -48,10 +48,10 @@ func exists(name string) bool { func runtimeOptions(workDir job.WorkDir) (RuntimeOptions, error) { var opts RuntimeOptions - if !exists(filepath.Join(workDir.ToString(), ".duci/config.yml")) { + if !exists(filepath.Join(workDir.String(), ".duci/config.yml")) { return opts, nil } - content, err := ioutil.ReadFile(filepath.Join(workDir.ToString(), ".duci/config.yml")) + content, err := ioutil.ReadFile(filepath.Join(workDir.String(), ".duci/config.yml")) if err != nil { return opts, errors.WithStack(err) } From 529828bd15c42de6a33ed5d904ab1e4494c17d28 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sun, 9 Dec 2018 21:55:15 +0900 Subject: [PATCH 050/135] Remove To prefix --- domain/model/docker/docker.go | 6 +++--- domain/model/docker/options.go | 8 ++++---- domain/model/docker/types.go | 4 ++-- domain/model/job/job.go | 2 +- presentation/controller/webhook/handler.go | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/domain/model/docker/docker.go b/domain/model/docker/docker.go index aad54ede..9d3f73a1 100644 --- a/domain/model/docker/docker.go +++ b/domain/model/docker/docker.go @@ -52,9 +52,9 @@ func (c *client) Build(ctx context.Context, file io.Reader, tag Tag, dockerfile func (c *client) Run(ctx context.Context, opts RuntimeOptions, tag Tag, cmd Command) (ContainerID, Log, error) { con, err := c.moby.ContainerCreate(ctx, &container.Config{ Image: tag.String(), - Env: opts.Environments.ToArray(), - Volumes: opts.Volumes.ToMap(), - Cmd: cmd.ToSlice(), + Env: opts.Environments.Array(), + Volumes: opts.Volumes.Map(), + Cmd: cmd.Slice(), }, &container.HostConfig{ Binds: opts.Volumes, }, nil, "") diff --git a/domain/model/docker/options.go b/domain/model/docker/options.go index 4a74348e..94ec8585 100644 --- a/domain/model/docker/options.go +++ b/domain/model/docker/options.go @@ -14,8 +14,8 @@ type RuntimeOptions struct { // Environments represents a docker `-e` option. type Environments map[string]interface{} -// ToArray returns string array of environments -func (e Environments) ToArray() []string { +// Array returns string array of environments +func (e Environments) Array() []string { var a []string for key, val := range e { a = append(a, fmt.Sprintf("%s=%v", key, val)) @@ -26,8 +26,8 @@ func (e Environments) ToArray() []string { // Volumes represents a docker `-v` option. type Volumes []string -// ToMap returns map of volumes. -func (v Volumes) ToMap() map[string]struct{} { +// Map returns map of volumes. +func (v Volumes) Map() map[string]struct{} { m := make(map[string]struct{}) for _, volume := range v { key := strings.Split(volume, ":")[0] diff --git a/domain/model/docker/types.go b/domain/model/docker/types.go index 2b13d5d2..7981e8e8 100644 --- a/domain/model/docker/types.go +++ b/domain/model/docker/types.go @@ -11,8 +11,8 @@ func (t Tag) String() string { // Command describes a docker CMD type Command []string -// ToSlice returns slice values -func (c Command) ToSlice() []string { +// Slice returns slice values +func (c Command) Slice() []string { return []string(c) } diff --git a/domain/model/job/job.go b/domain/model/job/job.go index 147f59c6..45f37c5d 100644 --- a/domain/model/job/job.go +++ b/domain/model/job/job.go @@ -35,7 +35,7 @@ func (j *Job) ToBytes() ([]byte, error) { // ID is the identifier of job type ID uuid.UUID -// ToSlice returns slice value +// Slice returns slice value func (i ID) ToSlice() []byte { return []byte(uuid.UUID(i).String()) } diff --git a/presentation/controller/webhook/handler.go b/presentation/controller/webhook/handler.go index 889caba7..1e38240f 100644 --- a/presentation/controller/webhook/handler.go +++ b/presentation/controller/webhook/handler.go @@ -126,7 +126,7 @@ func (h *handler) IssueCommentEvent(w http.ResponseWriter, r *http.Request) { Ref: pnt.GetRef(), SHA: plumbing.NewHash(pnt.GetHead()), }, - TaskName: fmt.Sprintf("%s/pr/%s", application.Name, phrase.Command().ToSlice()[0]), + TaskName: fmt.Sprintf("%s/pr/%s", application.Name, phrase.Command().Slice()[0]), TargetURL: targetURL(r), }) From 90b0d04df4f15c4eb88bedba28cbd155a068ce24 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Tue, 11 Dec 2018 07:14:18 +0900 Subject: [PATCH 051/135] Fix success --- domain/model/docker/docker_test.go | 631 ++++++++++++++++++ domain/model/docker/export_test.go | 31 + domain/model/docker/log_test.go | 131 ++++ .../model/docker/mock_docker/third_pirty.go | 140 ++++ domain/model/docker/options_test.go | 71 ++ domain/model/docker/types_test.go | 105 +++ 6 files changed, 1109 insertions(+) create mode 100644 domain/model/docker/docker_test.go create mode 100644 domain/model/docker/export_test.go create mode 100644 domain/model/docker/log_test.go create mode 100644 domain/model/docker/mock_docker/third_pirty.go create mode 100644 domain/model/docker/options_test.go create mode 100644 domain/model/docker/types_test.go diff --git a/domain/model/docker/docker_test.go b/domain/model/docker/docker_test.go new file mode 100644 index 00000000..ca17a68b --- /dev/null +++ b/domain/model/docker/docker_test.go @@ -0,0 +1,631 @@ +package docker_test + +import ( + "bytes" + "context" + "errors" + "fmt" + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/duck8823/duci/domain/model/docker" + "github.com/duck8823/duci/domain/model/docker/mock_docker" + . "github.com/golang/mock/gomock" + "github.com/google/go-cmp/cmp" + "github.com/labstack/gommon/random" + "gopkg.in/src-d/go-git.v4/utils/ioutil" + "os" + "strings" + "testing" +) + +func TestNew(t *testing.T) { + t.Run("without environment variable", func(t *testing.T) { + // given + DOCKER_CERT_PATH := os.Getenv("DOCKER_CERT_PATH") + _ = os.Setenv("DOCKER_CERT_PATH", "") + defer func() { + _ = os.Setenv("DOCKER_CERT_PATH", DOCKER_CERT_PATH) + }() + + DOCKER_HOST := os.Getenv("DOCKER_HOST") + _ = os.Setenv("DOCKER_HOST", "") + defer func() { + _ = os.Setenv("DOCKER_HOST", DOCKER_HOST) + }() + + DOCKER_API_VERSION := os.Getenv("DOCKER_API_VERSION") + _ = os.Setenv("DOCKER_API_VERSION", "") + defer func() { + _ = os.Setenv("DOCKER_API_VERSION", DOCKER_API_VERSION) + }() + + // when + get, err := docker.New() + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + _, ok := get.(docker.Docker) + if !ok { + t.Error("instance must be docker.Docker") + } + }) + + t.Run("with wrong environment variable DOCKER_HOST", func(t *testing.T) { + // given + DOCKER_HOST := os.Getenv("DOCKER_HOST") + _ = os.Setenv("DOCKER_HOST", "wrong host name") + defer func() { + _ = os.Setenv("DOCKER_HOST", DOCKER_HOST) + }() + + // when + got, err := docker.New() + + // then + if err == nil { + t.Error("error must not be nil") + } + + if got != nil { + t.Errorf("instance must be nil, but got %+v", err) + } + }) +} + +func TestClient_Build(t *testing.T) { + t.Run("with collect ImageBuildResponse", func(t *testing.T) { + // given + ctrl := NewController(t) + defer ctrl.Finish() + + // and + ctx := context.Background() + buildContext := strings.NewReader("hello world") + tag := "test_tag" + dockerfile := "test_dockerfile" + + // and + want := "want value" + + // and + mockMoby := mock_docker.NewMockMoby(ctrl) + mockMoby.EXPECT(). + ImageBuild(Eq(ctx), Eq(buildContext), Eq(types.ImageBuildOptions{ + Tags: []string{tag}, + Dockerfile: dockerfile, + Remove: true, + })). + Times(1). + Return(types.ImageBuildResponse{ + Body: ioutil.NewReadCloser(strings.NewReader(fmt.Sprintf("{\"stream\":\"%s\"}", want)), nil), + }, nil) + + // and + sut := &docker.Client{} + defer sut.SetMoby(mockMoby)() + + // when + got, err := sut.Build(ctx, buildContext, docker.Tag(tag), docker.Dockerfile(dockerfile)) + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + line, _ := got.ReadLine() + if line.Message != want { + t.Errorf("want: %s, but got: %s", want, line.Message) + } + }) + + t.Run("with error", func(t *testing.T) { + // given + ctrl := NewController(t) + defer ctrl.Finish() + + // and + ctx := context.Background() + buildContext := strings.NewReader("hello world") + tag := "test_tag" + dockerfile := "test_dockerfile" + + // and + empty := types.ImageBuildResponse{} + wantError := errors.New("test_error") + + // and + mockMoby := mock_docker.NewMockMoby(ctrl) + mockMoby.EXPECT(). + ImageBuild(Eq(ctx), Eq(buildContext), Eq(types.ImageBuildOptions{ + Tags: []string{tag}, + Dockerfile: dockerfile, + Remove: true, + })). + Times(1). + Return(empty, wantError) + + // and + sut := &docker.Client{} + defer sut.SetMoby(mockMoby)() + + // when + got, err := sut.Build(ctx, buildContext, docker.Tag(tag), docker.Dockerfile(dockerfile)) + + // then + if err.Error() != wantError.Error() { + t.Errorf("error want: %+v, but got: %+v", wantError, err) + } + + // and + if got != nil { + t.Errorf("log moust be nil, but got %+v", err) + } + }) +} + +func TestClient_Run(t *testing.T) { + t.Run("nominal scenario", func(t *testing.T) { + // given + ctrl := NewController(t) + defer ctrl.Finish() + + // and + ctx := context.Background() + opts := docker.RuntimeOptions{} + tag := docker.Tag("test_tag") + cmd := make([]string, 0) + + // and + wantID := docker.ContainerID(random.String(16, random.Alphanumeric)) + want := "hello test" + + // and + mockMoby := mock_docker.NewMockMoby(ctrl) + mockMoby.EXPECT(). + ContainerCreate(Eq(ctx), Any(), Any(), Nil(), Eq("")). + Times(1). + Return(container.ContainerCreateCreatedBody{ + ID: wantID.String(), + }, nil) + + mockMoby.EXPECT(). + ContainerStart(Eq(ctx), Eq(wantID.String()), Eq(types.ContainerStartOptions{})). + Times(1). + Return(nil) + + mockMoby.EXPECT(). + ContainerLogs(Eq(ctx), Eq(wantID.String()), Eq(types.ContainerLogsOptions{ + ShowStdout: true, + ShowStderr: true, + Follow: true, + })). + Times(1). + Return( + ioutil.NewReadCloser(bytes.NewReader(append([]byte{1, 0, 0, 0, 1, 1, 1, 1}, []byte(want)...)), + nil, + ), + nil, + ) + + // and + sut := &docker.Client{} + defer sut.SetMoby(mockMoby)() + + // when + gotID, got, err := sut.Run(ctx, opts, docker.Tag(tag), cmd) + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + if gotID != wantID { + t.Errorf("id want: %s, but got: %s", wantID, gotID) + } + + // and + line, _ := got.ReadLine() + if line.Message != want { + t.Errorf("want: %s, but got: %s", want, line.Message) + } + }) + + t.Run("non-nominal scenarios", func(t *testing.T) { + // where + for _, tt := range []struct { + name string + f func(*testing.T, docker.RunArgs) (moby docker.Moby, finish func()) + emptyID bool + }{ + { + name: "when failed create container", + f: mockMobyFailedCreateContainer, + emptyID: true, + }, + { + name: "when failed start container", + f: mockMobyFailedContainerStart, + emptyID: false, + }, + { + name: "when failed container logs", + f: mockMobyFailedContainerLogs, + emptyID: false, + }, + } { + t.Run(tt.name, func(t *testing.T) { + // given + ctx := context.Background() + opts := docker.RuntimeOptions{} + tag := docker.Tag("test_tag") + cmd := make([]string, 0) + + // and + mockMoby, finish := tt.f(t, docker.RunArgs{Ctx: ctx, Opts: opts, Tag: tag, Cmd: cmd}) + defer finish() + + // and + sut := &docker.Client{} + defer sut.SetMoby(mockMoby)() + + // when + gotID, got, err := sut.Run(ctx, opts, tag, cmd) + + // then + if err == nil { + t.Error("error must not be nil") + } + + // and + if tt.emptyID && len(gotID.String()) != 0 { + t.Errorf("id must be empty, but got: %s", gotID) + } else if !tt.emptyID && len(gotID.String()) == 0 { + t.Error("id must not be empty") + } + + // and + if got != nil { + t.Errorf("log must be nil, but got: %+v", got) + } + }) + } + }) +} + +func mockMobyFailedCreateContainer( + t *testing.T, + args docker.RunArgs, +) (moby docker.Moby, finish func()) { + t.Helper() + + ctrl := NewController(t) + + mockMoby := mock_docker.NewMockMoby(ctrl) + mockMoby.EXPECT(). + ContainerCreate(Eq(args.Ctx), Any(), Any(), Nil(), Eq("")). + Times(1). + Return(container.ContainerCreateCreatedBody{ + ID: random.String(16, random.Alphanumeric), + }, errors.New("test error")) + + mockMoby.EXPECT(). + ContainerStart(Any(), Any(), Any()). + Times(0) + + mockMoby.EXPECT(). + ContainerLogs(Any(), Any(), Any()). + Times(0) + + return mockMoby, func() { + ctrl.Finish() + } +} + +func mockMobyFailedContainerStart( + t *testing.T, + args docker.RunArgs, +) (moby docker.Moby, finish func()) { + t.Helper() + + conID := random.String(16, random.Alphanumeric) + + ctrl := NewController(t) + + mockMoby := mock_docker.NewMockMoby(ctrl) + mockMoby.EXPECT(). + ContainerCreate(Eq(args.Ctx), Any(), Any(), Nil(), Eq("")). + Times(1). + Return(container.ContainerCreateCreatedBody{ + ID: conID, + }, nil) + + mockMoby.EXPECT(). + ContainerStart(Eq(args.Ctx), Eq(conID), Eq(types.ContainerStartOptions{})). + Times(1). + Return(errors.New("test error")) + + mockMoby.EXPECT(). + ContainerLogs(Any(), Any(), Any()). + Times(0) + + return mockMoby, func() { + ctrl.Finish() + } +} + +func mockMobyFailedContainerLogs( + t *testing.T, + args docker.RunArgs, +) (moby docker.Moby, finish func()) { + t.Helper() + + conID := random.String(16, random.Alphanumeric) + + ctrl := NewController(t) + + mockMoby := mock_docker.NewMockMoby(ctrl) + mockMoby.EXPECT(). + ContainerCreate(Eq(args.Ctx), Any(), Any(), Nil(), Eq("")). + Times(1). + Return(container.ContainerCreateCreatedBody{ + ID: conID, + }, nil) + + mockMoby.EXPECT(). + ContainerStart(Eq(args.Ctx), Eq(conID), Eq(types.ContainerStartOptions{})). + Times(1). + Return(nil) + + mockMoby.EXPECT(). + ContainerLogs(Eq(args.Ctx), Eq(conID), Eq(types.ContainerLogsOptions{ + ShowStdout: true, + ShowStderr: true, + Follow: true, + })). + Times(1). + Return(nil, errors.New("test error")) + + return mockMoby, func() { + ctrl.Finish() + } +} + +func TestClient_RemoveContainer(t *testing.T) { + t.Run("without error", func(t *testing.T) { + // given + ctx := context.Background() + conID := docker.ContainerID(random.String(16, random.Alphanumeric)) + + // and + ctrl := NewController(t) + defer ctrl.Finish() + + mockMoby := mock_docker.NewMockMoby(ctrl) + mockMoby.EXPECT(). + ContainerRemove(Eq(ctx), Eq(conID.String()), Eq(types.ContainerRemoveOptions{})). + Times(1). + Return(nil) + + // and + sut := &docker.Client{} + defer sut.SetMoby(mockMoby)() + + // expect + if err := sut.RemoveContainer(ctx, conID); err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + }) + + t.Run("with error", func(t *testing.T) { + // given + ctx := context.Background() + conID := docker.ContainerID(random.String(16, random.Alphanumeric)) + + // and + ctrl := NewController(t) + defer ctrl.Finish() + + mockMoby := mock_docker.NewMockMoby(ctrl) + mockMoby.EXPECT(). + ContainerRemove(Eq(ctx), Eq(conID.String()), Eq(types.ContainerRemoveOptions{})). + Times(1). + Return(errors.New("test error")) + + // and + sut := &docker.Client{} + defer sut.SetMoby(mockMoby)() + + // expect + if err := sut.RemoveContainer(ctx, conID); err == nil { + t.Error("error must not be nil") + } + }) +} + +func TestClient_RemoveImage(t *testing.T) { + t.Run("without error", func(t *testing.T) { + // given + ctx := context.Background() + tag := docker.Tag(random.String(16, random.Alphanumeric)) + + // and + ctrl := NewController(t) + defer ctrl.Finish() + + mockMoby := mock_docker.NewMockMoby(ctrl) + mockMoby.EXPECT(). + ImageRemove(Eq(ctx), Eq(tag.String()), Eq(types.ImageRemoveOptions{})). + Times(1). + Return(nil, nil) + + sut := &docker.Client{} + defer sut.SetMoby(mockMoby)() + + // expect + if err := sut.RemoveImage(ctx, tag); err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + }) + + t.Run("without error", func(t *testing.T) { + // given + ctx := context.Background() + tag := docker.Tag(random.String(16, random.Alphanumeric)) + + // and + ctrl := NewController(t) + defer ctrl.Finish() + + mockMoby := mock_docker.NewMockMoby(ctrl) + mockMoby.EXPECT(). + ImageRemove(Eq(ctx), Eq(tag.String()), Eq(types.ImageRemoveOptions{})). + Times(1). + Return(nil, errors.New("test error")) + + sut := &docker.Client{} + defer sut.SetMoby(mockMoby)() + + // expect + if err := sut.RemoveImage(ctx, tag); err == nil { + t.Error("error must not be nil") + } + }) +} + +func TestClient_ExitCode(t *testing.T) { + t.Run("with exit code", func(t *testing.T) { + // given + ctx := context.Background() + conID := docker.ContainerID(random.String(16, random.Alphanumeric)) + + // and + want := docker.ExitCode(19) + + // and + body := make(chan container.ContainerWaitOKBody, 1) + e := make(chan error, 1) + + // and + ctrl := NewController(t) + defer ctrl.Finish() + + mockMoby := mock_docker.NewMockMoby(ctrl) + mockMoby.EXPECT(). + ContainerWait(Eq(ctx), Eq(conID.String()), Eq(container.WaitConditionNotRunning)). + Times(1). + Return(body, e) + + // and + sut := &docker.Client{} + defer sut.SetMoby(mockMoby)() + + // and + body <- container.ContainerWaitOKBody{StatusCode: int64(want)} + + // when + got, err := sut.ExitCode(ctx, conID) + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + if !cmp.Equal(got, want) { + t.Errorf("must be equal but: %+v", cmp.Diff(got, want)) + } + }) + + t.Run("with error", func(t *testing.T) { + // given + ctx := context.Background() + conID := docker.ContainerID(random.String(16, random.Alphanumeric)) + + // and + want := docker.ExitCode(-1) + + // and + body := make(chan container.ContainerWaitOKBody, 1) + e := make(chan error, 1) + + // and + ctrl := NewController(t) + defer ctrl.Finish() + + mockMoby := mock_docker.NewMockMoby(ctrl) + mockMoby.EXPECT(). + ContainerWait(Eq(ctx), Eq(conID.String()), Eq(container.WaitConditionNotRunning)). + Times(1). + Return(body, e) + + // and + sut := &docker.Client{} + defer sut.SetMoby(mockMoby)() + + // and + e <- errors.New("test error") + + // when + got, err := sut.ExitCode(ctx, conID) + + // then + if err == nil { + t.Error("error must not be nil") + } + + // and + if !cmp.Equal(got, want) { + t.Errorf("must be equal but: %+v", cmp.Diff(got, want)) + } + }) +} + +func TestClient_Status(t *testing.T) { + t.Run("without error", func(t *testing.T) { + // given + ctrl := NewController(t) + defer ctrl.Finish() + + mockMoby := mock_docker.NewMockMoby(ctrl) + mockMoby.EXPECT(). + Info(Any()). + Times(1). + Return(types.Info{}, nil) + + // and + sut := &docker.Client{} + defer sut.SetMoby(mockMoby)() + + // want + if err := sut.Status(); err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + }) + + t.Run("with error", func(t *testing.T) { + // given + ctrl := NewController(t) + defer ctrl.Finish() + + mockMoby := mock_docker.NewMockMoby(ctrl) + mockMoby.EXPECT(). + Info(Any()). + Times(1). + Return(types.Info{}, errors.New("test error")) + + // and + sut := &docker.Client{} + defer sut.SetMoby(mockMoby)() + + // want + if err := sut.Status(); err == nil { + t.Error("error must not be nil") + } + }) +} diff --git a/domain/model/docker/export_test.go b/domain/model/docker/export_test.go new file mode 100644 index 00000000..50dd10c1 --- /dev/null +++ b/domain/model/docker/export_test.go @@ -0,0 +1,31 @@ +package docker + +import ( + "context" + "time" +) + +type Client = client + +func (c *Client) SetMoby(moby Moby) (reset func()) { + tmp := c.moby + c.moby = moby + return func() { + c.moby = tmp + } +} + +type RunArgs struct { + Ctx context.Context + Opts RuntimeOptions + Tag Tag + Cmd Command +} + +func SetNowFunc(f func() time.Time) (reset func()) { + tmp := now + now = f + return func() { + now = tmp + } +} diff --git a/domain/model/docker/log_test.go b/domain/model/docker/log_test.go new file mode 100644 index 00000000..3fce6db5 --- /dev/null +++ b/domain/model/docker/log_test.go @@ -0,0 +1,131 @@ +package docker_test + +import ( + "fmt" + "github.com/duck8823/duci/domain/model/docker" + "github.com/duck8823/duci/domain/model/job" + "github.com/google/go-cmp/cmp" + "io" + "strings" + "testing" + "time" +) + +func TestNewBuildLog(t *testing.T) { + // when + got := docker.NewBuildLog(strings.NewReader("hello world")) + + // then + if _, ok := got.(job.Log); !ok { + t.Errorf("type assertion error.") + } +} + +func TestBuildLogger_ReadLine(t *testing.T) { + // given + now := time.Now() + defer docker.SetNowFunc(func() time.Time { + return now + })() + + // and + want := &job.LogLine{ + Timestamp: now, + Message: "hello test", + } + + // and + sut := docker.NewBuildLog(strings.NewReader(fmt.Sprintf("{\"stream\":\"%s\"}\n\nhello world\n", want.Message))) + + // when + got, err := sut.ReadLine() + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + if !cmp.Equal(got, want) { + t.Errorf("must be equal, but: %+v", cmp.Diff(got, want)) + } + + // when + got, err = sut.ReadLine() + + // then + if err != io.EOF { + t.Errorf("error must be io.EOF, but got %+v", err) + } + + // and + if got != nil { + t.Errorf("must be nil, but got %+v", got.Message) + } +} + +func TestNewRunLog(t *testing.T) { + // when + got := docker.NewRunLog(strings.NewReader("hello world")) + + // then + if _, ok := got.(job.Log); !ok { + t.Errorf("type assertion error.") + } +} + +func TestRunLogger_ReadLine(t *testing.T) { + // given + now := time.Now() + defer docker.SetNowFunc(func() time.Time { + return now + })() + + // and + want := &job.LogLine{ + Timestamp: now, + Message: "hello test", + } + + // and + sut := docker.NewRunLog(strings.NewReader(fmt.Sprintf("%shello test\rskipped line\n\n1234567890", string([]byte{1, 0, 0, 0, 9, 9, 9, 9})))) + + // when + got, err := sut.ReadLine() + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + if !cmp.Equal(got, want) { + t.Errorf("must be equal, but: %+v", cmp.Diff(got, want)) + } + + // when + got, err = sut.ReadLine() + + // then + if err == nil || err == io.EOF { + t.Errorf("error must not be nil (invalid prefix), but got %+v", err) + } + + // and + if got != nil { + t.Errorf("must be nil, but got %+v", got.Message) + } + + // when + got, err = sut.ReadLine() + + // then + if err != io.EOF { + t.Errorf("error must be io.EOF, but got %+v", err) + } + + // and + if got != nil { + t.Errorf("must be nil, but got %+v", got.Message) + } +} diff --git a/domain/model/docker/mock_docker/third_pirty.go b/domain/model/docker/mock_docker/third_pirty.go new file mode 100644 index 00000000..b7f03e5f --- /dev/null +++ b/domain/model/docker/mock_docker/third_pirty.go @@ -0,0 +1,140 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: domain/model/docker/third_pirty.go + +// Package mock_docker is a generated GoMock package. +package mock_docker + +import ( + context "context" + types "github.com/docker/docker/api/types" + container "github.com/docker/docker/api/types/container" + network "github.com/docker/docker/api/types/network" + gomock "github.com/golang/mock/gomock" + io "io" + reflect "reflect" +) + +// MockMoby is a mock of Moby interface +type MockMoby struct { + ctrl *gomock.Controller + recorder *MockMobyMockRecorder +} + +// MockMobyMockRecorder is the mock recorder for MockMoby +type MockMobyMockRecorder struct { + mock *MockMoby +} + +// NewMockMoby creates a new mock instance +func NewMockMoby(ctrl *gomock.Controller) *MockMoby { + mock := &MockMoby{ctrl: ctrl} + mock.recorder = &MockMobyMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockMoby) EXPECT() *MockMobyMockRecorder { + return m.recorder +} + +// ImageBuild mocks base method +func (m *MockMoby) ImageBuild(ctx context.Context, buildContext io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) { + ret := m.ctrl.Call(m, "ImageBuild", ctx, buildContext, options) + ret0, _ := ret[0].(types.ImageBuildResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ImageBuild indicates an expected call of ImageBuild +func (mr *MockMobyMockRecorder) ImageBuild(ctx, buildContext, options interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ImageBuild", reflect.TypeOf((*MockMoby)(nil).ImageBuild), ctx, buildContext, options) +} + +// ContainerCreate mocks base method +func (m *MockMoby) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (container.ContainerCreateCreatedBody, error) { + ret := m.ctrl.Call(m, "ContainerCreate", ctx, config, hostConfig, networkingConfig, containerName) + ret0, _ := ret[0].(container.ContainerCreateCreatedBody) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ContainerCreate indicates an expected call of ContainerCreate +func (mr *MockMobyMockRecorder) ContainerCreate(ctx, config, hostConfig, networkingConfig, containerName interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContainerCreate", reflect.TypeOf((*MockMoby)(nil).ContainerCreate), ctx, config, hostConfig, networkingConfig, containerName) +} + +// ContainerStart mocks base method +func (m *MockMoby) ContainerStart(ctx context.Context, containerID string, options types.ContainerStartOptions) error { + ret := m.ctrl.Call(m, "ContainerStart", ctx, containerID, options) + ret0, _ := ret[0].(error) + return ret0 +} + +// ContainerStart indicates an expected call of ContainerStart +func (mr *MockMobyMockRecorder) ContainerStart(ctx, containerID, options interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContainerStart", reflect.TypeOf((*MockMoby)(nil).ContainerStart), ctx, containerID, options) +} + +// ContainerLogs mocks base method +func (m *MockMoby) ContainerLogs(ctx context.Context, container string, options types.ContainerLogsOptions) (io.ReadCloser, error) { + ret := m.ctrl.Call(m, "ContainerLogs", ctx, container, options) + ret0, _ := ret[0].(io.ReadCloser) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ContainerLogs indicates an expected call of ContainerLogs +func (mr *MockMobyMockRecorder) ContainerLogs(ctx, container, options interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContainerLogs", reflect.TypeOf((*MockMoby)(nil).ContainerLogs), ctx, container, options) +} + +// ContainerRemove mocks base method +func (m *MockMoby) ContainerRemove(ctx context.Context, containerID string, options types.ContainerRemoveOptions) error { + ret := m.ctrl.Call(m, "ContainerRemove", ctx, containerID, options) + ret0, _ := ret[0].(error) + return ret0 +} + +// ContainerRemove indicates an expected call of ContainerRemove +func (mr *MockMobyMockRecorder) ContainerRemove(ctx, containerID, options interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContainerRemove", reflect.TypeOf((*MockMoby)(nil).ContainerRemove), ctx, containerID, options) +} + +// ImageRemove mocks base method +func (m *MockMoby) ImageRemove(ctx context.Context, imageID string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) { + ret := m.ctrl.Call(m, "ImageRemove", ctx, imageID, options) + ret0, _ := ret[0].([]types.ImageDeleteResponseItem) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ImageRemove indicates an expected call of ImageRemove +func (mr *MockMobyMockRecorder) ImageRemove(ctx, imageID, options interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ImageRemove", reflect.TypeOf((*MockMoby)(nil).ImageRemove), ctx, imageID, options) +} + +// ContainerWait mocks base method +func (m *MockMoby) ContainerWait(ctx context.Context, containerID string, condition container.WaitCondition) (<-chan container.ContainerWaitOKBody, <-chan error) { + ret := m.ctrl.Call(m, "ContainerWait", ctx, containerID, condition) + ret0, _ := ret[0].(<-chan container.ContainerWaitOKBody) + ret1, _ := ret[1].(<-chan error) + return ret0, ret1 +} + +// ContainerWait indicates an expected call of ContainerWait +func (mr *MockMobyMockRecorder) ContainerWait(ctx, containerID, condition interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContainerWait", reflect.TypeOf((*MockMoby)(nil).ContainerWait), ctx, containerID, condition) +} + +// Info mocks base method +func (m *MockMoby) Info(ctx context.Context) (types.Info, error) { + ret := m.ctrl.Call(m, "Info", ctx) + ret0, _ := ret[0].(types.Info) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Info indicates an expected call of Info +func (mr *MockMobyMockRecorder) Info(ctx interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Info", reflect.TypeOf((*MockMoby)(nil).Info), ctx) +} diff --git a/domain/model/docker/options_test.go b/domain/model/docker/options_test.go new file mode 100644 index 00000000..de1a1c14 --- /dev/null +++ b/domain/model/docker/options_test.go @@ -0,0 +1,71 @@ +package docker_test + +import ( + "github.com/duck8823/duci/domain/model/docker" + "github.com/google/go-cmp/cmp" + "sort" + "testing" +) + +func TestEnvironments_ToArray(t *testing.T) { + var empty []string + for _, tt := range []struct { + in docker.Environments + want []string + }{ + { + in: docker.Environments{}, + want: empty, + }, + { + in: docker.Environments{ + "int": 19, + "string": "hello", + }, + want: []string{ + "int=19", + "string=hello", + }, + }, + } { + // when + got := tt.in.Array() + want := tt.want + sort.Strings(got) + sort.Strings(want) + + // then + if !cmp.Equal(got, want) { + t.Errorf("must be equal. but %+v", cmp.Diff(got, want)) + } + } +} + +func TestVolumes_Volumes(t *testing.T) { + for _, tt := range []struct { + in docker.Volumes + want map[string]struct{} + }{ + { + in: docker.Volumes{}, + want: make(map[string]struct{}), + }, + { + in: docker.Volumes{ + "/hoge/fuga:/hoge/hoge", + }, + want: map[string]struct{}{ + "/hoge/fuga": {}, + }, + }, + } { + // when + got := tt.in.Map() + want := tt.want + + // then + if !cmp.Equal(got, want) { + t.Errorf("must be equal. but %+v", cmp.Diff(got, want)) + } + } +} diff --git a/domain/model/docker/types_test.go b/domain/model/docker/types_test.go new file mode 100644 index 00000000..7fe983f3 --- /dev/null +++ b/domain/model/docker/types_test.go @@ -0,0 +1,105 @@ +package docker_test + +import ( + "fmt" + "github.com/duck8823/duci/domain/model/docker" + "github.com/google/go-cmp/cmp" + "github.com/labstack/gommon/random" + "testing" +) + +func TestTag_String(t *testing.T) { + // given + want := "hello" + + // and + sut := docker.Tag(want) + + // when + got := sut.String() + + // then + if got != want { + t.Errorf("must equal: want %s, got %s", want, got) + } +} + +func TestCommand_Slice(t *testing.T) { + // given + want := []string{"test", "./..."} + + // and + sut := docker.Command(want) + + // when + got := sut.Slice() + + // then + if !cmp.Equal(got, want) { + t.Errorf("must equal: want %+v, got %+v", want, got) + } +} + +func TestDockerfile_String(t *testing.T) { + // given + want := "duck8823/duci" + + // and + sut := docker.Dockerfile(want) + + // when + got := sut.String() + + // then + if got != want { + t.Errorf("must equal: want %s, got %s", want, got) + } +} + +func TestContainerID_String(t *testing.T) { + // given + want := random.String(16, random.Alphanumeric) + + // and + sut := docker.ContainerID(want) + + // when + got := sut.String() + + // then + if got != want { + t.Errorf("must equal: want %s, got %s", want, got) + } +} + +func TestExitCode_IsFailure(t *testing.T) { + // where + for _, tt := range []struct { + code int64 + want bool + }{ + { + code: 0, + want: false, + }, + { + code: -1, + want: true, + }, + { + code: 1, + want: true, + }, + } { + t.Run(fmt.Sprintf("when code is %+v", tt.code), func(t *testing.T) { + // given + sut := docker.ExitCode(tt.code) + + // expect + if sut.IsFailure() != tt.want { + t.Errorf("must be %+v, but got %+v", tt.want, sut.IsFailure()) + } + }) + + } +} From 4a47878ebd86a69f710af2adfd4e6f57b829aa56 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Tue, 11 Dec 2018 07:14:53 +0900 Subject: [PATCH 052/135] Fix exit code for success --- domain/model/docker/types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain/model/docker/types.go b/domain/model/docker/types.go index 7981e8e8..e3bacb42 100644 --- a/domain/model/docker/types.go +++ b/domain/model/docker/types.go @@ -37,5 +37,5 @@ type ExitCode int64 // IsFailure returns whether failure code or not func (c ExitCode) IsFailure() bool { - return c != 1 + return c != 0 } From e9dc806ca5a8644bb3ed4e73ad6afd1004840b93 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Tue, 11 Dec 2018 07:15:28 +0900 Subject: [PATCH 053/135] Change log logic --- domain/model/docker/log.go | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/domain/model/docker/log.go b/domain/model/docker/log.go index a68a5c26..6e0be265 100644 --- a/domain/model/docker/log.go +++ b/domain/model/docker/log.go @@ -18,27 +18,24 @@ type buildLogger struct { } // NewBuildLog return a instance of Log. -func NewBuildLog(r io.Reader) *buildLogger { +func NewBuildLog(r io.Reader) Log { return &buildLogger{bufio.NewReader(r)} } // ReadLine returns LogLine. func (l *buildLogger) ReadLine() (*LogLine, error) { for { - line, _, readErr := l.reader.ReadLine() - msg := extractMessage(line) - if readErr == io.EOF { - return &LogLine{Timestamp: now(), Message: msg}, readErr - } - if readErr != nil { - return nil, errors.WithStack(readErr) + line, _, err := l.reader.ReadLine() + if err != nil { + return nil, err } + msg := extractMessage(line) if len(msg) == 0 { continue } - return &LogLine{Timestamp: now(), Message: msg}, readErr + return &LogLine{Timestamp: now(), Message: msg}, nil } } @@ -47,26 +44,28 @@ type runLogger struct { } // NewRunLog returns a instance of Log -func NewRunLog(r io.Reader) *runLogger { +func NewRunLog(r io.Reader) Log { return &runLogger{bufio.NewReader(r)} } // ReadLine returns LogLine. func (l *runLogger) ReadLine() (*LogLine, error) { for { - line, _, readErr := l.reader.ReadLine() - if readErr != nil && readErr != io.EOF { - return nil, errors.WithStack(readErr) + line, _, err := l.reader.ReadLine() + if err != nil { + return nil, err } - messages, err := trimPrefix(line) + msg, err := trimPrefix(line) if err != nil { return nil, errors.WithStack(err) + } else if len(msg) == 0 { + continue } // prevent to CR - progress := bytes.Split(messages, []byte{'\r'}) - return &LogLine{Timestamp: now(), Message: string(progress[0])}, readErr + progress := bytes.Split(msg, []byte{'\r'}) + return &LogLine{Timestamp: now(), Message: string(progress[0])}, nil } } @@ -83,10 +82,10 @@ func trimPrefix(line []byte) ([]byte, error) { return []byte{}, nil } - // detect logstore prefix + // detect prefix // see https://godoc.org/github.com/docker/docker/client#Client.ContainerLogs if !((line[0] == 1 || line[0] == 2) && (line[1] == 0 && line[2] == 0 && line[3] == 0)) { - return nil, fmt.Errorf("invalid logstore prefix: %+v", line[:7]) + return nil, fmt.Errorf("invalid prefix: %+v", line[:7]) } return line[8:], nil } From 318d957dc216dd56b8dfd9d8dcfb056f60a8089e Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Thu, 13 Dec 2018 23:55:18 +0900 Subject: [PATCH 054/135] Add test cases for git --- domain/model/job/target/git/export_test.go | 77 ++++++++ domain/model/job/target/git/git.go | 2 + domain/model/job/target/git/git_test.go | 48 +++++ domain/model/job/target/git/http_client.go | 2 +- .../model/job/target/git/http_client_test.go | 138 +++++++++++++ domain/model/job/target/git/log.go | 15 +- domain/model/job/target/git/log_test.go | 81 ++++++++ domain/model/job/target/git/ssh_client.go | 2 +- .../model/job/target/git/ssh_client_test.go | 187 ++++++++++++++++++ 9 files changed, 539 insertions(+), 13 deletions(-) create mode 100644 domain/model/job/target/git/export_test.go create mode 100644 domain/model/job/target/git/git_test.go create mode 100644 domain/model/job/target/git/http_client_test.go create mode 100644 domain/model/job/target/git/log_test.go create mode 100644 domain/model/job/target/git/ssh_client_test.go diff --git a/domain/model/job/target/git/export_test.go b/domain/model/job/target/git/export_test.go new file mode 100644 index 00000000..6069b912 --- /dev/null +++ b/domain/model/job/target/git/export_test.go @@ -0,0 +1,77 @@ +package git + +import ( + "bufio" + "context" + "gopkg.in/src-d/go-git.v4" + "gopkg.in/src-d/go-git.v4/plumbing" + "time" +) + +type HttpGitClient = httpGitClient + +type SshGitClient = sshGitClient + +type CloneLogger = cloneLogger + +func (l *CloneLogger) SetReader(r *bufio.Reader) (reset func()) { + tmp := l.reader + l.reader = r + return func() { + l.reader = tmp + } +} + +func SetInstance(git Git) (reset func()) { + tmp := instance + instance = git + return func() { + instance = tmp + } +} + +func SetPlainCloneFunc(f func(path string, isBare bool, o *git.CloneOptions) (*git.Repository, error)) (reset func()) { + tmp := plainClone + plainClone = f + return func() { + plainClone = tmp + } +} + +func SetNowFunc(f func() time.Time) (reset func()) { + tmp := now + now = f + return func() { + now = tmp + } +} + +type MockTargetSource struct { + URL string + Ref string + SHA plumbing.Hash +} + +func (t *MockTargetSource) GetCloneURL() string { + return t.URL +} + +func (t *MockTargetSource) GetSSHURL() string { + return t.URL +} + +func (t *MockTargetSource) GetRef() string { + return t.Ref +} + +func (t *MockTargetSource) GetSHA() plumbing.Hash { + return t.SHA +} + +func (l *ProgressLogger) SetContext(ctx context.Context) (reset func()) { + tmp := l.ctx + l.ctx = ctx + return func() { + l.ctx = tmp + } +} diff --git a/domain/model/job/target/git/git.go b/domain/model/job/target/git/git.go index 969a5bca..1ed67916 100644 --- a/domain/model/job/target/git/git.go +++ b/domain/model/job/target/git/git.go @@ -9,6 +9,8 @@ import ( var instance Git +var plainClone = git.PlainClone + // TargetSource is a interface returns clone URLs, Ref and SHA for target type TargetSource interface { GetSSHURL() string diff --git a/domain/model/job/target/git/git_test.go b/domain/model/job/target/git/git_test.go new file mode 100644 index 00000000..b62d9022 --- /dev/null +++ b/domain/model/job/target/git/git_test.go @@ -0,0 +1,48 @@ +package git_test + +import ( + "github.com/duck8823/duci/domain/model/job/target/git" + "github.com/google/go-cmp/cmp" + "testing" +) + +func TestGetInstance(t *testing.T) { + t.Run("when instance is nil", func(t *testing.T) { + // given + defer git.SetInstance(nil)() + + // when + got, err := git.GetInstance() + + // then + if err == nil { + t.Error("error must not be nil") + } + + // and + if got != nil { + t.Errorf("must be nil, but got %+v", err) + } + }) + + t.Run("when instance is not nil", func(t *testing.T) { + // given + want := &git.HttpGitClient{} + + // and + defer git.SetInstance(want)() + + // when + got, err := git.GetInstance() + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + if !cmp.Equal(got, want) { + t.Errorf("must be equal, but %+v", cmp.Diff(got, want)) + } + }) +} diff --git a/domain/model/job/target/git/http_client.go b/domain/model/job/target/git/http_client.go index c830c5a9..d4797cf7 100644 --- a/domain/model/job/target/git/http_client.go +++ b/domain/model/job/target/git/http_client.go @@ -24,7 +24,7 @@ func InitializeWithHTTP(logFunc runner.LogFunc) error { // Clone a repository into the path with target source. func (s *httpGitClient) Clone(ctx context.Context, dir string, src TargetSource) error { - gitRepository, err := git.PlainClone(dir, false, &git.CloneOptions{ + gitRepository, err := plainClone(dir, false, &git.CloneOptions{ URL: src.GetCloneURL(), Progress: &ProgressLogger{ctx: ctx, LogFunc: s.LogFunc}, ReferenceName: plumbing.ReferenceName(src.GetRef()), diff --git a/domain/model/job/target/git/http_client_test.go b/domain/model/job/target/git/http_client_test.go new file mode 100644 index 00000000..b32b2e01 --- /dev/null +++ b/domain/model/job/target/git/http_client_test.go @@ -0,0 +1,138 @@ +package git_test + +import ( + "context" + "errors" + "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/job/target/git" + "github.com/duck8823/duci/domain/model/runner" + "github.com/labstack/gommon/random" + go_git "gopkg.in/src-d/go-git.v4" + "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/object" + "os" + "path/filepath" + "testing" +) + +func TestInitializeWithHTTP(t *testing.T) { + t.Run("when instance is nil", func(t *testing.T) { + // given + defer git.SetInstance(nil)() + + // when + err := git.InitializeWithHTTP(func(_ context.Context, _ job.Log) {}) + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + }) + + t.Run("when instance is not nil", func(t *testing.T) { + // given + defer git.SetInstance(&git.HttpGitClient{})() + + // when + err := git.InitializeWithHTTP(func(_ context.Context, _ job.Log) {}) + + // then + if err == nil { + t.Error("error must not be nil") + } + }) +} + +func TestHttpGitClient_Clone(t *testing.T) { + t.Run("when failure git clone", func(t *testing.T) { + // given + reset := git.SetPlainCloneFunc(func(_ string, _ bool, _ *go_git.CloneOptions) (*go_git.Repository, error) { + return nil, errors.New("test") + }) + defer reset() + + // and + sut := &git.HttpGitClient{LogFunc: runner.NothingToDo} + + // expect + if err := sut.Clone( + context.Background(), + "/path/to/dummy", + &git.MockTargetSource{}, + ); err == nil { + t.Error("error must not nil.") + } + }) + + t.Run("when success git clone and checkout", func(t *testing.T) { + // given + var hash plumbing.Hash + defer git.SetPlainCloneFunc(func(tmpDir string, _ bool, _ *go_git.CloneOptions) (*go_git.Repository, error) { + // git init + repo, err := go_git.PlainInit(tmpDir, false) + if err != nil { + t.Fatalf("error occur: %+v", err) + } + + w, err := repo.Worktree() + if err != nil { + t.Fatalf("error occur: %+v", err) + } + + // initial commit ( for success checkout ) + hash, err = w.Commit("init. commit", &go_git.CommitOptions{Author: &object.Signature{}}) + if err != nil { + t.Fatalf("error occur: %+v", err) + } + + return repo, nil + })() + + tmpDir, reset := createTmpDir(t) + defer reset() + + // amd + sut := &git.HttpGitClient{LogFunc: runner.NothingToDo} + + // expect + if err := sut.Clone(context.Background(), tmpDir, &git.MockTargetSource{Ref: "HEAD", SHA: hash}); err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + }) + + t.Run("when success git clone but failure checkout", func(t *testing.T) { + // given + defer git.SetPlainCloneFunc(func(tmpDir string, _ bool, _ *go_git.CloneOptions) (*go_git.Repository, error) { + // git init + repo, err := go_git.PlainInit(tmpDir, false) + if err != nil { + t.Fatalf("error occur: %+v", err) + } + + return repo, nil + })() + + tmpDir, reset := createTmpDir(t) + defer reset() + + // and + sut := &git.HttpGitClient{LogFunc: runner.NothingToDo} + + // expect + if err := sut.Clone(context.Background(), tmpDir, &git.MockTargetSource{Ref: "HEAD"}); err == nil { + t.Error("error must not be nil") + } + }) +} + +func createTmpDir(t *testing.T) (tmpDir string, reset func()) { + t.Helper() + + dir := filepath.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + if err := os.MkdirAll(dir, 0700); err != nil { + t.Fatalf("error occur: %+v", err) + } + return dir, func() { + _ = os.RemoveAll(dir) + } +} diff --git a/domain/model/job/target/git/log.go b/domain/model/job/target/git/log.go index 61939eb8..383efdcb 100644 --- a/domain/model/job/target/git/log.go +++ b/domain/model/job/target/git/log.go @@ -6,8 +6,6 @@ import ( "context" "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/runner" - "github.com/pkg/errors" - "io" "regexp" "time" ) @@ -21,21 +19,16 @@ type cloneLogger struct { // ReadLine returns LogLine. func (l *cloneLogger) ReadLine() (*job.LogLine, error) { for { - line, _, readErr := l.reader.ReadLine() - msg := string(line) - - if readErr == io.EOF { - return &job.LogLine{Timestamp: now(), Message: msg}, readErr - } - if readErr != nil { - return nil, errors.WithStack(readErr) + line, _, err := l.reader.ReadLine() + if err != nil { + return nil, err } if len(line) == 0 || rep.Match(line) { continue } - return &job.LogLine{Timestamp: now(), Message: msg}, readErr + return &job.LogLine{Timestamp: now(), Message: string(line)}, nil } } diff --git a/domain/model/job/target/git/log_test.go b/domain/model/job/target/git/log_test.go new file mode 100644 index 00000000..575d7473 --- /dev/null +++ b/domain/model/job/target/git/log_test.go @@ -0,0 +1,81 @@ +package git_test + +import ( + "bufio" + "context" + "fmt" + "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/job/target/git" + "github.com/google/go-cmp/cmp" + "io" + "strings" + "testing" + "time" +) + +func TestCloneLogger_ReadLine(t *testing.T) { + // given + now := time.Now() + defer git.SetNowFunc(func() time.Time { + return now + })() + + // and + want := &job.LogLine{ + Timestamp: now, + Message: "Hello World", + } + + // and + sut := &git.CloneLogger{} + defer sut.SetReader(bufio.NewReader(strings.NewReader(fmt.Sprintf("%s\n\n", want.Message))))() + + // when + got, err := sut.ReadLine() + + // then + if err != nil { + t.Errorf("err must be nil, but got %+v", err) + } + + // and + if !cmp.Equal(got, want) { + t.Errorf("must be equal, but %+v", cmp.Diff(got, want)) + } + + // when + got, err = sut.ReadLine() + + // then + if err != io.EOF { + t.Errorf("must be equal io.EOF, but got %+v", err) + } +} + +func TestProgressLogger_Write(t *testing.T) { + // given + var got string + sut := &git.ProgressLogger{ + LogFunc: func(_ context.Context, log job.Log) { + line, _ := log.ReadLine() + got = line.Message + }, + } + sut.SetContext(context.Background()) + + // and + want := "hello world" + + // when + _, err := sut.Write([]byte(want)) + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + if got != want { + t.Errorf("must be equal, but not\n%+v", cmp.Diff(got, want)) + } +} diff --git a/domain/model/job/target/git/ssh_client.go b/domain/model/job/target/git/ssh_client.go index db34bd26..b48c5f1a 100644 --- a/domain/model/job/target/git/ssh_client.go +++ b/domain/model/job/target/git/ssh_client.go @@ -32,7 +32,7 @@ func InitializeWithSSH(path string, logFunc runner.LogFunc) error { // Clone a repository into the path with target source. func (s *sshGitClient) Clone(ctx context.Context, dir string, src TargetSource) error { - gitRepository, err := git.PlainClone(dir, false, &git.CloneOptions{ + gitRepository, err := plainClone(dir, false, &git.CloneOptions{ URL: src.GetSSHURL(), Auth: s.auth, Progress: &ProgressLogger{ctx: ctx, LogFunc: s.LogFunc}, diff --git a/domain/model/job/target/git/ssh_client_test.go b/domain/model/job/target/git/ssh_client_test.go new file mode 100644 index 00000000..35d93d69 --- /dev/null +++ b/domain/model/job/target/git/ssh_client_test.go @@ -0,0 +1,187 @@ +package git_test + +import ( + "context" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "errors" + "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/job/target/git" + "github.com/duck8823/duci/domain/model/runner" + "github.com/labstack/gommon/random" + go_git "gopkg.in/src-d/go-git.v4" + "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/object" + "os" + "path/filepath" + "testing" +) + +func TestInitializeWithSSH(t *testing.T) { + t.Run("when instance is nil", func(t *testing.T) { + t.Run("with correct key path", func(t *testing.T) { + // given + defer git.SetInstance(nil)() + + // and + path, reset := createTemporaryKey(t) + defer reset() + + // when + err := git.InitializeWithSSH(path, func(_ context.Context, _ job.Log) {}) + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + }) + + t.Run("with wrong key path", func(t *testing.T) { + // given + defer git.SetInstance(nil)() + + // when + err := git.InitializeWithSSH("/path/to/nothing", func(_ context.Context, _ job.Log) {}) + + // then + if err == nil { + t.Error("error must not be nil") + } + }) + }) + + t.Run("when instance is not nil", func(t *testing.T) { + // given + defer git.SetInstance(&git.SshGitClient{})() + + // and + path, reset := createTemporaryKey(t) + defer reset() + + // when + err := git.InitializeWithSSH(path, func(_ context.Context, _ job.Log) {}) + + // then + if err == nil { + t.Error("error must not be nil") + } + }) +} + +func TestSshGitClient_Clone(t *testing.T) { + t.Run("when failure git clone", func(t *testing.T) { + // given + reset := git.SetPlainCloneFunc(func(_ string, _ bool, _ *go_git.CloneOptions) (*go_git.Repository, error) { + return nil, errors.New("test") + }) + defer reset() + + // and + sut := &git.SshGitClient{LogFunc: runner.NothingToDo} + + // expect + if err := sut.Clone( + context.Background(), + "/path/to/dummy", + &git.MockTargetSource{}, + ); err == nil { + t.Error("error must not nil.") + } + }) + + t.Run("when success git clone and checkout", func(t *testing.T) { + // given + var hash plumbing.Hash + defer git.SetPlainCloneFunc(func(tmpDir string, _ bool, _ *go_git.CloneOptions) (*go_git.Repository, error) { + // git init + repo, err := go_git.PlainInit(tmpDir, false) + if err != nil { + t.Fatalf("error occur: %+v", err) + } + + w, err := repo.Worktree() + if err != nil { + t.Fatalf("error occur: %+v", err) + } + + // initial commit ( for success checkout ) + hash, err = w.Commit("init. commit", &go_git.CommitOptions{Author: &object.Signature{}}) + if err != nil { + t.Fatalf("error occur: %+v", err) + } + + return repo, nil + })() + + tmpDir, reset := createTmpDir(t) + defer reset() + + // amd + sut := &git.SshGitClient{LogFunc: runner.NothingToDo} + + // expect + if err := sut.Clone(context.Background(), tmpDir, &git.MockTargetSource{Ref: "HEAD", SHA: hash}); err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + }) + + t.Run("when success git clone but failure checkout", func(t *testing.T) { + // given + defer git.SetPlainCloneFunc(func(tmpDir string, _ bool, _ *go_git.CloneOptions) (*go_git.Repository, error) { + // git init + repo, err := go_git.PlainInit(tmpDir, false) + if err != nil { + t.Fatalf("error occur: %+v", err) + } + + return repo, nil + })() + + tmpDir, reset := createTmpDir(t) + defer reset() + + // and + sut := &git.SshGitClient{LogFunc: runner.NothingToDo} + + // expect + if err := sut.Clone(context.Background(), tmpDir, &git.MockTargetSource{Ref: "HEAD"}); err == nil { + t.Error("error must not be nil") + } + }) +} + +func createTemporaryKey(t *testing.T) (path string, reset func()) { + t.Helper() + + privateKey, err := rsa.GenerateKey(rand.Reader, 256) + if err != nil { + t.Fatalf("error occur: %+v", err) + } + privateKeyDer := x509.MarshalPKCS1PrivateKey(privateKey) + privateKeyBlock := pem.Block{ + Type: "RSA PRIVATE KEY", + Headers: nil, + Bytes: privateKeyDer, + } + privateKeyPem := string(pem.EncodeToMemory(&privateKeyBlock)) + + tempDir := filepath.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + if err := os.MkdirAll(tempDir, 0700); err != nil { + t.Fatalf("error occur: %+v", err) + } + keyPath := filepath.Join(tempDir, "id_rsa") + file, err := os.OpenFile(keyPath, os.O_WRONLY|os.O_CREATE, 0600) + if err != nil { + t.Fatalf("error occur: %+v", err) + } + + if _, err := file.WriteString(privateKeyPem); err != nil { + t.Fatalf("error occur: %+v", err) + } + + return keyPath, func() { + _ = os.RemoveAll(tempDir) + } +} From 255afa42be8f92f95b9b39fea21274c7aa6698a1 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 15 Dec 2018 09:50:17 +0900 Subject: [PATCH 055/135] Add test cases for github --- domain/model/job/target/github/export_test.go | 42 +++ domain/model/job/target/github/github_test.go | 263 ++++++++++++++++++ .../job/target/github/repository_test.go | 124 +++++++++ domain/model/job/target/github/status.go | 4 +- domain/model/job/target/github/status_test.go | 43 +++ .../job/target/github/target_point_test.go | 43 +++ .../job/target/github/target_source_test.go | 46 +++ 7 files changed, 563 insertions(+), 2 deletions(-) create mode 100644 domain/model/job/target/github/export_test.go create mode 100644 domain/model/job/target/github/github_test.go create mode 100644 domain/model/job/target/github/repository_test.go create mode 100644 domain/model/job/target/github/status_test.go create mode 100644 domain/model/job/target/github/target_point_test.go create mode 100644 domain/model/job/target/github/target_source_test.go diff --git a/domain/model/job/target/github/export_test.go b/domain/model/job/target/github/export_test.go new file mode 100644 index 00000000..3694c5cf --- /dev/null +++ b/domain/model/job/target/github/export_test.go @@ -0,0 +1,42 @@ +package github + +import ( + "context" + "github.com/google/go-github/github" +) + +type StubClient struct { +} + +func (*StubClient) GetPullRequest(ctx context.Context, repo Repository, num int) (*github.PullRequest, error) { + return nil, nil +} + +func (*StubClient) CreateCommitStatus(ctx context.Context, status CommitStatus) error { + return nil +} + +type MockRepository struct { + FullName string + URL string +} + +func (r *MockRepository) GetFullName() string { + return r.FullName +} + +func (r *MockRepository) GetSSHURL() string { + return r.URL +} + +func (r *MockRepository) GetCloneURL() string { + return r.URL +} + +func SetInstance(github GitHub) (reset func()) { + tmp := instance + instance = github + return func() { + instance = tmp + } +} diff --git a/domain/model/job/target/github/github_test.go b/domain/model/job/target/github/github_test.go new file mode 100644 index 00000000..4adaf2bf --- /dev/null +++ b/domain/model/job/target/github/github_test.go @@ -0,0 +1,263 @@ +package github_test + +import ( + "context" + "fmt" + "github.com/duck8823/duci/domain/model/job/target/github" + "github.com/google/go-cmp/cmp" + go_github "github.com/google/go-github/github" + "github.com/labstack/gommon/random" + "gopkg.in/h2non/gock.v1" + "gopkg.in/src-d/go-git.v4/plumbing" + "net/url" + "testing" +) + +func TestInitialize(t *testing.T) { + t.Run("when instance is nil", func(t *testing.T) { + // given + defer github.SetInstance(nil)() + + // when + err := github.Initialize("github_api_token") + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + }) + + t.Run("when instance is not nil", func(t *testing.T) { + // given + defer github.SetInstance(&github.StubClient{})() + + // when + err := github.Initialize("github_api_token") + + // then + if err == nil { + t.Error("error must not be nil") + } + }) +} + +func TestGetInstance(t *testing.T) { + t.Run("when instance is nil", func(t *testing.T) { + // given + defer github.SetInstance(nil)() + + // when + got, err := github.GetInstance() + + // then + if err == nil { + t.Error("error must not be nil") + } + + // and + if got != nil { + t.Errorf("must be nil, but got %+v", got) + } + }) + + t.Run("when instance is not nil", func(t *testing.T) { + // given + want := &github.StubClient{} + + // and + defer github.SetInstance(want)() + + // when + got, err := github.GetInstance() + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + if !cmp.Equal(got, want) { + t.Errorf("must be equal, but %+v", cmp.Diff(got, want)) + } + + }) +} + +func TestClient_GetPullRequest(t *testing.T) { + // given + _ = github.Initialize("github_api_token") + sut, err := github.GetInstance() + if err != nil { + t.Fatalf("error occurred. %+v", err) + } + + t.Run("when github server returns status ok", func(t *testing.T) { + // given + repo := &github.MockRepository{ + FullName: "duck8823/duci", + } + num := 19 + + // and + want := "hello world" + + // and + gock.New("https://api.github.com"). + Get(fmt.Sprintf("/repos/%s/pulls/%d", repo.FullName, num)). + Reply(200). + JSON(&go_github.PullRequest{ + Title: go_github.String(want), + }) + defer gock.Clean() + + // when + got, err := sut.GetPullRequest(context.Background(), repo, num) + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + if got.GetTitle() != want { + t.Errorf("must be equal, but diff %+v", cmp.Diff(got.GetTitle(), want)) + } + }) + + t.Run("when github server returns status not found", func(t *testing.T) { + // given + repo := &github.MockRepository{ + FullName: "duck8823/duci", + } + num := 19 + + // and + gock.New("https://api.github.com"). + Get(fmt.Sprintf("/repos/%s/pulls/%d", repo.FullName, num)). + Reply(404) + defer gock.Clean() + + // when + pr, err := sut.GetPullRequest(context.Background(), repo, num) + + // then + if err == nil { + t.Error("error must not be nil") + } + + // and + if pr != nil { + t.Errorf("must be nil, but got %+v", pr) + } + }) + + t.Run("with invalid repository", func(t *testing.T) { + // given + repo := &github.MockRepository{ + FullName: "", + } + + // expect + if _, err := sut.GetPullRequest(context.Background(), repo, 19); err == nil { + t.Error("error must not be nil") + } + }) +} + +func TestClient_CreateCommitStatus(t *testing.T) { + // given + _ = github.Initialize("github_api_token") + sut, err := github.GetInstance() + if err != nil { + t.Fatalf("error occurred. %+v", err) + } + + t.Run("when github server returns status ok", func(t *testing.T) { + // given + status := github.CommitStatus{ + TargetSource: &github.TargetSource{ + Repository: &github.MockRepository{ + FullName: "duck8823/duci", + }, + SHA: plumbing.ComputeHash(plumbing.AnyObject, []byte(random.String(16, random.Alphanumeric))), + }, + State: github.SUCCESS, + Description: "hello world", + Context: "duci test", + TargetURL: &url.URL{ + Scheme: "http", + Host: "example.com", + }, + } + + // and + gock.New("https://api.github.com"). + Post(fmt.Sprintf("/repos/%s/statuses/%s", status.TargetSource.Repository.GetFullName(), status.TargetSource.SHA)). + Reply(200) + defer gock.Clean() + + // expect + if err := sut.CreateCommitStatus( + context.Background(), + status, + ); err != nil { + t.Errorf("error must be nil: but got %+v", err) + } + }) + + t.Run("when github server returns status not found", func(t *testing.T) { + // given + status := github.CommitStatus{ + TargetSource: &github.TargetSource{ + Repository: &github.MockRepository{ + FullName: "duck8823/duci", + }, + SHA: plumbing.ComputeHash(plumbing.AnyObject, []byte(random.String(16, random.Alphanumeric))), + }, + State: github.SUCCESS, + Description: "hello world", + Context: "duci test", + TargetURL: &url.URL{ + Scheme: "http", + Host: "example.com", + }, + } + + // and + gock.New("https://api.github.com"). + Post(fmt.Sprintf("/repos/%s/statuses/%s", status.TargetSource.Repository.GetFullName(), status.TargetSource.SHA)). + Reply(404) + defer gock.Clean() + + // expect + if err := sut.CreateCommitStatus( + context.Background(), + status, + ); err == nil { + t.Error("error must not be nil") + } + }) + + t.Run("with invalid repository", func(t *testing.T) { + // given + status := github.CommitStatus{ + TargetSource: &github.TargetSource{ + Repository: &github.MockRepository{ + FullName: "", + }, + }, + TargetURL: &url.URL{ + Scheme: "http", + Host: "example.com", + }, + } + + // expect + if err := sut.CreateCommitStatus( + context.Background(), + status, + ); err == nil { + t.Error("error must not be nil") + } + }) +} diff --git a/domain/model/job/target/github/repository_test.go b/domain/model/job/target/github/repository_test.go new file mode 100644 index 00000000..28b9c283 --- /dev/null +++ b/domain/model/job/target/github/repository_test.go @@ -0,0 +1,124 @@ +package github_test + +import ( + "fmt" + "github.com/duck8823/duci/domain/model/job/target/github" + "github.com/google/go-cmp/cmp" + "testing" +) + +func TestRepositoryName_Owner(t *testing.T) { + t.Run("with correct name", func(t *testing.T) { + // given + want := "duck8823" + + // and + sut := github.RepositoryName(fmt.Sprintf("%s/duci", want)) + + // when + got, err := sut.Owner() + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + if got != want { + t.Errorf("must be equal, but %+v", cmp.Diff(got, want)) + } + }) + + t.Run("with invalid name", func(t *testing.T) { + // where + for _, tt := range []struct { + name string + }{ + { + name: "", + }, + { + name: "duck8823", + }, + { + name: "duck8823/duci/domain", + }, + } { + t.Run(fmt.Sprintf("when name is %s", tt.name), func(t *testing.T) { + // given + sut := github.RepositoryName(tt.name) + + // when + got, err := sut.Owner() + + // then + if err == nil { + t.Error("error must not be nil") + } + + // and + if got != "" { + t.Errorf("must be empty, but got %+v", got) + } + }) + } + }) +} + +func TestRepositoryName_Repo(t *testing.T) { + t.Run("with correct name", func(t *testing.T) { + // given + want := "duci" + + // and + sut := github.RepositoryName(fmt.Sprintf("duck8823/%s", want)) + + // when + got, err := sut.Repo() + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + if got != want { + t.Errorf("must be equal, but %+v", cmp.Diff(got, want)) + } + }) + + t.Run("with invalid name", func(t *testing.T) { + // where + for _, tt := range []struct { + name string + }{ + { + name: "", + }, + { + name: "duci", + }, + { + name: "duck8823/duci/domain", + }, + } { + t.Run(fmt.Sprintf("when name is %s", tt.name), func(t *testing.T) { + // given + sut := github.RepositoryName(tt.name) + + // when + got, err := sut.Repo() + + // then + if err == nil { + t.Error("error must not be nil") + } + + // and + if got != "" { + t.Errorf("must be empty, but got %+v", got) + } + }) + } + }) +} diff --git a/domain/model/job/target/github/status.go b/domain/model/job/target/github/status.go index 946e2d2d..b051c0ec 100644 --- a/domain/model/job/target/github/status.go +++ b/domain/model/job/target/github/status.go @@ -12,8 +12,8 @@ func (s State) String() string { type Description string func (d Description) TrimmedString() string { - if len(d) >= 50 { - return string([]rune(d)[:46]) + "..." + if len(d) > 50 { + return string([]rune(d)[:47]) + "..." } return string(d) } diff --git a/domain/model/job/target/github/status_test.go b/domain/model/job/target/github/status_test.go new file mode 100644 index 00000000..9c499671 --- /dev/null +++ b/domain/model/job/target/github/status_test.go @@ -0,0 +1,43 @@ +package github_test + +import ( + "github.com/duck8823/duci/domain/model/job/target/github" + "github.com/google/go-cmp/cmp" + "testing" +) + +func TestDescription_TrimmedString(t *testing.T) { + // where + for _, tt := range []struct { + in string + want string + }{ + { + in: "hello world", + want: "hello world", + }, + { + in: "123456789012345678901234567890123456789012345678901234567890", + want: "12345678901234567890123456789012345678901234567...", + }, + { + in: "12345678901234567890123456789012345678901234567890", + want: "12345678901234567890123456789012345678901234567890", + }, + { + in: "123456789012345678901234567890123456789012345678901", + want: "12345678901234567890123456789012345678901234567...", + }, + } { + // given + sut := github.Description(tt.in) + + // when + got := sut.TrimmedString() + + // then + if got != tt.want { + t.Errorf("must be equal, but %+v", cmp.Diff(got, tt.want)) + } + } +} diff --git a/domain/model/job/target/github/target_point_test.go b/domain/model/job/target/github/target_point_test.go new file mode 100644 index 00000000..12a1a366 --- /dev/null +++ b/domain/model/job/target/github/target_point_test.go @@ -0,0 +1,43 @@ +package github_test + +import ( + "github.com/duck8823/duci/domain/model/job/target/github" + "github.com/google/go-cmp/cmp" + "testing" +) + +func TestSimpleTargetPoint_GetRef(t *testing.T) { + // given + want := "ref" + + // and + sut := &github.SimpleTargetPoint{ + Ref: want, + } + + // when + got := sut.GetRef() + + // then + if got != want { + t.Errorf("must be equal, but %+v", cmp.Diff(got, want)) + } +} + +func TestSimpleTargetPoint_GetHead(t *testing.T) { + // given + want := "sha" + + // and + sut := &github.SimpleTargetPoint{ + SHA: want, + } + + // when + got := sut.GetHead() + + // then + if got != want { + t.Errorf("must be equal, but %+v", cmp.Diff(got, want)) + } +} diff --git a/domain/model/job/target/github/target_source_test.go b/domain/model/job/target/github/target_source_test.go new file mode 100644 index 00000000..c806ad4f --- /dev/null +++ b/domain/model/job/target/github/target_source_test.go @@ -0,0 +1,46 @@ +package github_test + +import ( + "github.com/duck8823/duci/domain/model/job/target/github" + "github.com/google/go-cmp/cmp" + "github.com/labstack/gommon/random" + "gopkg.in/src-d/go-git.v4/plumbing" + "testing" +) + +func TestTargetSource_GetRef(t *testing.T) { + // given + want := "ref" + + // and + sut := &github.TargetSource{ + Ref: want, + } + + // when + got := sut.GetRef() + + // then + if got != want { + t.Errorf("must be euqal, but %+v", cmp.Diff(got, want)) + } + +} + +func TestTargetSource_GetSHA(t *testing.T) { + // given + want := plumbing.ComputeHash(plumbing.AnyObject, []byte(random.String(16, random.Alphanumeric))) + + // and + sut := &github.TargetSource{ + SHA: want, + } + + // when + got := sut.GetSHA() + + // then + if got != want { + t.Errorf("must be euqal, but %+v", cmp.Diff(got, want)) + } +} From 815ee77695a0851c55a8382dafce6ee9a405f0c3 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 15 Dec 2018 10:59:43 +0900 Subject: [PATCH 056/135] mockgen git and github --- domain/model/job/target/git/mock_git/git.go | 119 ++++++++++++++++++ .../job/target/github/mock_github/github.go | 61 +++++++++ 2 files changed, 180 insertions(+) create mode 100644 domain/model/job/target/git/mock_git/git.go create mode 100644 domain/model/job/target/github/mock_github/github.go diff --git a/domain/model/job/target/git/mock_git/git.go b/domain/model/job/target/git/mock_git/git.go new file mode 100644 index 00000000..a2a27d47 --- /dev/null +++ b/domain/model/job/target/git/mock_git/git.go @@ -0,0 +1,119 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: domain/model/job/target/git/git.go + +// Package mock_git is a generated GoMock package. +package mock_git + +import ( + context "context" + git "github.com/duck8823/duci/domain/model/job/target/git" + gomock "github.com/golang/mock/gomock" + plumbing "gopkg.in/src-d/go-git.v4/plumbing" + reflect "reflect" +) + +// MockTargetSource is a mock of TargetSource interface +type MockTargetSource struct { + ctrl *gomock.Controller + recorder *MockTargetSourceMockRecorder +} + +// MockTargetSourceMockRecorder is the mock recorder for MockTargetSource +type MockTargetSourceMockRecorder struct { + mock *MockTargetSource +} + +// NewMockTargetSource creates a new mock instance +func NewMockTargetSource(ctrl *gomock.Controller) *MockTargetSource { + mock := &MockTargetSource{ctrl: ctrl} + mock.recorder = &MockTargetSourceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockTargetSource) EXPECT() *MockTargetSourceMockRecorder { + return m.recorder +} + +// GetSSHURL mocks base method +func (m *MockTargetSource) GetSSHURL() string { + ret := m.ctrl.Call(m, "GetSSHURL") + ret0, _ := ret[0].(string) + return ret0 +} + +// GetSSHURL indicates an expected call of GetSSHURL +func (mr *MockTargetSourceMockRecorder) GetSSHURL() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSSHURL", reflect.TypeOf((*MockTargetSource)(nil).GetSSHURL)) +} + +// GetCloneURL mocks base method +func (m *MockTargetSource) GetCloneURL() string { + ret := m.ctrl.Call(m, "GetCloneURL") + ret0, _ := ret[0].(string) + return ret0 +} + +// GetCloneURL indicates an expected call of GetCloneURL +func (mr *MockTargetSourceMockRecorder) GetCloneURL() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCloneURL", reflect.TypeOf((*MockTargetSource)(nil).GetCloneURL)) +} + +// GetRef mocks base method +func (m *MockTargetSource) GetRef() string { + ret := m.ctrl.Call(m, "GetRef") + ret0, _ := ret[0].(string) + return ret0 +} + +// GetRef indicates an expected call of GetRef +func (mr *MockTargetSourceMockRecorder) GetRef() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRef", reflect.TypeOf((*MockTargetSource)(nil).GetRef)) +} + +// GetSHA mocks base method +func (m *MockTargetSource) GetSHA() plumbing.Hash { + ret := m.ctrl.Call(m, "GetSHA") + ret0, _ := ret[0].(plumbing.Hash) + return ret0 +} + +// GetSHA indicates an expected call of GetSHA +func (mr *MockTargetSourceMockRecorder) GetSHA() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSHA", reflect.TypeOf((*MockTargetSource)(nil).GetSHA)) +} + +// MockGit is a mock of Git interface +type MockGit struct { + ctrl *gomock.Controller + recorder *MockGitMockRecorder +} + +// MockGitMockRecorder is the mock recorder for MockGit +type MockGitMockRecorder struct { + mock *MockGit +} + +// NewMockGit creates a new mock instance +func NewMockGit(ctrl *gomock.Controller) *MockGit { + mock := &MockGit{ctrl: ctrl} + mock.recorder = &MockGitMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockGit) EXPECT() *MockGitMockRecorder { + return m.recorder +} + +// Clone mocks base method +func (m *MockGit) Clone(ctx context.Context, dir string, src git.TargetSource) error { + ret := m.ctrl.Call(m, "Clone", ctx, dir, src) + ret0, _ := ret[0].(error) + return ret0 +} + +// Clone indicates an expected call of Clone +func (mr *MockGitMockRecorder) Clone(ctx, dir, src interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Clone", reflect.TypeOf((*MockGit)(nil).Clone), ctx, dir, src) +} diff --git a/domain/model/job/target/github/mock_github/github.go b/domain/model/job/target/github/mock_github/github.go new file mode 100644 index 00000000..ea5b4cd3 --- /dev/null +++ b/domain/model/job/target/github/mock_github/github.go @@ -0,0 +1,61 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: domain/model/job/target/github/github.go + +// Package mock_github is a generated GoMock package. +package mock_github + +import ( + context "context" + github "github.com/duck8823/duci/domain/model/job/target/github" + gomock "github.com/golang/mock/gomock" + github0 "github.com/google/go-github/github" + reflect "reflect" +) + +// MockGitHub is a mock of GitHub interface +type MockGitHub struct { + ctrl *gomock.Controller + recorder *MockGitHubMockRecorder +} + +// MockGitHubMockRecorder is the mock recorder for MockGitHub +type MockGitHubMockRecorder struct { + mock *MockGitHub +} + +// NewMockGitHub creates a new mock instance +func NewMockGitHub(ctrl *gomock.Controller) *MockGitHub { + mock := &MockGitHub{ctrl: ctrl} + mock.recorder = &MockGitHubMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockGitHub) EXPECT() *MockGitHubMockRecorder { + return m.recorder +} + +// GetPullRequest mocks base method +func (m *MockGitHub) GetPullRequest(ctx context.Context, repo github.Repository, num int) (*github0.PullRequest, error) { + ret := m.ctrl.Call(m, "GetPullRequest", ctx, repo, num) + ret0, _ := ret[0].(*github0.PullRequest) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetPullRequest indicates an expected call of GetPullRequest +func (mr *MockGitHubMockRecorder) GetPullRequest(ctx, repo, num interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPullRequest", reflect.TypeOf((*MockGitHub)(nil).GetPullRequest), ctx, repo, num) +} + +// CreateCommitStatus mocks base method +func (m *MockGitHub) CreateCommitStatus(ctx context.Context, status github.CommitStatus) error { + ret := m.ctrl.Call(m, "CreateCommitStatus", ctx, status) + ret0, _ := ret[0].(error) + return ret0 +} + +// CreateCommitStatus indicates an expected call of CreateCommitStatus +func (mr *MockGitHubMockRecorder) CreateCommitStatus(ctx, status interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateCommitStatus", reflect.TypeOf((*MockGitHub)(nil).CreateCommitStatus), ctx, status) +} From 6eb8e2295cbf0905e11bb4ed5616360da8cba5c4 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sun, 16 Dec 2018 10:26:10 +0900 Subject: [PATCH 057/135] [wip] for testable --- domain/model/job/target/export_test.go | 30 ++++++ domain/model/job/target/github_push.go | 32 ++++--- domain/model/job/target/github_push_test.go | 101 ++++++++++++++++++++ domain/model/job/target/local.go | 15 ++- presentation/controller/webhook/handler.go | 22 +++-- 5 files changed, 176 insertions(+), 24 deletions(-) create mode 100644 domain/model/job/target/export_test.go create mode 100644 domain/model/job/target/github_push_test.go diff --git a/domain/model/job/target/export_test.go b/domain/model/job/target/export_test.go new file mode 100644 index 00000000..c9284f46 --- /dev/null +++ b/domain/model/job/target/export_test.go @@ -0,0 +1,30 @@ +package target + +import "github.com/duck8823/duci/domain/model/job/target/git" + +type GithubPush = githubPush + +func (g *GithubPush) SetGit(git git.Git) (reset func()) { + tmp := g.git + g.git = git + return func() { + g.git = tmp + } +} + +type MockRepository struct { + FullName string + URL string +} + +func (r *MockRepository) GetFullName() string { + return r.FullName +} + +func (r *MockRepository) GetSSHURL() string { + return r.URL +} + +func (r *MockRepository) GetCloneURL() string { + return r.URL +} \ No newline at end of file diff --git a/domain/model/job/target/github_push.go b/domain/model/job/target/github_push.go index 64872346..0f5642b9 100644 --- a/domain/model/job/target/github_push.go +++ b/domain/model/job/target/github_push.go @@ -13,30 +13,40 @@ import ( "path" ) -// GitHubPush is target with github repository -type GitHubPush struct { +// githubPush is target with github repository +type githubPush struct { + git git.Git Repo github.Repository Point github.TargetPoint } +// NewGitHubPush returns target for github push event +func NewGithubPush(repo github.Repository, point github.TargetPoint) (*githubPush, error) { + cli, err := git.GetInstance() + if err != nil { + return nil, errors.WithStack(err) + } + + return &githubPush{ + git: cli, + Repo: repo, + Point: point, + }, nil +} + // Prepare working directory -func (g *GitHubPush) Prepare() (job.WorkDir, job.Cleanup, error) { +func (g *githubPush) Prepare() (job.WorkDir, job.Cleanup, error) { tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric, random.Numeric)) if err := os.MkdirAll(tmpDir, 0700); err != nil { - return "", nil, errors.WithStack(err) - } - - cli, err := git.GetInstance() - if err != nil { - return "", nil, errors.WithStack(err) + return "", cleanupFunc(tmpDir), errors.WithStack(err) } - if err := cli.Clone(context.Background(), tmpDir, &github.TargetSource{ + if err := g.git.Clone(context.Background(), tmpDir, &github.TargetSource{ Repository: g.Repo, Ref: fmt.Sprintf("refs/heads/%s", g.Point.GetRef()), SHA: plumbing.NewHash(g.Point.GetHead()), }); err != nil { - return "", nil, errors.WithStack(err) + return "", cleanupFunc(tmpDir), errors.WithStack(err) } return job.WorkDir(tmpDir), cleanupFunc(tmpDir), nil diff --git a/domain/model/job/target/github_push_test.go b/domain/model/job/target/github_push_test.go new file mode 100644 index 00000000..4e8a606a --- /dev/null +++ b/domain/model/job/target/github_push_test.go @@ -0,0 +1,101 @@ +package target_test + +import ( + "errors" + "github.com/duck8823/duci/domain/model/job/target" + "github.com/duck8823/duci/domain/model/job/target/git/mock_git" + "github.com/duck8823/duci/domain/model/job/target/github" + "github.com/golang/mock/gomock" + "github.com/labstack/gommon/random" + "testing" +) + +func TestGithubPush_Prepare(t *testing.T) { + t.Run("when success git clone", func(t *testing.T) { + // given + repo := &target.MockRepository{ + FullName: "duck8823/duci", + URL: "http://example.com", + } + point := &github.SimpleTargetPoint{ + Ref: "test", + SHA: random.String(16, random.Alphanumeric), + } + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + // and + mockGit := mock_git.NewMockGit(ctrl) + mockGit.EXPECT(). + Clone(gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Return(nil) + + // and + sut := &target.GithubPush{ + Repo: repo, + Point: point, + } + defer sut.SetGit(mockGit)() + + // when + got, cleanup, err := sut.Prepare() + defer cleanup() + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + if len(got) == 0 { + t.Error("must not be empty") + } + }) + + t.Run("when failure git clone", func(t *testing.T) { + // given + repo := &target.MockRepository{ + FullName: "duck8823/duci", + URL: "http://example.com", + } + point := &github.SimpleTargetPoint{ + Ref: "test", + SHA: random.String(16, random.Alphanumeric), + } + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + // and + mockGit := mock_git.NewMockGit(ctrl) + mockGit.EXPECT(). + Clone(gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Return(errors.New("test error")) + + // and + sut := &target.GithubPush{ + Repo: repo, + Point: point, + } + defer sut.SetGit(mockGit)() + + // when + got, cleanup, err := sut.Prepare() + defer cleanup() + + // then + if err == nil { + t.Error("error must not be nil") + } + + // and + if len(got) != 0 { + t.Errorf("must be empty, but got %+v", got) + } + }) +} \ No newline at end of file diff --git a/domain/model/job/target/local.go b/domain/model/job/target/local.go index 42fbbe00..66fb50b3 100644 --- a/domain/model/job/target/local.go +++ b/domain/model/job/target/local.go @@ -10,19 +10,24 @@ import ( "path" ) -// Local is target with local directory -type Local struct { - Path string +// local is target with local directory +type local struct { + path string +} + +// NewLocal returns target for local +func NewLocal(path string) job.Target { + return &local{path: path} } // Prepare working directory -func (l *Local) Prepare() (job.WorkDir, job.Cleanup, error) { +func (l *local) Prepare() (job.WorkDir, job.Cleanup, error) { tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric, random.Numeric)) if err := os.MkdirAll(tmpDir, 0700); err != nil { return "", nil, errors.WithStack(err) } - if err := copyDir(tmpDir, l.Path); err != nil { + if err := copyDir(tmpDir, l.path); err != nil { return "", nil, errors.WithStack(err) } diff --git a/presentation/controller/webhook/handler.go b/presentation/controller/webhook/handler.go index 1e38240f..cff5e11d 100644 --- a/presentation/controller/webhook/handler.go +++ b/presentation/controller/webhook/handler.go @@ -72,10 +72,13 @@ func (h *handler) PushEvent(w http.ResponseWriter, r *http.Request) { TargetURL: targetURL(r), }) - if err := h.executor.Execute(ctx, &target.GitHubPush{ - Repo: event.GetRepo(), - Point: event, - }); err != nil { + tgt, err := target.NewGithubPush(event.GetRepo(), event) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + if err := h.executor.Execute(ctx, tgt); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } @@ -130,10 +133,13 @@ func (h *handler) IssueCommentEvent(w http.ResponseWriter, r *http.Request) { TargetURL: targetURL(r), }) - go h.executor.Execute(ctx, &target.GitHubPush{ - Repo: event.GetRepo(), - Point: pnt, - }, phrase.Command()...) + tgt, err := target.NewGithubPush(event.GetRepo(), pnt) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + go h.executor.Execute(ctx, tgt, phrase.Command()...) w.WriteHeader(http.StatusOK) } From 825f751a31cbe3866cb05f84f2f81c94939b508a Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sun, 16 Dec 2018 13:59:14 +0900 Subject: [PATCH 058/135] Add singleton container --- domain/internal/container/container.go | 64 +++++++++ domain/internal/container/container_test.go | 150 ++++++++++++++++++++ domain/internal/container/export_test.go | 23 +++ 3 files changed, 237 insertions(+) create mode 100644 domain/internal/container/container.go create mode 100644 domain/internal/container/container_test.go create mode 100644 domain/internal/container/export_test.go diff --git a/domain/internal/container/container.go b/domain/internal/container/container.go new file mode 100644 index 00000000..06cc21b0 --- /dev/null +++ b/domain/internal/container/container.go @@ -0,0 +1,64 @@ +package container + +import ( + "fmt" + "reflect" +) + +type singletonContainer struct { + values map[string]interface{} +} + +var instance *singletonContainer + +func init() { + instance = &singletonContainer{ + make(map[string]interface{}), + } +} + +// Submit an instance to container +func Submit(val interface{}) error { + var key string + if reflect.TypeOf(val).Kind() == reflect.Ptr { + key = reflect.Indirect(reflect.ValueOf(val)).Type().String() + } else { + key = reflect.ValueOf(val).Type().String() + } + + if instance.values[key] != nil { + return fmt.Errorf("already submitted such type of %s", key) + } + + instance.values[key] = val + return nil +} + +// Get an instance from container +func Get(ptr interface{}) error { + val := reflect.ValueOf(ptr) + key := reflect.Indirect(val).Type().String() + component := instance.values[key] + if component == nil { + if reflect.Indirect(val).Type().Kind() != reflect.Interface { + return fmt.Errorf("component not found. such type of %s", key) + } + for _, component := range instance.values { + value := reflect.ValueOf(component) + elm := reflect.ValueOf(ptr).Elem() + if value.Type().Implements(elm.Type()) { + elm.Set(value) + return nil + } + } + return fmt.Errorf("component not found. such type of %s", key) + } + + elm := reflect.ValueOf(ptr).Elem() + if reflect.TypeOf(component).Kind() == reflect.Ptr { + elm.Set(reflect.Indirect(reflect.ValueOf(component))) + } else { + elm.Set(reflect.ValueOf(component)) + } + return nil +} diff --git a/domain/internal/container/container_test.go b/domain/internal/container/container_test.go new file mode 100644 index 00000000..c6541eca --- /dev/null +++ b/domain/internal/container/container_test.go @@ -0,0 +1,150 @@ +package container_test + +import ( + "fmt" + "github.com/duck8823/duci/domain/internal/container" + "github.com/google/go-cmp/cmp" + "reflect" + "testing" +) + +type testInterface interface { + Hoge() +} + +type testImpl struct { + Name string +} + +func (*testImpl) Hoge() {} + +type testInterfaceNothing interface { + Fuga() +} + +type hoge string + +func TestSubmit(t *testing.T) { + // given + ins := &container.SingletonContainer{} + defer ins.SetValues(map[string]interface{}{})() + defer container.SetInstance(ins)() + + // and + want := map[string]interface{}{ + "string": "test", + } + + // when + err := container.Submit("test") + + // then + if err != nil { + t.Errorf("must be nil, but got %+v", err) + } + + // and + if !cmp.Equal(ins.GetValues(), want) { + t.Errorf("must be equal, but %+v", cmp.Diff(ins.GetValues(), want)) + } + + // when + err = container.Submit("twice") + + // then + if err == nil { + t.Error("must not be nil") + } + + // and + if !cmp.Equal(ins.GetValues(), want) { + t.Errorf("must be equal, but %+v", cmp.Diff(ins.GetValues(), want)) + } + + // when + str := "ptr tri" + err = container.Submit(&str) + + // then + if err == nil { + t.Error("must not be nil") + } + + // and + if !cmp.Equal(ins.GetValues(), want) { + t.Errorf("must be equal, but %+v", cmp.Diff(ins.GetValues(), want)) + } + +} + +func TestGet(t *testing.T) { + // given + ins := &container.SingletonContainer{} + defer ins.SetValues(map[string]interface{}{ + "string": "value", + "int": 1234, + "float64": 12.34, + "container_test.testImpl": &testImpl{Name: "hoge"}, + })() + defer container.SetInstance(ins)() + + // where + for _, tt := range []struct { + in interface{} + want interface{} + err bool + }{ + { + in: new(string), + want: "value", + }, + { + in: new(int), + want: 1234, + }, + { + in: new(float64), + want: 12.34, + }, + { + in: new(hoge), + want: hoge(""), + err: true, + }, + { + in: new(testImpl), + want: testImpl{Name: "hoge"}, + }, + { + in: new(testInterface), + want: &testImpl{Name: "hoge"}, + }, + { + in: new(testInterfaceNothing), + err: true, + }, + } { + t.Run(fmt.Sprintf("type=%s", reflect.TypeOf(tt.in).String()), func(t *testing.T) { + // when + err := container.Get(tt.in) + got := Value(tt.in) + + // then + if tt.err && err == nil { + t.Error("must not be nil") + } + if !tt.err && err != nil { + t.Errorf("must be nil, but got %+v", err) + } + + // and + if !cmp.Equal(got, tt.want) { + t.Errorf("must be equal, but %+v", cmp.Diff(got, tt.want)) + } + }) + } +} + +func Value(v interface{}) interface{} { + return reflect.Indirect(reflect.ValueOf(v)).Interface() +} \ No newline at end of file diff --git a/domain/internal/container/export_test.go b/domain/internal/container/export_test.go new file mode 100644 index 00000000..d173e1e1 --- /dev/null +++ b/domain/internal/container/export_test.go @@ -0,0 +1,23 @@ +package container + +type SingletonContainer = singletonContainer + +func (s *SingletonContainer) SetValues(values map[string]interface{}) (reset func()) { + tmp := s.values + s.values = values + return func() { + s.values = tmp + } +} + +func (s *SingletonContainer) GetValues() map[string]interface{} { + return s.values +} + +func SetInstance(ins *singletonContainer) (reset func()) { + tmp := instance + instance = ins + return func() { + instance = tmp + } +} From 4288e8c73e146e458353ff013145ecbd2a81dc85 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sun, 16 Dec 2018 18:50:17 +0900 Subject: [PATCH 059/135] Add override function --- domain/internal/container/container.go | 13 ++++++++++++ domain/internal/container/container_test.go | 23 +++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/domain/internal/container/container.go b/domain/internal/container/container.go index 06cc21b0..2968c0ce 100644 --- a/domain/internal/container/container.go +++ b/domain/internal/container/container.go @@ -34,6 +34,19 @@ func Submit(val interface{}) error { return nil } +// Override an instance to container +func Override(val interface{}) { + var key string + if reflect.TypeOf(val).Kind() == reflect.Ptr { + key = reflect.Indirect(reflect.ValueOf(val)).Type().String() + } else { + key = reflect.ValueOf(val).Type().String() + } + + instance.values[key] = val + return +} + // Get an instance from container func Get(ptr interface{}) error { val := reflect.ValueOf(ptr) diff --git a/domain/internal/container/container_test.go b/domain/internal/container/container_test.go index c6541eca..ea2e68fc 100644 --- a/domain/internal/container/container_test.go +++ b/domain/internal/container/container_test.go @@ -77,6 +77,29 @@ func TestSubmit(t *testing.T) { } +func TestOverride(t *testing.T) { + // given + ins := &container.SingletonContainer{} + defer ins.SetValues(map[string]interface{}{ + "string": "hoge", + })() + defer container.SetInstance(ins)() + + // and + want := map[string]interface{}{ + "string": "test", + } + + // when + container.Override("test") + + // then + if !cmp.Equal(ins.GetValues(), want) { + t.Errorf("must be equal, but %+v", cmp.Diff(ins.GetValues(), want)) + } + +} + func TestGet(t *testing.T) { // given ins := &container.SingletonContainer{} From 03982cebae0a950f6e7e2e8f9938c4d715f7f94d Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Mon, 17 Dec 2018 01:58:23 +0900 Subject: [PATCH 060/135] Remove instance variable form git package --- domain/internal/container/container.go | 34 ++++--- domain/internal/container/container_test.go | 90 +++++++++++-------- domain/model/job/target/export_test.go | 19 +++- domain/model/job/target/git/export_test.go | 8 -- domain/model/job/target/git/git.go | 11 ++- domain/model/job/target/git/git_test.go | 6 +- domain/model/job/target/git/http_client.go | 7 +- .../model/job/target/git/http_client_test.go | 6 +- domain/model/job/target/git/ssh_client.go | 11 ++- .../model/job/target/git/ssh_client_test.go | 8 +- domain/model/job/target/github_push_test.go | 63 ++++++++++++- 11 files changed, 181 insertions(+), 82 deletions(-) diff --git a/domain/internal/container/container.go b/domain/internal/container/container.go index 2968c0ce..8489ac8f 100644 --- a/domain/internal/container/container.go +++ b/domain/internal/container/container.go @@ -34,19 +34,6 @@ func Submit(val interface{}) error { return nil } -// Override an instance to container -func Override(val interface{}) { - var key string - if reflect.TypeOf(val).Kind() == reflect.Ptr { - key = reflect.Indirect(reflect.ValueOf(val)).Type().String() - } else { - key = reflect.ValueOf(val).Type().String() - } - - instance.values[key] = val - return -} - // Get an instance from container func Get(ptr interface{}) error { val := reflect.ValueOf(ptr) @@ -75,3 +62,24 @@ func Get(ptr interface{}) error { } return nil } + +// Override an instance to container +// TODO: should not use in production code +func Override(val interface{}) { + var key string + if reflect.TypeOf(val).Kind() == reflect.Ptr { + key = reflect.Indirect(reflect.ValueOf(val)).Type().String() + } else { + key = reflect.ValueOf(val).Type().String() + } + + instance.values[key] = val + return +} + +// Reset instances in container +// TODO: should not use in production code +func Clear() { + instance.values = make(map[string]interface{}) + return +} diff --git a/domain/internal/container/container_test.go b/domain/internal/container/container_test.go index ea2e68fc..6e8a5d74 100644 --- a/domain/internal/container/container_test.go +++ b/domain/internal/container/container_test.go @@ -77,36 +77,13 @@ func TestSubmit(t *testing.T) { } -func TestOverride(t *testing.T) { - // given - ins := &container.SingletonContainer{} - defer ins.SetValues(map[string]interface{}{ - "string": "hoge", - })() - defer container.SetInstance(ins)() - - // and - want := map[string]interface{}{ - "string": "test", - } - - // when - container.Override("test") - - // then - if !cmp.Equal(ins.GetValues(), want) { - t.Errorf("must be equal, but %+v", cmp.Diff(ins.GetValues(), want)) - } - -} - func TestGet(t *testing.T) { // given ins := &container.SingletonContainer{} defer ins.SetValues(map[string]interface{}{ - "string": "value", - "int": 1234, - "float64": 12.34, + "string": "value", + "int": 1234, + "float64": 12.34, "container_test.testImpl": &testImpl{Name: "hoge"}, })() defer container.SetInstance(ins)() @@ -118,32 +95,32 @@ func TestGet(t *testing.T) { err bool }{ { - in: new(string), + in: new(string), want: "value", }, { - in: new(int), + in: new(int), want: 1234, }, { - in: new(float64), + in: new(float64), want: 12.34, }, { - in: new(hoge), + in: new(hoge), want: hoge(""), - err: true, + err: true, }, { - in: new(testImpl), + in: new(testImpl), want: testImpl{Name: "hoge"}, }, { - in: new(testInterface), + in: new(testInterface), want: &testImpl{Name: "hoge"}, }, { - in: new(testInterfaceNothing), + in: new(testInterfaceNothing), err: true, }, } { @@ -168,6 +145,49 @@ func TestGet(t *testing.T) { } } +func TestOverride(t *testing.T) { + // given + ins := &container.SingletonContainer{} + defer ins.SetValues(map[string]interface{}{ + "string": "hoge", + })() + defer container.SetInstance(ins)() + + // and + want := map[string]interface{}{ + "string": "test", + } + + // when + container.Override("test") + + // then + if !cmp.Equal(ins.GetValues(), want) { + t.Errorf("must be equal, but %+v", cmp.Diff(ins.GetValues(), want)) + } + +} + +func TestClear(t *testing.T) { + // given + want := make(map[string]interface{}) + + // and + ins := &container.SingletonContainer{} + defer ins.SetValues(map[string]interface{}{ + "string": "hoge", + })() + defer container.SetInstance(ins)() + + // when + container.Clear() + + // then + if !cmp.Equal(ins.GetValues(), want) { + t.Errorf("must be equal, but %+v", cmp.Diff(ins.GetValues(), want)) + } +} + func Value(v interface{}) interface{} { return reflect.Indirect(reflect.ValueOf(v)).Interface() -} \ No newline at end of file +} diff --git a/domain/model/job/target/export_test.go b/domain/model/job/target/export_test.go index c9284f46..0590af8a 100644 --- a/domain/model/job/target/export_test.go +++ b/domain/model/job/target/export_test.go @@ -1,6 +1,9 @@ package target -import "github.com/duck8823/duci/domain/model/job/target/git" +import ( + "context" + "github.com/duck8823/duci/domain/model/job/target/git" +) type GithubPush = githubPush @@ -12,6 +15,10 @@ func (g *GithubPush) SetGit(git git.Git) (reset func()) { } } +func (g *GithubPush) GetGit() git.Git { + return g.git +} + type MockRepository struct { FullName string URL string @@ -27,4 +34,12 @@ func (r *MockRepository) GetSSHURL() string { func (r *MockRepository) GetCloneURL() string { return r.URL -} \ No newline at end of file +} + +type StubGit struct { + Err error +} + +func (g *StubGit) Clone(_ context.Context, _ string, _ git.TargetSource) error { + return g.Err +} diff --git a/domain/model/job/target/git/export_test.go b/domain/model/job/target/git/export_test.go index 6069b912..fa6a1371 100644 --- a/domain/model/job/target/git/export_test.go +++ b/domain/model/job/target/git/export_test.go @@ -22,14 +22,6 @@ func (l *CloneLogger) SetReader(r *bufio.Reader) (reset func()) { } } -func SetInstance(git Git) (reset func()) { - tmp := instance - instance = git - return func() { - instance = tmp - } -} - func SetPlainCloneFunc(f func(path string, isBare bool, o *git.CloneOptions) (*git.Repository, error)) (reset func()) { tmp := plainClone plainClone = f diff --git a/domain/model/job/target/git/git.go b/domain/model/job/target/git/git.go index 1ed67916..4cb3a31a 100644 --- a/domain/model/job/target/git/git.go +++ b/domain/model/job/target/git/git.go @@ -2,13 +2,12 @@ package git import ( "context" + "github.com/duck8823/duci/domain/internal/container" "github.com/pkg/errors" "gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4/plumbing" ) -var instance Git - var plainClone = git.PlainClone // TargetSource is a interface returns clone URLs, Ref and SHA for target @@ -26,11 +25,11 @@ type Git interface { // GetInstance returns a git client func GetInstance() (Git, error) { - if instance == nil { - return nil, errors.New("instance still not initialized.") + git := new(Git) + if err := container.Get(git); err != nil { + return nil, errors.WithStack(err) } - - return instance, nil + return *git, nil } func checkout(repo *git.Repository, sha plumbing.Hash) error { diff --git a/domain/model/job/target/git/git_test.go b/domain/model/job/target/git/git_test.go index b62d9022..08978d03 100644 --- a/domain/model/job/target/git/git_test.go +++ b/domain/model/job/target/git/git_test.go @@ -1,6 +1,7 @@ package git_test import ( + "github.com/duck8823/duci/domain/internal/container" "github.com/duck8823/duci/domain/model/job/target/git" "github.com/google/go-cmp/cmp" "testing" @@ -9,7 +10,7 @@ import ( func TestGetInstance(t *testing.T) { t.Run("when instance is nil", func(t *testing.T) { // given - defer git.SetInstance(nil)() + container.Clear() // when got, err := git.GetInstance() @@ -30,7 +31,8 @@ func TestGetInstance(t *testing.T) { want := &git.HttpGitClient{} // and - defer git.SetInstance(want)() + container.Override(want) + defer container.Clear() // when got, err := git.GetInstance() diff --git a/domain/model/job/target/git/http_client.go b/domain/model/job/target/git/http_client.go index d4797cf7..f546e580 100644 --- a/domain/model/job/target/git/http_client.go +++ b/domain/model/job/target/git/http_client.go @@ -2,6 +2,7 @@ package git import ( "context" + "github.com/duck8823/duci/domain/internal/container" "github.com/duck8823/duci/domain/model/runner" "github.com/pkg/errors" "gopkg.in/src-d/go-git.v4" @@ -14,11 +15,9 @@ type httpGitClient struct { // InitializeWithHTTP initialize git client with http protocol func InitializeWithHTTP(logFunc runner.LogFunc) error { - if instance != nil { - return errors.New("instance already initialized.") + if err := container.Submit(&httpGitClient{LogFunc: logFunc}); err != nil { + return errors.WithStack(err) } - - instance = &httpGitClient{LogFunc: logFunc} return nil } diff --git a/domain/model/job/target/git/http_client_test.go b/domain/model/job/target/git/http_client_test.go index b32b2e01..51c543ef 100644 --- a/domain/model/job/target/git/http_client_test.go +++ b/domain/model/job/target/git/http_client_test.go @@ -3,6 +3,7 @@ package git_test import ( "context" "errors" + "github.com/duck8823/duci/domain/internal/container" "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/job/target/git" "github.com/duck8823/duci/domain/model/runner" @@ -18,7 +19,7 @@ import ( func TestInitializeWithHTTP(t *testing.T) { t.Run("when instance is nil", func(t *testing.T) { // given - defer git.SetInstance(nil)() + container.Clear() // when err := git.InitializeWithHTTP(func(_ context.Context, _ job.Log) {}) @@ -31,7 +32,8 @@ func TestInitializeWithHTTP(t *testing.T) { t.Run("when instance is not nil", func(t *testing.T) { // given - defer git.SetInstance(&git.HttpGitClient{})() + container.Override(&git.HttpGitClient{}) + defer container.Clear() // when err := git.InitializeWithHTTP(func(_ context.Context, _ job.Log) {}) diff --git a/domain/model/job/target/git/ssh_client.go b/domain/model/job/target/git/ssh_client.go index b48c5f1a..1ef39ca0 100644 --- a/domain/model/job/target/git/ssh_client.go +++ b/domain/model/job/target/git/ssh_client.go @@ -2,6 +2,7 @@ package git import ( "context" + "github.com/duck8823/duci/domain/internal/container" "github.com/duck8823/duci/domain/model/runner" "github.com/pkg/errors" "gopkg.in/src-d/go-git.v4" @@ -17,16 +18,14 @@ type sshGitClient struct { // InitializeWithSSH returns git client with ssh protocol func InitializeWithSSH(path string, logFunc runner.LogFunc) error { - if instance != nil { - return errors.New("instance already initialized.") - } - auth, err := ssh.NewPublicKeysFromFile("git", path, "") if err != nil { - return err + return errors.WithStack(err) } - instance = &sshGitClient{auth: auth, LogFunc: logFunc} + if err := container.Submit(&sshGitClient{auth: auth, LogFunc: logFunc}); err != nil { + return errors.WithStack(err) + } return nil } diff --git a/domain/model/job/target/git/ssh_client_test.go b/domain/model/job/target/git/ssh_client_test.go index 35d93d69..3f9c77ae 100644 --- a/domain/model/job/target/git/ssh_client_test.go +++ b/domain/model/job/target/git/ssh_client_test.go @@ -7,6 +7,7 @@ import ( "crypto/x509" "encoding/pem" "errors" + "github.com/duck8823/duci/domain/internal/container" "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/job/target/git" "github.com/duck8823/duci/domain/model/runner" @@ -23,7 +24,7 @@ func TestInitializeWithSSH(t *testing.T) { t.Run("when instance is nil", func(t *testing.T) { t.Run("with correct key path", func(t *testing.T) { // given - defer git.SetInstance(nil)() + container.Clear() // and path, reset := createTemporaryKey(t) @@ -40,7 +41,7 @@ func TestInitializeWithSSH(t *testing.T) { t.Run("with wrong key path", func(t *testing.T) { // given - defer git.SetInstance(nil)() + container.Clear() // when err := git.InitializeWithSSH("/path/to/nothing", func(_ context.Context, _ job.Log) {}) @@ -54,7 +55,8 @@ func TestInitializeWithSSH(t *testing.T) { t.Run("when instance is not nil", func(t *testing.T) { // given - defer git.SetInstance(&git.SshGitClient{})() + container.Override(&git.SshGitClient{}) + defer container.Clear() // and path, reset := createTemporaryKey(t) diff --git a/domain/model/job/target/github_push_test.go b/domain/model/job/target/github_push_test.go index 4e8a606a..d0c08f8f 100644 --- a/domain/model/job/target/github_push_test.go +++ b/domain/model/job/target/github_push_test.go @@ -2,14 +2,75 @@ package target_test import ( "errors" + "github.com/duck8823/duci/domain/internal/container" "github.com/duck8823/duci/domain/model/job/target" "github.com/duck8823/duci/domain/model/job/target/git/mock_git" "github.com/duck8823/duci/domain/model/job/target/github" "github.com/golang/mock/gomock" + "github.com/google/go-cmp/cmp" "github.com/labstack/gommon/random" "testing" ) +func TestNewGithubPush(t *testing.T) { + t.Run("when git found", func(t *testing.T) { + // given + wantGit := &target.StubGit{} + + // and + container.Override(wantGit) + defer container.Clear() + + // and + want := &target.GithubPush{ + Repo: &target.MockRepository{ + FullName: "duck8823/duci", + URL: "http://example.com", + }, + Point: &github.SimpleTargetPoint{ + Ref: "test", + SHA: random.String(16, random.Alphanumeric), + }, + } + want.SetGit(wantGit) + + // when + got, err := target.NewGithubPush(want.Repo, want.Point) + + // then + if err != nil { + t.Errorf("must be nil, but got %+v", err) + } + + // and + if !cmp.Equal(got.Repo, want.Repo) { + t.Errorf("must be equal, but %+v", cmp.Diff(got.Repo, want.Repo)) + } + + if !cmp.Equal(got.GetGit(), want.GetGit()) { + t.Errorf("must be equal, but %+v", cmp.Diff(got.GetGit(), want.GetGit())) + } + }) + + t.Run("when git not found", func(t *testing.T) { + // given + container.Clear() + + // when + got, err := target.NewGithubPush(nil, nil) + + // then + if err == nil { + t.Errorf("must not be nil") + } + + // and + if got != nil { + t.Errorf("must be nil, but got %+v", got) + } + }) +} + func TestGithubPush_Prepare(t *testing.T) { t.Run("when success git clone", func(t *testing.T) { // given @@ -98,4 +159,4 @@ func TestGithubPush_Prepare(t *testing.T) { t.Errorf("must be empty, but got %+v", got) } }) -} \ No newline at end of file +} From af0ec67409845ced44afa6d5014be92f16684d8e Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Mon, 17 Dec 2018 23:50:14 +0900 Subject: [PATCH 061/135] Remove NewGithubPush --- domain/model/job/target/export_test.go | 27 +-------- domain/model/job/target/github_push.go | 28 +++------ domain/model/job/target/github_push_test.go | 66 ++------------------- presentation/controller/webhook/handler.go | 14 ++--- 4 files changed, 20 insertions(+), 115 deletions(-) diff --git a/domain/model/job/target/export_test.go b/domain/model/job/target/export_test.go index 0590af8a..62cb429b 100644 --- a/domain/model/job/target/export_test.go +++ b/domain/model/job/target/export_test.go @@ -1,23 +1,6 @@ package target -import ( - "context" - "github.com/duck8823/duci/domain/model/job/target/git" -) - -type GithubPush = githubPush - -func (g *GithubPush) SetGit(git git.Git) (reset func()) { - tmp := g.git - g.git = git - return func() { - g.git = tmp - } -} - -func (g *GithubPush) GetGit() git.Git { - return g.git -} +type GithubPush = GitHubPush type MockRepository struct { FullName string @@ -35,11 +18,3 @@ func (r *MockRepository) GetSSHURL() string { func (r *MockRepository) GetCloneURL() string { return r.URL } - -type StubGit struct { - Err error -} - -func (g *StubGit) Clone(_ context.Context, _ string, _ git.TargetSource) error { - return g.Err -} diff --git a/domain/model/job/target/github_push.go b/domain/model/job/target/github_push.go index 0f5642b9..b5857d3f 100644 --- a/domain/model/job/target/github_push.go +++ b/domain/model/job/target/github_push.go @@ -13,35 +13,25 @@ import ( "path" ) -// githubPush is target with github repository -type githubPush struct { - git git.Git +// GitHubPush is target with github repository +type GitHubPush struct { Repo github.Repository Point github.TargetPoint } -// NewGitHubPush returns target for github push event -func NewGithubPush(repo github.Repository, point github.TargetPoint) (*githubPush, error) { - cli, err := git.GetInstance() - if err != nil { - return nil, errors.WithStack(err) - } - - return &githubPush{ - git: cli, - Repo: repo, - Point: point, - }, nil -} - // Prepare working directory -func (g *githubPush) Prepare() (job.WorkDir, job.Cleanup, error) { +func (g *GitHubPush) Prepare() (job.WorkDir, job.Cleanup, error) { tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric, random.Numeric)) if err := os.MkdirAll(tmpDir, 0700); err != nil { return "", cleanupFunc(tmpDir), errors.WithStack(err) } - if err := g.git.Clone(context.Background(), tmpDir, &github.TargetSource{ + git, err := git.GetInstance() + if err != nil { + return "", cleanupFunc(tmpDir), errors.WithStack(err) + } + + if err := git.Clone(context.Background(), tmpDir, &github.TargetSource{ Repository: g.Repo, Ref: fmt.Sprintf("refs/heads/%s", g.Point.GetRef()), SHA: plumbing.NewHash(g.Point.GetHead()), diff --git a/domain/model/job/target/github_push_test.go b/domain/model/job/target/github_push_test.go index d0c08f8f..5d2aac1d 100644 --- a/domain/model/job/target/github_push_test.go +++ b/domain/model/job/target/github_push_test.go @@ -7,70 +7,10 @@ import ( "github.com/duck8823/duci/domain/model/job/target/git/mock_git" "github.com/duck8823/duci/domain/model/job/target/github" "github.com/golang/mock/gomock" - "github.com/google/go-cmp/cmp" "github.com/labstack/gommon/random" "testing" ) -func TestNewGithubPush(t *testing.T) { - t.Run("when git found", func(t *testing.T) { - // given - wantGit := &target.StubGit{} - - // and - container.Override(wantGit) - defer container.Clear() - - // and - want := &target.GithubPush{ - Repo: &target.MockRepository{ - FullName: "duck8823/duci", - URL: "http://example.com", - }, - Point: &github.SimpleTargetPoint{ - Ref: "test", - SHA: random.String(16, random.Alphanumeric), - }, - } - want.SetGit(wantGit) - - // when - got, err := target.NewGithubPush(want.Repo, want.Point) - - // then - if err != nil { - t.Errorf("must be nil, but got %+v", err) - } - - // and - if !cmp.Equal(got.Repo, want.Repo) { - t.Errorf("must be equal, but %+v", cmp.Diff(got.Repo, want.Repo)) - } - - if !cmp.Equal(got.GetGit(), want.GetGit()) { - t.Errorf("must be equal, but %+v", cmp.Diff(got.GetGit(), want.GetGit())) - } - }) - - t.Run("when git not found", func(t *testing.T) { - // given - container.Clear() - - // when - got, err := target.NewGithubPush(nil, nil) - - // then - if err == nil { - t.Errorf("must not be nil") - } - - // and - if got != nil { - t.Errorf("must be nil, but got %+v", got) - } - }) -} - func TestGithubPush_Prepare(t *testing.T) { t.Run("when success git clone", func(t *testing.T) { // given @@ -93,13 +33,14 @@ func TestGithubPush_Prepare(t *testing.T) { Clone(gomock.Any(), gomock.Any(), gomock.Any()). Times(1). Return(nil) + container.Override(mockGit) + defer container.Clear() // and sut := &target.GithubPush{ Repo: repo, Point: point, } - defer sut.SetGit(mockGit)() // when got, cleanup, err := sut.Prepare() @@ -137,13 +78,14 @@ func TestGithubPush_Prepare(t *testing.T) { Clone(gomock.Any(), gomock.Any(), gomock.Any()). Times(1). Return(errors.New("test error")) + container.Override(mockGit) + defer container.Clear() // and sut := &target.GithubPush{ Repo: repo, Point: point, } - defer sut.SetGit(mockGit)() // when got, cleanup, err := sut.Prepare() diff --git a/presentation/controller/webhook/handler.go b/presentation/controller/webhook/handler.go index cff5e11d..30286f53 100644 --- a/presentation/controller/webhook/handler.go +++ b/presentation/controller/webhook/handler.go @@ -72,10 +72,9 @@ func (h *handler) PushEvent(w http.ResponseWriter, r *http.Request) { TargetURL: targetURL(r), }) - tgt, err := target.NewGithubPush(event.GetRepo(), event) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return + tgt := &target.GitHubPush{ + Repo: event.GetRepo(), + Point: event, } if err := h.executor.Execute(ctx, tgt); err != nil { @@ -133,10 +132,9 @@ func (h *handler) IssueCommentEvent(w http.ResponseWriter, r *http.Request) { TargetURL: targetURL(r), }) - tgt, err := target.NewGithubPush(event.GetRepo(), pnt) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return + tgt := &target.GitHubPush{ + Repo: event.GetRepo(), + Point: pnt, } go h.executor.Execute(ctx, tgt, phrase.Command()...) From 4289921d16ee71716ea269e4007b20c2895a2685 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Tue, 18 Dec 2018 00:09:37 +0900 Subject: [PATCH 062/135] Remove GitHubPR struct and rename GitHubPush to GitHub --- domain/model/job/target/export_test.go | 2 - .../job/target/{github_push.go => github.go} | 6 +-- domain/model/job/target/github_pr.go | 53 ------------------- .../{github_push_test.go => github_test.go} | 39 +++++++++++++- presentation/controller/webhook/handler.go | 4 +- 5 files changed, 42 insertions(+), 62 deletions(-) rename domain/model/job/target/{github_push.go => github.go} (88%) delete mode 100644 domain/model/job/target/github_pr.go rename domain/model/job/target/{github_push_test.go => github_test.go} (75%) diff --git a/domain/model/job/target/export_test.go b/domain/model/job/target/export_test.go index 62cb429b..ada36ee8 100644 --- a/domain/model/job/target/export_test.go +++ b/domain/model/job/target/export_test.go @@ -1,7 +1,5 @@ package target -type GithubPush = GitHubPush - type MockRepository struct { FullName string URL string diff --git a/domain/model/job/target/github_push.go b/domain/model/job/target/github.go similarity index 88% rename from domain/model/job/target/github_push.go rename to domain/model/job/target/github.go index b5857d3f..ee2c1645 100644 --- a/domain/model/job/target/github_push.go +++ b/domain/model/job/target/github.go @@ -13,14 +13,14 @@ import ( "path" ) -// GitHubPush is target with github repository -type GitHubPush struct { +// GitHub is target with github repository +type GitHub struct { Repo github.Repository Point github.TargetPoint } // Prepare working directory -func (g *GitHubPush) Prepare() (job.WorkDir, job.Cleanup, error) { +func (g *GitHub) Prepare() (job.WorkDir, job.Cleanup, error) { tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric, random.Numeric)) if err := os.MkdirAll(tmpDir, 0700); err != nil { return "", cleanupFunc(tmpDir), errors.WithStack(err) diff --git a/domain/model/job/target/github_pr.go b/domain/model/job/target/github_pr.go deleted file mode 100644 index 73097a15..00000000 --- a/domain/model/job/target/github_pr.go +++ /dev/null @@ -1,53 +0,0 @@ -package target - -import ( - "context" - "fmt" - "github.com/duck8823/duci/domain/model/job" - "github.com/duck8823/duci/domain/model/job/target/git" - "github.com/duck8823/duci/domain/model/job/target/github" - "github.com/labstack/gommon/random" - "github.com/pkg/errors" - "gopkg.in/src-d/go-git.v4/plumbing" - "os" - "path" -) - -// GitHubPR is target with github pull request -type GitHubPR struct { - Repo github.Repository - Num int -} - -// Prepare working directory -func (g *GitHubPR) Prepare() (job.WorkDir, job.Cleanup, error) { - tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric, random.Numeric)) - if err := os.MkdirAll(tmpDir, 0700); err != nil { - return "", nil, errors.WithStack(err) - } - - githubCli, err := github.GetInstance() - if err != nil { - return "", nil, errors.WithStack(err) - } - - pr, err := githubCli.GetPullRequest(context.Background(), g.Repo, g.Num) - if err != nil { - return "", nil, errors.WithStack(err) - } - - gitCli, err := git.GetInstance() - if err != nil { - return "", nil, errors.WithStack(err) - } - - if err := gitCli.Clone(context.Background(), tmpDir, &github.TargetSource{ - Repository: g.Repo, - Ref: fmt.Sprintf("refs/heads/%s", pr.GetHead().GetRef()), - SHA: plumbing.NewHash(pr.GetHead().GetSHA()), - }); err != nil { - return "", nil, errors.WithStack(err) - } - - return job.WorkDir(tmpDir), cleanupFunc(tmpDir), nil -} diff --git a/domain/model/job/target/github_push_test.go b/domain/model/job/target/github_test.go similarity index 75% rename from domain/model/job/target/github_push_test.go rename to domain/model/job/target/github_test.go index 5d2aac1d..102261eb 100644 --- a/domain/model/job/target/github_push_test.go +++ b/domain/model/job/target/github_test.go @@ -37,7 +37,7 @@ func TestGithubPush_Prepare(t *testing.T) { defer container.Clear() // and - sut := &target.GithubPush{ + sut := &target.GitHub{ Repo: repo, Point: point, } @@ -82,7 +82,42 @@ func TestGithubPush_Prepare(t *testing.T) { defer container.Clear() // and - sut := &target.GithubPush{ + sut := &target.GitHub{ + Repo: repo, + Point: point, + } + + // when + got, cleanup, err := sut.Prepare() + defer cleanup() + + // then + if err == nil { + t.Error("error must not be nil") + } + + // and + if len(got) != 0 { + t.Errorf("must be empty, but got %+v", got) + } + }) + + t.Run("when git have not be initialized", func(t *testing.T) { + // given + repo := &target.MockRepository{ + FullName: "duck8823/duci", + URL: "http://example.com", + } + point := &github.SimpleTargetPoint{ + Ref: "test", + SHA: random.String(16, random.Alphanumeric), + } + + // and + container.Clear() + + // and + sut := &target.GitHub{ Repo: repo, Point: point, } diff --git a/presentation/controller/webhook/handler.go b/presentation/controller/webhook/handler.go index 30286f53..a762004e 100644 --- a/presentation/controller/webhook/handler.go +++ b/presentation/controller/webhook/handler.go @@ -72,7 +72,7 @@ func (h *handler) PushEvent(w http.ResponseWriter, r *http.Request) { TargetURL: targetURL(r), }) - tgt := &target.GitHubPush{ + tgt := &target.GitHub{ Repo: event.GetRepo(), Point: event, } @@ -132,7 +132,7 @@ func (h *handler) IssueCommentEvent(w http.ResponseWriter, r *http.Request) { TargetURL: targetURL(r), }) - tgt := &target.GitHubPush{ + tgt := &target.GitHub{ Repo: event.GetRepo(), Point: pnt, } From e5a3b675393db0e7b9604ea8a79b67677de93cf5 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Tue, 18 Dec 2018 08:00:21 +0900 Subject: [PATCH 063/135] Add test for models --- domain/model/job/job_test.go | 84 +++++++++++++++++++++++++++ domain/model/job/target/local.go | 15 ++--- domain/model/job/target/local_test.go | 25 ++++++++ domain/model/job/target_test.go | 23 ++++++++ 4 files changed, 137 insertions(+), 10 deletions(-) create mode 100644 domain/model/job/job_test.go create mode 100644 domain/model/job/target/local_test.go create mode 100644 domain/model/job/target_test.go diff --git a/domain/model/job/job_test.go b/domain/model/job/job_test.go new file mode 100644 index 00000000..a1cfbf37 --- /dev/null +++ b/domain/model/job/job_test.go @@ -0,0 +1,84 @@ +package job_test + +import ( + "github.com/duck8823/duci/domain/model/job" + "github.com/google/go-cmp/cmp" + "github.com/google/uuid" + "testing" +) + +func TestJob_AppendLog(t *testing.T) { + // given + want := []job.LogLine{{ + Message: "Hello World", + }} + + // and + sut := job.Job{} + + // when + sut.AppendLog(want[0]) + + // then + got := sut.Stream + if !cmp.Equal(got, want) { + t.Errorf("must be equal, but %+v", cmp.Diff(got, want)) + } +} + +func TestJob_Finish(t *testing.T) { + // given + sut := job.Job{} + + // when + sut.Finish() + + // then + if !sut.Finished { + t.Errorf("must be true, but false") + } +} + +func TestJob_ToBytes(t *testing.T) { + t.Run("when success marshal", func(t *testing.T) { + // given + want := []byte("{\"ID\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"finished\":false,\"stream\":[]}") + + // and + sut := job.Job{ + ID: job.ID(uuid.Nil), + Finished: false, + Stream: []job.LogLine{}, + } + + // when + got, err := sut.ToBytes() + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + if !cmp.Equal(got, want) { + t.Errorf("must be equal, but %+v", cmp.Diff(got, want)) + } + }) +} + +func TestID_ToSlice(t *testing.T) { + // given + want := []byte(uuid.New().String()) + + // and + id, _ := uuid.ParseBytes(want) + sut := job.ID(id) + + // when + got := sut.ToSlice() + + // then + if !cmp.Equal(got, want) { + t.Errorf("must be equal, but %+v", cmp.Diff(string(got), string(want))) + } +} \ No newline at end of file diff --git a/domain/model/job/target/local.go b/domain/model/job/target/local.go index 66fb50b3..ee54d364 100644 --- a/domain/model/job/target/local.go +++ b/domain/model/job/target/local.go @@ -10,24 +10,19 @@ import ( "path" ) -// local is target with local directory -type local struct { - path string -} - -// NewLocal returns target for local -func NewLocal(path string) job.Target { - return &local{path: path} +// Local is target with Local directory +type Local struct { + Path string } // Prepare working directory -func (l *local) Prepare() (job.WorkDir, job.Cleanup, error) { +func (l *Local) Prepare() (job.WorkDir, job.Cleanup, error) { tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric, random.Numeric)) if err := os.MkdirAll(tmpDir, 0700); err != nil { return "", nil, errors.WithStack(err) } - if err := copyDir(tmpDir, l.path); err != nil { + if err := copyDir(tmpDir, l.Path); err != nil { return "", nil, errors.WithStack(err) } diff --git a/domain/model/job/target/local_test.go b/domain/model/job/target/local_test.go new file mode 100644 index 00000000..45691a69 --- /dev/null +++ b/domain/model/job/target/local_test.go @@ -0,0 +1,25 @@ +package target_test + +import ( + "github.com/duck8823/duci/domain/model/job/target" + "testing" +) + +func TestLocal_Prepare(t *testing.T) { + // given + sut := &target.Local{Path: "."} + + // when + dir, cleanup, err := sut.Prepare() + defer cleanup() + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + if len(dir) == 0 { + t.Errorf("must not be empty") + } +} \ No newline at end of file diff --git a/domain/model/job/target_test.go b/domain/model/job/target_test.go new file mode 100644 index 00000000..b9f1b8d3 --- /dev/null +++ b/domain/model/job/target_test.go @@ -0,0 +1,23 @@ +package job_test + +import ( + "github.com/duck8823/duci/domain/model/job" + "github.com/google/go-cmp/cmp" + "testing" +) + +func TestWorkDir_String(t *testing.T) { + // given + want := "/path/to/dir" + + // and + sut := job.WorkDir(want) + + // when + got := sut.String() + + // then + if !cmp.Equal(got, want) { + t.Errorf("must be equal, but %+v", cmp.Diff(got, want)) + } +} From b6253bd00f30f1301835d19f429513e8d87fecd4 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Tue, 18 Dec 2018 08:42:49 +0900 Subject: [PATCH 064/135] Remove package variable in job --- application/service/job/job.go | 18 ++++++++---------- domain/model/job/job_test.go | 6 +++--- domain/model/job/target/git/git.go | 2 +- domain/model/job/target/git/git_test.go | 2 +- domain/model/job/target/git/http_client.go | 2 +- .../model/job/target/git/http_client_test.go | 2 +- domain/model/job/target/git/ssh_client.go | 2 +- domain/model/job/target/git/ssh_client_test.go | 2 +- domain/model/job/target/github_test.go | 2 +- domain/model/job/target/local_test.go | 2 +- .../container/container.go | 0 .../container/container_test.go | 2 +- .../container/export_test.go | 0 13 files changed, 20 insertions(+), 22 deletions(-) rename {domain/internal => internal}/container/container.go (100%) rename {domain/internal => internal}/container/container_test.go (98%) rename {domain/internal => internal}/container/export_test.go (100%) diff --git a/application/service/job/job.go b/application/service/job/job.go index 0defda38..c1212a25 100644 --- a/application/service/job/job.go +++ b/application/service/job/job.go @@ -3,6 +3,7 @@ package job_service import ( . "github.com/duck8823/duci/domain/model/job" . "github.com/duck8823/duci/infrastructure/job" + "github.com/duck8823/duci/internal/container" "github.com/pkg/errors" ) @@ -14,33 +15,30 @@ type Service interface { Finish(id ID) error } -var instance *serviceImpl - type serviceImpl struct { repo Repository } // Initialize implementation of job service func Initialize(path string) error { - if instance != nil { - return errors.New("instance already initialized.") - } - dataSource, err := NewDataSource(path) if err != nil { return errors.WithStack(err) } - instance = &serviceImpl{repo: dataSource} + if err := container.Submit(&serviceImpl{repo: dataSource}); err != nil { + return errors.WithStack(err) + } return nil } // GetInstance returns job service func GetInstance() (Service, error) { - if instance == nil { - return nil, errors.New("instance still not initialized.") + ins := new(Service) + if err := container.Get(ins); err != nil { + return nil, errors.WithStack(err) } - return instance, nil + return *ins, nil } // FindBy returns job is found by ID diff --git a/domain/model/job/job_test.go b/domain/model/job/job_test.go index a1cfbf37..cfc14048 100644 --- a/domain/model/job/job_test.go +++ b/domain/model/job/job_test.go @@ -46,9 +46,9 @@ func TestJob_ToBytes(t *testing.T) { // and sut := job.Job{ - ID: job.ID(uuid.Nil), + ID: job.ID(uuid.Nil), Finished: false, - Stream: []job.LogLine{}, + Stream: []job.LogLine{}, } // when @@ -81,4 +81,4 @@ func TestID_ToSlice(t *testing.T) { if !cmp.Equal(got, want) { t.Errorf("must be equal, but %+v", cmp.Diff(string(got), string(want))) } -} \ No newline at end of file +} diff --git a/domain/model/job/target/git/git.go b/domain/model/job/target/git/git.go index 4cb3a31a..3dbdccde 100644 --- a/domain/model/job/target/git/git.go +++ b/domain/model/job/target/git/git.go @@ -2,7 +2,7 @@ package git import ( "context" - "github.com/duck8823/duci/domain/internal/container" + "github.com/duck8823/duci/internal/container" "github.com/pkg/errors" "gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4/plumbing" diff --git a/domain/model/job/target/git/git_test.go b/domain/model/job/target/git/git_test.go index 08978d03..aad54b3b 100644 --- a/domain/model/job/target/git/git_test.go +++ b/domain/model/job/target/git/git_test.go @@ -1,8 +1,8 @@ package git_test import ( - "github.com/duck8823/duci/domain/internal/container" "github.com/duck8823/duci/domain/model/job/target/git" + "github.com/duck8823/duci/internal/container" "github.com/google/go-cmp/cmp" "testing" ) diff --git a/domain/model/job/target/git/http_client.go b/domain/model/job/target/git/http_client.go index f546e580..d0d1854d 100644 --- a/domain/model/job/target/git/http_client.go +++ b/domain/model/job/target/git/http_client.go @@ -2,8 +2,8 @@ package git import ( "context" - "github.com/duck8823/duci/domain/internal/container" "github.com/duck8823/duci/domain/model/runner" + "github.com/duck8823/duci/internal/container" "github.com/pkg/errors" "gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4/plumbing" diff --git a/domain/model/job/target/git/http_client_test.go b/domain/model/job/target/git/http_client_test.go index 51c543ef..ed989d66 100644 --- a/domain/model/job/target/git/http_client_test.go +++ b/domain/model/job/target/git/http_client_test.go @@ -3,10 +3,10 @@ package git_test import ( "context" "errors" - "github.com/duck8823/duci/domain/internal/container" "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/job/target/git" "github.com/duck8823/duci/domain/model/runner" + "github.com/duck8823/duci/internal/container" "github.com/labstack/gommon/random" go_git "gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4/plumbing" diff --git a/domain/model/job/target/git/ssh_client.go b/domain/model/job/target/git/ssh_client.go index 1ef39ca0..aa3db130 100644 --- a/domain/model/job/target/git/ssh_client.go +++ b/domain/model/job/target/git/ssh_client.go @@ -2,8 +2,8 @@ package git import ( "context" - "github.com/duck8823/duci/domain/internal/container" "github.com/duck8823/duci/domain/model/runner" + "github.com/duck8823/duci/internal/container" "github.com/pkg/errors" "gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4/plumbing" diff --git a/domain/model/job/target/git/ssh_client_test.go b/domain/model/job/target/git/ssh_client_test.go index 3f9c77ae..1b4f3ecf 100644 --- a/domain/model/job/target/git/ssh_client_test.go +++ b/domain/model/job/target/git/ssh_client_test.go @@ -7,10 +7,10 @@ import ( "crypto/x509" "encoding/pem" "errors" - "github.com/duck8823/duci/domain/internal/container" "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/job/target/git" "github.com/duck8823/duci/domain/model/runner" + "github.com/duck8823/duci/internal/container" "github.com/labstack/gommon/random" go_git "gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4/plumbing" diff --git a/domain/model/job/target/github_test.go b/domain/model/job/target/github_test.go index 102261eb..808b0b31 100644 --- a/domain/model/job/target/github_test.go +++ b/domain/model/job/target/github_test.go @@ -2,10 +2,10 @@ package target_test import ( "errors" - "github.com/duck8823/duci/domain/internal/container" "github.com/duck8823/duci/domain/model/job/target" "github.com/duck8823/duci/domain/model/job/target/git/mock_git" "github.com/duck8823/duci/domain/model/job/target/github" + "github.com/duck8823/duci/internal/container" "github.com/golang/mock/gomock" "github.com/labstack/gommon/random" "testing" diff --git a/domain/model/job/target/local_test.go b/domain/model/job/target/local_test.go index 45691a69..63e7fa36 100644 --- a/domain/model/job/target/local_test.go +++ b/domain/model/job/target/local_test.go @@ -22,4 +22,4 @@ func TestLocal_Prepare(t *testing.T) { if len(dir) == 0 { t.Errorf("must not be empty") } -} \ No newline at end of file +} diff --git a/domain/internal/container/container.go b/internal/container/container.go similarity index 100% rename from domain/internal/container/container.go rename to internal/container/container.go diff --git a/domain/internal/container/container_test.go b/internal/container/container_test.go similarity index 98% rename from domain/internal/container/container_test.go rename to internal/container/container_test.go index 6e8a5d74..e1c53209 100644 --- a/domain/internal/container/container_test.go +++ b/internal/container/container_test.go @@ -2,7 +2,7 @@ package container_test import ( "fmt" - "github.com/duck8823/duci/domain/internal/container" + "github.com/duck8823/duci/internal/container" "github.com/google/go-cmp/cmp" "reflect" "testing" diff --git a/domain/internal/container/export_test.go b/internal/container/export_test.go similarity index 100% rename from domain/internal/container/export_test.go rename to internal/container/export_test.go From 5f3509827bb74b64f9398b48761dcde499a8479a Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Tue, 18 Dec 2018 08:47:00 +0900 Subject: [PATCH 065/135] Add test case --- application/config_test.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/application/config_test.go b/application/config_test.go index 1740a4da..a87f2b58 100644 --- a/application/config_test.go +++ b/application/config_test.go @@ -131,3 +131,19 @@ func TestMaskString_MarshalJSON(t *testing.T) { t.Errorf("wont masked string, but got '%s'", actual) } } + +func TestMaskString_String(t *testing.T) { + // given + want := "hoge" + + // and + sut := application.MaskString(want) + + // when + got := sut.String() + + // then + if !cmp.Equal(got, want) { + t.Errorf("must be equal, but %+v", cmp.Diff(got, want)) + } +} \ No newline at end of file From 77de961d95f8741512017a2a7ce9e8eed66f9ba6 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Wed, 19 Dec 2018 01:28:45 +0900 Subject: [PATCH 066/135] Add test case to application context --- application/context_test.go | 70 +++++++++++++++++++++++++++++++++++++ application/export_test.go | 4 +++ 2 files changed, 74 insertions(+) create mode 100644 application/context_test.go diff --git a/application/context_test.go b/application/context_test.go new file mode 100644 index 00000000..accd8cbb --- /dev/null +++ b/application/context_test.go @@ -0,0 +1,70 @@ +package application_test + +import ( + "context" + "github.com/duck8823/duci/application" + "github.com/duck8823/duci/domain/model/job" + "github.com/google/go-cmp/cmp" + "github.com/google/uuid" + "testing" +) + +func TestContextWithJob(t *testing.T) { + // given + want := &application.BuildJob{ + ID: job.ID(uuid.New()), + } + + // and + ctx := application.ContextWithJob(context.Background(), want) + + // when + got := ctx.Value(application.GetCtxKey()) + + // then + if !cmp.Equal(got, want) { + t.Errorf("must be equal, but %+v", cmp.Diff(got, want)) + } +} + +func TestBuildJobFromContext(t *testing.T) { + t.Run("with value", func(t *testing.T) { + // given + want := &application.BuildJob{ + ID: job.ID(uuid.New()), + } + + sut := context.WithValue(context.Background(), application.GetCtxKey(), want) + + // when + got, err := application.BuildJobFromContext(sut) + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + if !cmp.Equal(got, want) { + t.Errorf("must be equal, but %+v", cmp.Diff(got, want)) + } + }) + + t.Run("without value", func(t *testing.T) { + sut := context.Background() + + // when + got, err := application.BuildJobFromContext(sut) + + // then + if err == nil { + t.Error("error must not be nil") + } + + // and + if got != nil { + t.Errorf("must be nil, but got %+v", got) + } + }) + +} \ No newline at end of file diff --git a/application/export_test.go b/application/export_test.go index 03d3b5b1..daa40666 100644 --- a/application/export_test.go +++ b/application/export_test.go @@ -27,3 +27,7 @@ func CheckLatestVersion() { func TrimSuffix(tag string) string { return trimSuffix(tag) } + +func GetCtxKey() string { + return ctxKey +} \ No newline at end of file From 76e8f44f7219cb948711492f484a7a615ae61069 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Wed, 19 Dec 2018 01:44:13 +0900 Subject: [PATCH 067/135] Add initialize test --- application/initialize_test.go | 100 +++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 application/initialize_test.go diff --git a/application/initialize_test.go b/application/initialize_test.go new file mode 100644 index 00000000..8b6f6376 --- /dev/null +++ b/application/initialize_test.go @@ -0,0 +1,100 @@ +package application_test + +import ( + "github.com/duck8823/duci/application" + "github.com/duck8823/duci/application/service/job" + "github.com/duck8823/duci/domain/model/job/target/git" + "github.com/duck8823/duci/domain/model/job/target/github" + "github.com/duck8823/duci/internal/container" + "github.com/labstack/gommon/random" + "os" + "path" + "testing" +) + +func TestInitialize(t *testing.T) { + t.Run("when singleton container is empty", func(t *testing.T) { + // given + application.Config.Server.DatabasePath = path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + + // and + container.Clear() + + // when + err := application.Initialize() + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + git := new(git.Git) + if err := container.Get(git); err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + github := new(github.GitHub) + if err := container.Get(github); err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + jobService := new(job_service.Service) + if err := container.Get(jobService); err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + }) + + t.Run("when singleton container contains Git instance", func(t *testing.T) { + // given + application.Config.Server.DatabasePath = path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + + // and + container.Override(new(git.Git)) + defer container.Clear() + + // when + err := application.Initialize() + + // then + if err == nil { + t.Error("error must not be nil") + } + }) + + t.Run("when singleton container contains GitHub instance", func(t *testing.T) { + // given + application.Config.Server.DatabasePath = path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + + // and + container.Override(new(github.GitHub)) + defer container.Clear() + + // when + err := application.Initialize() + + // then + if err == nil { + t.Error("error must not be nil") + } + }) + + t.Run("when singleton container contains JobService instance", func(t *testing.T) { + // given + application.Config.Server.DatabasePath = path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + + // and + container.Override(new(job_service.Service)) + defer container.Clear() + + // when + err := application.Initialize() + + // then + if err == nil { + t.Error("error must not be nil") + } + }) +} \ No newline at end of file From fce32bcc5ba05c0650186a356ff5fd21c5a3a91e Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Wed, 19 Dec 2018 07:34:45 +0900 Subject: [PATCH 068/135] Add line brake --- application/config_test.go | 2 +- application/context_test.go | 2 +- application/export_test.go | 2 +- application/initialize_test.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/application/config_test.go b/application/config_test.go index a87f2b58..52394ecd 100644 --- a/application/config_test.go +++ b/application/config_test.go @@ -146,4 +146,4 @@ func TestMaskString_String(t *testing.T) { if !cmp.Equal(got, want) { t.Errorf("must be equal, but %+v", cmp.Diff(got, want)) } -} \ No newline at end of file +} diff --git a/application/context_test.go b/application/context_test.go index accd8cbb..2ed3fd9d 100644 --- a/application/context_test.go +++ b/application/context_test.go @@ -67,4 +67,4 @@ func TestBuildJobFromContext(t *testing.T) { } }) -} \ No newline at end of file +} diff --git a/application/export_test.go b/application/export_test.go index daa40666..b111f7ce 100644 --- a/application/export_test.go +++ b/application/export_test.go @@ -30,4 +30,4 @@ func TrimSuffix(tag string) string { func GetCtxKey() string { return ctxKey -} \ No newline at end of file +} diff --git a/application/initialize_test.go b/application/initialize_test.go index 8b6f6376..347c707d 100644 --- a/application/initialize_test.go +++ b/application/initialize_test.go @@ -97,4 +97,4 @@ func TestInitialize(t *testing.T) { t.Error("error must not be nil") } }) -} \ No newline at end of file +} From 9147ff038a3b26e785b632515dabff99a84e3a42 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Wed, 19 Dec 2018 07:40:16 +0900 Subject: [PATCH 069/135] Set instance to container as interface --- application/service/job/job.go | 4 +++- domain/model/job/target/git/http_client.go | 4 +++- domain/model/job/target/git/ssh_client.go | 4 +++- .../model/job/target/git/ssh_client_test.go | 2 +- domain/model/job/target/github/export_test.go | 8 ------- domain/model/job/target/github/github.go | 21 +++++++++---------- domain/model/job/target/github/github_test.go | 11 ++++++---- 7 files changed, 27 insertions(+), 27 deletions(-) diff --git a/application/service/job/job.go b/application/service/job/job.go index c1212a25..acf1bb88 100644 --- a/application/service/job/job.go +++ b/application/service/job/job.go @@ -26,7 +26,9 @@ func Initialize(path string) error { return errors.WithStack(err) } - if err := container.Submit(&serviceImpl{repo: dataSource}); err != nil { + service := new(Service) + *service = &serviceImpl{repo: dataSource} + if err := container.Submit(service); err != nil { return errors.WithStack(err) } return nil diff --git a/domain/model/job/target/git/http_client.go b/domain/model/job/target/git/http_client.go index d0d1854d..c85edc3f 100644 --- a/domain/model/job/target/git/http_client.go +++ b/domain/model/job/target/git/http_client.go @@ -15,7 +15,9 @@ type httpGitClient struct { // InitializeWithHTTP initialize git client with http protocol func InitializeWithHTTP(logFunc runner.LogFunc) error { - if err := container.Submit(&httpGitClient{LogFunc: logFunc}); err != nil { + git := new(Git) + *git = &httpGitClient{LogFunc: logFunc} + if err := container.Submit(git); err != nil { return errors.WithStack(err) } return nil diff --git a/domain/model/job/target/git/ssh_client.go b/domain/model/job/target/git/ssh_client.go index aa3db130..37be8fbc 100644 --- a/domain/model/job/target/git/ssh_client.go +++ b/domain/model/job/target/git/ssh_client.go @@ -23,7 +23,9 @@ func InitializeWithSSH(path string, logFunc runner.LogFunc) error { return errors.WithStack(err) } - if err := container.Submit(&sshGitClient{auth: auth, LogFunc: logFunc}); err != nil { + git := new(Git) + *git = &sshGitClient{auth: auth, LogFunc: logFunc} + if err := container.Submit(git); err != nil { return errors.WithStack(err) } return nil diff --git a/domain/model/job/target/git/ssh_client_test.go b/domain/model/job/target/git/ssh_client_test.go index 1b4f3ecf..822f97f7 100644 --- a/domain/model/job/target/git/ssh_client_test.go +++ b/domain/model/job/target/git/ssh_client_test.go @@ -55,7 +55,7 @@ func TestInitializeWithSSH(t *testing.T) { t.Run("when instance is not nil", func(t *testing.T) { // given - container.Override(&git.SshGitClient{}) + container.Override(new(git.Git)) defer container.Clear() // and diff --git a/domain/model/job/target/github/export_test.go b/domain/model/job/target/github/export_test.go index 3694c5cf..0154af9d 100644 --- a/domain/model/job/target/github/export_test.go +++ b/domain/model/job/target/github/export_test.go @@ -32,11 +32,3 @@ func (r *MockRepository) GetSSHURL() string { func (r *MockRepository) GetCloneURL() string { return r.URL } - -func SetInstance(github GitHub) (reset func()) { - tmp := instance - instance = github - return func() { - instance = tmp - } -} diff --git a/domain/model/job/target/github/github.go b/domain/model/job/target/github/github.go index 6f4ca288..ac4affce 100644 --- a/domain/model/job/target/github/github.go +++ b/domain/model/job/target/github/github.go @@ -2,13 +2,12 @@ package github import ( "context" + "github.com/duck8823/duci/internal/container" go_github "github.com/google/go-github/github" "github.com/pkg/errors" "golang.org/x/oauth2" ) -var instance GitHub - // GitHub describes a github client. type GitHub interface { GetPullRequest(ctx context.Context, repo Repository, num int) (*go_github.PullRequest, error) @@ -21,24 +20,24 @@ type client struct { // Initialize create a github client. func Initialize(token string) error { - if instance != nil { - return errors.New("instance already initialized.") - } - ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token}) tc := oauth2.NewClient(context.Background(), ts) - instance = &client{go_github.NewClient(tc)} + github := new(GitHub) + *github = &client{go_github.NewClient(tc)} + if err := container.Submit(github); err != nil { + return errors.WithStack(err) + } return nil } // GetInstance returns a github client func GetInstance() (GitHub, error) { - if instance == nil { - return nil, errors.New("instance still not initialized.") + github := new(GitHub) + if err := container.Get(github); err != nil { + return nil, errors.WithStack(err) } - - return instance, nil + return *github, nil } // GetPullRequest returns a pull request with specific repository and number. diff --git a/domain/model/job/target/github/github_test.go b/domain/model/job/target/github/github_test.go index 4adaf2bf..492e003e 100644 --- a/domain/model/job/target/github/github_test.go +++ b/domain/model/job/target/github/github_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "github.com/duck8823/duci/domain/model/job/target/github" + "github.com/duck8823/duci/internal/container" "github.com/google/go-cmp/cmp" go_github "github.com/google/go-github/github" "github.com/labstack/gommon/random" @@ -16,7 +17,7 @@ import ( func TestInitialize(t *testing.T) { t.Run("when instance is nil", func(t *testing.T) { // given - defer github.SetInstance(nil)() + container.Clear() // when err := github.Initialize("github_api_token") @@ -29,7 +30,8 @@ func TestInitialize(t *testing.T) { t.Run("when instance is not nil", func(t *testing.T) { // given - defer github.SetInstance(&github.StubClient{})() + container.Override(&github.StubClient{}) + defer container.Clear() // when err := github.Initialize("github_api_token") @@ -44,7 +46,7 @@ func TestInitialize(t *testing.T) { func TestGetInstance(t *testing.T) { t.Run("when instance is nil", func(t *testing.T) { // given - defer github.SetInstance(nil)() + container.Clear() // when got, err := github.GetInstance() @@ -65,7 +67,8 @@ func TestGetInstance(t *testing.T) { want := &github.StubClient{} // and - defer github.SetInstance(want)() + container.Override(want) + defer container.Clear() // when got, err := github.GetInstance() From a51335833ce33d8a76d6b71a139151c1eb6b60a9 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 22 Dec 2018 14:12:52 +0900 Subject: [PATCH 070/135] Separate files implementation and interface --- application/service/job/service.go | 11 +++++++++++ application/service/job/{job.go => service_impl.go} | 8 -------- 2 files changed, 11 insertions(+), 8 deletions(-) create mode 100644 application/service/job/service.go rename application/service/job/{job.go => service_impl.go} (92%) diff --git a/application/service/job/service.go b/application/service/job/service.go new file mode 100644 index 00000000..38076a4c --- /dev/null +++ b/application/service/job/service.go @@ -0,0 +1,11 @@ +package job_service + +import "github.com/duck8823/duci/domain/model/job" + +// Service represents job service +type Service interface { + FindBy(id job.ID) (*job.Job, error) + Start(id job.ID) error + Append(id job.ID, line job.LogLine) error + Finish(id job.ID) error +} diff --git a/application/service/job/job.go b/application/service/job/service_impl.go similarity index 92% rename from application/service/job/job.go rename to application/service/job/service_impl.go index acf1bb88..b31ae7ae 100644 --- a/application/service/job/job.go +++ b/application/service/job/service_impl.go @@ -7,14 +7,6 @@ import ( "github.com/pkg/errors" ) -// Service represents job service -type Service interface { - FindBy(id ID) (*Job, error) - Start(id ID) error - Append(id ID, line LogLine) error - Finish(id ID) error -} - type serviceImpl struct { repo Repository } From 5a4bc82d779e6f5da84e7530ec3f62fcad7381df Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 22 Dec 2018 14:13:14 +0900 Subject: [PATCH 071/135] Add test for job service --- application/service/job/export_test.go | 23 +++++++ application/service/job/service_test.go | 89 +++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 application/service/job/export_test.go create mode 100644 application/service/job/service_test.go diff --git a/application/service/job/export_test.go b/application/service/job/export_test.go new file mode 100644 index 00000000..81047f62 --- /dev/null +++ b/application/service/job/export_test.go @@ -0,0 +1,23 @@ +package job_service + +import "github.com/duck8823/duci/domain/model/job" + +type StubService struct { + ID string +} + +func (s *StubService) FindBy(_ job.ID) (*job.Job, error) { + return nil, nil +} + +func (s *StubService) Start(_ job.ID) error { + return nil +} + +func (s *StubService) Append(_ job.ID, _ job.LogLine) error { + return nil +} + +func (s *StubService) Finish(_ job.ID) error { + return nil +} diff --git a/application/service/job/service_test.go b/application/service/job/service_test.go new file mode 100644 index 00000000..086871f7 --- /dev/null +++ b/application/service/job/service_test.go @@ -0,0 +1,89 @@ +package job_service_test + +import ( + "github.com/duck8823/duci/application/service/job" + "github.com/duck8823/duci/internal/container" + "github.com/google/go-cmp/cmp" + "github.com/labstack/gommon/random" + "os" + "path" + "testing" +) + +func TestInitialize(t *testing.T) { + t.Run("with temporary directory", func(t *testing.T) { + // given + tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + defer func() { + _ = os.RemoveAll(tmpDir) + }() + + // when + err := job_service.Initialize(tmpDir) + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + }) + + t.Run("with invalid directory", func(t *testing.T) { + // given + tmpDir := path.Join("/path/to/invalid/dir") + defer func() { + _ = os.RemoveAll(tmpDir) + }() + + // when + err := job_service.Initialize(tmpDir) + + // then + if err == nil { + t.Error("error must not be nil") + } + }) +} + +func TestGetInstance(t *testing.T) { + t.Run("when instance is nil", func(t *testing.T) { + // given + container.Clear() + + // when + got, err := job_service.GetInstance() + + // then + if err == nil { + t.Error("error must not be nil") + } + + // and + if got != nil { + t.Errorf("must be nil, but got %+v", err) + } + }) + + t.Run("when instance is not nil", func(t *testing.T) { + // given + want := &job_service.StubService{ + ID: random.String(16, random.Alphanumeric), + } + + // and + container.Override(want) + defer container.Clear() + + // when + got, err := job_service.GetInstance() + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + if !cmp.Equal(got, want) { + t.Errorf("must be equal, but %+v", cmp.Diff(got, want)) + } + }) +} From 80266bd61f85a7c5dbfdea052521cda30bffef84 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 22 Dec 2018 14:13:37 +0900 Subject: [PATCH 072/135] Generate mock_service --- application/service/job/mock_job/service.go | 83 +++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 application/service/job/mock_job/service.go diff --git a/application/service/job/mock_job/service.go b/application/service/job/mock_job/service.go new file mode 100644 index 00000000..52b5c4e6 --- /dev/null +++ b/application/service/job/mock_job/service.go @@ -0,0 +1,83 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: application/service/job/service.go + +// Package mock_job_service is a generated GoMock package. +package mock_job_service + +import ( + job "github.com/duck8823/duci/domain/model/job" + gomock "github.com/golang/mock/gomock" + reflect "reflect" +) + +// MockService is a mock of Service interface +type MockService struct { + ctrl *gomock.Controller + recorder *MockServiceMockRecorder +} + +// MockServiceMockRecorder is the mock recorder for MockService +type MockServiceMockRecorder struct { + mock *MockService +} + +// NewMockService creates a new mock instance +func NewMockService(ctrl *gomock.Controller) *MockService { + mock := &MockService{ctrl: ctrl} + mock.recorder = &MockServiceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockService) EXPECT() *MockServiceMockRecorder { + return m.recorder +} + +// FindBy mocks base method +func (m *MockService) FindBy(id job.ID) (*job.Job, error) { + ret := m.ctrl.Call(m, "FindBy", id) + ret0, _ := ret[0].(*job.Job) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindBy indicates an expected call of FindBy +func (mr *MockServiceMockRecorder) FindBy(id interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindBy", reflect.TypeOf((*MockService)(nil).FindBy), id) +} + +// Start mocks base method +func (m *MockService) Start(id job.ID) error { + ret := m.ctrl.Call(m, "Start", id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Start indicates an expected call of Start +func (mr *MockServiceMockRecorder) Start(id interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*MockService)(nil).Start), id) +} + +// Append mocks base method +func (m *MockService) Append(id job.ID, line job.LogLine) error { + ret := m.ctrl.Call(m, "Append", id, line) + ret0, _ := ret[0].(error) + return ret0 +} + +// Append indicates an expected call of Append +func (mr *MockServiceMockRecorder) Append(id, line interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Append", reflect.TypeOf((*MockService)(nil).Append), id, line) +} + +// Finish mocks base method +func (m *MockService) Finish(id job.ID) error { + ret := m.ctrl.Call(m, "Finish", id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Finish indicates an expected call of Finish +func (mr *MockServiceMockRecorder) Finish(id interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Finish", reflect.TypeOf((*MockService)(nil).Finish), id) +} From 9ac29e10f92d8f806cc44d03f09e003054b1867c Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sun, 23 Dec 2018 16:04:18 +0900 Subject: [PATCH 073/135] Add test for job service --- application/service/job/export_test.go | 10 + application/service/job/service_test.go | 358 ++++++++++++++++++++++++ domain/model/job/mock_job/repository.go | 59 ++++ 3 files changed, 427 insertions(+) create mode 100644 domain/model/job/mock_job/repository.go diff --git a/application/service/job/export_test.go b/application/service/job/export_test.go index 81047f62..e778ef27 100644 --- a/application/service/job/export_test.go +++ b/application/service/job/export_test.go @@ -21,3 +21,13 @@ func (s *StubService) Append(_ job.ID, _ job.LogLine) error { func (s *StubService) Finish(_ job.ID) error { return nil } + +type ServiceImpl = serviceImpl + +func (s *ServiceImpl) SetRepo(repo job.Repository) (reset func()) { + tmp := s.repo + s.repo = repo + return func() { + s.repo = tmp + } +} diff --git a/application/service/job/service_test.go b/application/service/job/service_test.go index 086871f7..2f3af885 100644 --- a/application/service/job/service_test.go +++ b/application/service/job/service_test.go @@ -2,12 +2,18 @@ package job_service_test import ( "github.com/duck8823/duci/application/service/job" + "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/job/mock_job" "github.com/duck8823/duci/internal/container" + "github.com/golang/mock/gomock" "github.com/google/go-cmp/cmp" + "github.com/google/uuid" "github.com/labstack/gommon/random" + "github.com/pkg/errors" "os" "path" "testing" + "time" ) func TestInitialize(t *testing.T) { @@ -87,3 +93,355 @@ func TestGetInstance(t *testing.T) { } }) } + +func TestServiceImpl_FindBy(t *testing.T) { + t.Run("when repo returns job", func(t *testing.T) { + // given + id := job.ID(uuid.New()) + + // and + want := &job.Job{ + ID: id, + Finished: true, + Stream: []job.LogLine{ + { + Timestamp: time.Now(), + Message: "hello world", + }, + }, + } + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + repo := mock_job.NewMockRepository(ctrl) + repo.EXPECT(). + FindBy(gomock.Eq(id)). + Times(1). + Return(want, nil) + + // and + sut := &job_service.ServiceImpl{} + defer sut.SetRepo(repo)() + + // when + got, err := sut.FindBy(id) + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + if !cmp.Equal(got, want) { + t.Errorf("must be equal but %+v", cmp.Diff(got, want)) + } + }) + + t.Run("when repo returns error", func(t *testing.T) { + // given + id := job.ID(uuid.New()) + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + repo := mock_job.NewMockRepository(ctrl) + repo.EXPECT(). + FindBy(gomock.Eq(id)). + Times(1). + Return(nil, errors.New("test error")) + + // and + sut := &job_service.ServiceImpl{} + defer sut.SetRepo(repo)() + + // when + got, err := sut.FindBy(id) + + // then + if err == nil { + t.Error("error must not be nil") + } + + // and + if got != nil { + t.Errorf("must be nil, but got %+v", got) + } + }) +} + +func TestServiceImpl_Start(t *testing.T) { + t.Run("when repo returns nil", func(t *testing.T) { + // given + id := job.ID(uuid.New()) + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + repo := mock_job.NewMockRepository(ctrl) + repo.EXPECT(). + Save(gomock.Eq(job.Job{ID: id, Finished: false})). + Times(1). + Return(nil) + + // and + sut := &job_service.ServiceImpl{} + defer sut.SetRepo(repo)() + + // when + err := sut.Start(id) + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + }) + + t.Run("when repo returns error", func(t *testing.T) { + // given + id := job.ID(uuid.New()) + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + repo := mock_job.NewMockRepository(ctrl) + repo.EXPECT(). + Save(gomock.Eq(job.Job{ID: id, Finished: false})). + Times(1). + Return(errors.New("test error")) + + // and + sut := &job_service.ServiceImpl{} + defer sut.SetRepo(repo)() + + // when + err := sut.Start(id) + + // then + if err == nil { + t.Error("error must not be nil") + } + }) +} + +func TestServiceImpl_Append(t *testing.T) { + t.Run("when failure find job", func(t *testing.T) { + // given + id := job.ID(uuid.New()) + line := job.LogLine{Timestamp: time.Now(), Message: "Hello Test"} + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + repo := mock_job.NewMockRepository(ctrl) + repo.EXPECT(). + FindBy(gomock.Eq(id)). + Times(1). + Return(nil, errors.New("test error")) + + // and + sut := &job_service.ServiceImpl{} + defer sut.SetRepo(repo)() + + // when + err := sut.Append(id, line) + + // then + if err == nil { + t.Error("error must not be nil") + } + }) + + t.Run("when failure save job", func(t *testing.T) { + // given + id := job.ID(uuid.New()) + line := job.LogLine{Timestamp: time.Now(), Message: "Hello Test"} + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + repo := mock_job.NewMockRepository(ctrl) + repo.EXPECT(). + FindBy(gomock.Eq(id)). + Times(1). + Return(&job.Job{ID: id, Finished: false}, nil) + repo.EXPECT(). + Save(gomock.Eq(job.Job{ID: id, Finished: false, Stream: []job.LogLine{line}})). + Times(1). + Return(errors.New("test error")) + + // and + sut := &job_service.ServiceImpl{} + defer sut.SetRepo(repo)() + + // when + err := sut.Append(id, line) + + // then + if err == nil { + t.Error("error must not be nil") + } + }) + + t.Run("when job not found", func(t *testing.T) { + // given + id := job.ID(uuid.New()) + line := job.LogLine{Timestamp: time.Now(), Message: "Hello Test"} + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + repo := mock_job.NewMockRepository(ctrl) + repo.EXPECT(). + FindBy(gomock.Eq(id)). + Times(1). + Return(nil, job.NotFound) + repo.EXPECT(). + Save(gomock.Eq(job.Job{ID: id, Finished: false, Stream: []job.LogLine{line}})). + Times(1). + Return(errors.New("test error")) + + // and + sut := &job_service.ServiceImpl{} + defer sut.SetRepo(repo)() + + // when + err := sut.Append(id, line) + + // then + if err == nil { + t.Error("error must not be nil") + } + }) + + t.Run("without any error", func(t *testing.T) { + // given + id := job.ID(uuid.New()) + line := job.LogLine{Timestamp: time.Now(), Message: "Hello Test"} + + // and + stored := job.LogLine{Timestamp: time.Now(), Message: "Stored line"} + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + repo := mock_job.NewMockRepository(ctrl) + repo.EXPECT(). + FindBy(gomock.Eq(id)). + Times(1). + Return(&job.Job{ID: id, Finished: false, Stream: []job.LogLine{stored}}, nil) + repo.EXPECT(). + Save(gomock.Eq(job.Job{ID: id, Finished: false, Stream: []job.LogLine{stored, line}})). + Times(1). + Return(nil) + + // and + sut := &job_service.ServiceImpl{} + defer sut.SetRepo(repo)() + + // when + err := sut.Append(id, line) + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + }) +} + +func TestServiceImpl_Finish(t *testing.T) { + t.Run("when find job, returns error", func(t *testing.T) { + // given + id := job.ID(uuid.New()) + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + repo := mock_job.NewMockRepository(ctrl) + repo.EXPECT(). + FindBy(gomock.Eq(id)). + Times(1). + Return(nil, errors.New("test error")) + + // and + sut := &job_service.ServiceImpl{} + defer sut.SetRepo(repo)() + + // when + err := sut.Finish(id) + + // then + if err == nil { + t.Error("error must not be nil") + } + }) + + t.Run("when save, returns error", func(t *testing.T) { + // given + id := job.ID(uuid.New()) + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + repo := mock_job.NewMockRepository(ctrl) + repo.EXPECT(). + FindBy(gomock.Eq(id)). + Times(1). + Return(&job.Job{ID: id, Finished: false}, nil) + repo.EXPECT(). + Save(gomock.Eq(job.Job{ID: id, Finished: true})). + Times(1). + Return(errors.New("test error")) + + // and + sut := &job_service.ServiceImpl{} + defer sut.SetRepo(repo)() + + // when + err := sut.Finish(id) + + // then + if err == nil { + t.Error("error must not be nil") + } + }) + + t.Run("without any error", func(t *testing.T) { + // given + id := job.ID(uuid.New()) + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + repo := mock_job.NewMockRepository(ctrl) + repo.EXPECT(). + FindBy(gomock.Eq(id)). + Times(1). + Return(&job.Job{ID: id, Finished: false}, nil) + repo.EXPECT(). + Save(gomock.Eq(job.Job{ID: id, Finished: true})). + Return(nil) + + // and + sut := &job_service.ServiceImpl{} + defer sut.SetRepo(repo)() + + // when + err := sut.Finish(id) + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + }) +} diff --git a/domain/model/job/mock_job/repository.go b/domain/model/job/mock_job/repository.go new file mode 100644 index 00000000..a6e50244 --- /dev/null +++ b/domain/model/job/mock_job/repository.go @@ -0,0 +1,59 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: domain/model/job/repository.go + +// Package mock_job is a generated GoMock package. +package mock_job + +import ( + job "github.com/duck8823/duci/domain/model/job" + gomock "github.com/golang/mock/gomock" + reflect "reflect" +) + +// MockRepository is a mock of Repository interface +type MockRepository struct { + ctrl *gomock.Controller + recorder *MockRepositoryMockRecorder +} + +// MockRepositoryMockRecorder is the mock recorder for MockRepository +type MockRepositoryMockRecorder struct { + mock *MockRepository +} + +// NewMockRepository creates a new mock instance +func NewMockRepository(ctrl *gomock.Controller) *MockRepository { + mock := &MockRepository{ctrl: ctrl} + mock.recorder = &MockRepositoryMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockRepository) EXPECT() *MockRepositoryMockRecorder { + return m.recorder +} + +// FindBy mocks base method +func (m *MockRepository) FindBy(arg0 job.ID) (*job.Job, error) { + ret := m.ctrl.Call(m, "FindBy", arg0) + ret0, _ := ret[0].(*job.Job) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindBy indicates an expected call of FindBy +func (mr *MockRepositoryMockRecorder) FindBy(arg0 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindBy", reflect.TypeOf((*MockRepository)(nil).FindBy), arg0) +} + +// Save mocks base method +func (m *MockRepository) Save(arg0 job.Job) error { + ret := m.ctrl.Call(m, "Save", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// Save indicates an expected call of Save +func (mr *MockRepositoryMockRecorder) Save(arg0 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Save", reflect.TypeOf((*MockRepository)(nil).Save), arg0) +} From 10420ca8958583215db433b7422260256b236185 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Tue, 25 Dec 2018 01:08:03 +0900 Subject: [PATCH 074/135] Add datasource test --- infrastructure/job/data_source_test.go | 205 +++++++++++++++++++++ infrastructure/job/export_test.go | 11 ++ infrastructure/job/mock_job/third_pirty.go | 84 +++++++++ infrastructure/job/third_pirty.go | 8 +- 4 files changed, 304 insertions(+), 4 deletions(-) create mode 100644 infrastructure/job/data_source_test.go create mode 100644 infrastructure/job/export_test.go create mode 100644 infrastructure/job/mock_job/third_pirty.go diff --git a/infrastructure/job/data_source_test.go b/infrastructure/job/data_source_test.go new file mode 100644 index 00000000..380ce483 --- /dev/null +++ b/infrastructure/job/data_source_test.go @@ -0,0 +1,205 @@ +package job_test + +import ( + "encoding/json" + "github.com/duck8823/duci/domain/model/job" + . "github.com/duck8823/duci/infrastructure/job" + "github.com/duck8823/duci/infrastructure/job/mock_job" + "github.com/golang/mock/gomock" + "github.com/google/go-cmp/cmp" + "github.com/google/uuid" + "github.com/labstack/gommon/random" + "github.com/pkg/errors" + "os" + "path" + "testing" + "time" +) + +func TestNewDataSource(t *testing.T) { + t.Run("with temporary path", func(t *testing.T) { + // given + tmpPath := path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + defer func() { + _ = os.RemoveAll(tmpPath) + }() + + // when + got, err := NewDataSource(tmpPath) + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + if got == nil { + t.Error("must not be nil") + } + }) + + t.Run("with wrong path", func(t *testing.T) { + // when + got, err := NewDataSource("/path/to/wrong/path") + + // then + if err == nil { + t.Error("error must not be nil") + } + + // and + if got != nil { + t.Errorf("must be nil, but got %+v", got) + } + }) +} + +func TestDataSource_FindBy(t *testing.T) { + t.Run("when returns data", func(t *testing.T) { + // given + id := job.ID(uuid.New()) + + // and + want := &job.Job{ + ID: id, + Finished: false, + Stream: []job.LogLine{{Timestamp: time.Now(), Message: "Hello Test"}}, + } + data, err := json.Marshal(want) + if err != nil { + t.Fatalf("error occurred: %+v", err) + } + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + db := mock_job.NewMockLevelDB(ctrl) + db.EXPECT(). + Get(gomock.Eq([]byte(uuid.UUID(id).String())), gomock.Nil()). + Times(1). + Return(data, nil) + + // and + sut := &DataSource{} + defer sut.SetDB(db)() + + // when + got, err := sut.FindBy(id) + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + if !cmp.Equal(got, want) { + t.Errorf("must be equal, but %+v", cmp.Diff(got, want)) + } + }) + + t.Run("when returns error", func(t *testing.T) { + // given + id := job.ID(uuid.New()) + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + db := mock_job.NewMockLevelDB(ctrl) + db.EXPECT(). + Get(gomock.Eq([]byte(uuid.UUID(id).String())), gomock.Nil()). + Times(1). + Return(nil, errors.New("test error")) + + // and + sut := &DataSource{} + defer sut.SetDB(db)() + + // when + got, err := sut.FindBy(id) + + // then + if err == nil { + t.Error("error must not be nil") + } + + // and + if got != nil { + t.Errorf("must be nil, but got %+v", got) + } + }) +} + +func TestDataSource_Save(t *testing.T) { + t.Run("when returns no error", func(t *testing.T) { + // given + id := job.ID(uuid.New()) + + // and + job := &job.Job{ + ID: id, + Finished: false, + Stream: []job.LogLine{{Timestamp: time.Now(), Message: "Hello Test"}}, + } + data, err := json.Marshal(job) + if err != nil { + t.Fatalf("error occurred: %+v", err) + } + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + db := mock_job.NewMockLevelDB(ctrl) + db.EXPECT(). + Put(gomock.Eq([]byte(uuid.UUID(id).String())), gomock.Eq(data), gomock.Nil()). + Times(1). + Return(nil) + + // and + sut := &DataSource{} + defer sut.SetDB(db)() + + // expect + if err := sut.Save(*job); err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + }) + + t.Run("when returns error", func(t *testing.T) { + // given + id := job.ID(uuid.New()) + + // and + job := &job.Job{ + ID: id, + Finished: false, + Stream: []job.LogLine{{Timestamp: time.Now(), Message: "Hello Test"}}, + } + data, err := json.Marshal(job) + if err != nil { + t.Fatalf("error occurred: %+v", err) + } + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + db := mock_job.NewMockLevelDB(ctrl) + db.EXPECT(). + Put(gomock.Eq([]byte(uuid.UUID(id).String())), gomock.Eq(data), gomock.Nil()). + Times(1). + Return(errors.New("test error")) + + // and + sut := &DataSource{} + defer sut.SetDB(db)() + + // expect + if err := sut.Save(*job); err == nil { + t.Error("error must not be nil") + } + }) + +} diff --git a/infrastructure/job/export_test.go b/infrastructure/job/export_test.go new file mode 100644 index 00000000..bd59dd10 --- /dev/null +++ b/infrastructure/job/export_test.go @@ -0,0 +1,11 @@ +package job + +type DataSource = dataSource + +func (d *DataSource) SetDB(db LevelDB) (cancel func()) { + tmp := d.db + d.db = db + return func() { + d.db = tmp + } +} diff --git a/infrastructure/job/mock_job/third_pirty.go b/infrastructure/job/mock_job/third_pirty.go new file mode 100644 index 00000000..23d44493 --- /dev/null +++ b/infrastructure/job/mock_job/third_pirty.go @@ -0,0 +1,84 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: infrastructure/job/third_pirty.go + +// Package mock_job is a generated GoMock package. +package mock_job + +import ( + gomock "github.com/golang/mock/gomock" + opt "github.com/syndtr/goleveldb/leveldb/opt" + reflect "reflect" +) + +// MockLevelDB is a mock of LevelDB interface +type MockLevelDB struct { + ctrl *gomock.Controller + recorder *MockLevelDBMockRecorder +} + +// MockLevelDBMockRecorder is the mock recorder for MockLevelDB +type MockLevelDBMockRecorder struct { + mock *MockLevelDB +} + +// NewMockLevelDB creates a new mock instance +func NewMockLevelDB(ctrl *gomock.Controller) *MockLevelDB { + mock := &MockLevelDB{ctrl: ctrl} + mock.recorder = &MockLevelDBMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockLevelDB) EXPECT() *MockLevelDBMockRecorder { + return m.recorder +} + +// Get mocks base method +func (m *MockLevelDB) Get(key []byte, ro *opt.ReadOptions) ([]byte, error) { + ret := m.ctrl.Call(m, "Get", key, ro) + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Get indicates an expected call of Get +func (mr *MockLevelDBMockRecorder) Get(key, ro interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockLevelDB)(nil).Get), key, ro) +} + +// Has mocks base method +func (m *MockLevelDB) Has(key []byte, ro *opt.ReadOptions) (bool, error) { + ret := m.ctrl.Call(m, "Has", key, ro) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Has indicates an expected call of Has +func (mr *MockLevelDBMockRecorder) Has(key, ro interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Has", reflect.TypeOf((*MockLevelDB)(nil).Has), key, ro) +} + +// Put mocks base method +func (m *MockLevelDB) Put(key, value []byte, wo *opt.WriteOptions) error { + ret := m.ctrl.Call(m, "Put", key, value, wo) + ret0, _ := ret[0].(error) + return ret0 +} + +// Put indicates an expected call of Put +func (mr *MockLevelDBMockRecorder) Put(key, value, wo interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Put", reflect.TypeOf((*MockLevelDB)(nil).Put), key, value, wo) +} + +// Close mocks base method +func (m *MockLevelDB) Close() error { + ret := m.ctrl.Call(m, "Close") + ret0, _ := ret[0].(error) + return ret0 +} + +// Close indicates an expected call of Close +func (mr *MockLevelDBMockRecorder) Close() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockLevelDB)(nil).Close)) +} diff --git a/infrastructure/job/third_pirty.go b/infrastructure/job/third_pirty.go index b37740f9..4de53a7c 100644 --- a/infrastructure/job/third_pirty.go +++ b/infrastructure/job/third_pirty.go @@ -1,13 +1,13 @@ package job import ( - . "github.com/syndtr/goleveldb/leveldb/opt" + "github.com/syndtr/goleveldb/leveldb/opt" ) // LevelDB is a interface represents key-value store. type LevelDB interface { - Get(key []byte, ro *ReadOptions) (value []byte, err error) - Has(key []byte, ro *ReadOptions) (ret bool, err error) - Put(key, value []byte, wo *WriteOptions) error + Get(key []byte, ro *opt.ReadOptions) (value []byte, err error) + Has(key []byte, ro *opt.ReadOptions) (ret bool, err error) + Put(key, value []byte, wo *opt.WriteOptions) error Close() error } From 5c3475ca5e06736b443e5ac82af62a20a88a7565 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Wed, 26 Dec 2018 23:44:23 +0900 Subject: [PATCH 075/135] Fix test case --- infrastructure/job/data_source_test.go | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/infrastructure/job/data_source_test.go b/infrastructure/job/data_source_test.go index 380ce483..ffc0852e 100644 --- a/infrastructure/job/data_source_test.go +++ b/infrastructure/job/data_source_test.go @@ -10,6 +10,7 @@ import ( "github.com/google/uuid" "github.com/labstack/gommon/random" "github.com/pkg/errors" + "github.com/syndtr/goleveldb/leveldb" "os" "path" "testing" @@ -19,13 +20,13 @@ import ( func TestNewDataSource(t *testing.T) { t.Run("with temporary path", func(t *testing.T) { // given - tmpPath := path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) defer func() { - _ = os.RemoveAll(tmpPath) + _ = os.RemoveAll(tmpDir) }() // when - got, err := NewDataSource(tmpPath) + got, err := NewDataSource(tmpDir) // then if err != nil { @@ -39,8 +40,21 @@ func TestNewDataSource(t *testing.T) { }) t.Run("with wrong path", func(t *testing.T) { + // given + tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + defer func() { + _ = os.RemoveAll(tmpDir) + }() + + // and + db, err := leveldb.OpenFile(tmpDir, nil) + if err != nil { + t.Fatalf("error occurred: %+v", err) + } + defer db.Close() + // when - got, err := NewDataSource("/path/to/wrong/path") + got, err := NewDataSource(tmpDir) // then if err == nil { From d9dade0fbcbdfd4426efb185350abfa170a7cba0 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Sun, 30 Dec 2018 11:41:59 +0900 Subject: [PATCH 076/135] Add test for runner builder --- domain/model/runner/builder_test.go | 96 +++++++++++++++++++++++++++++ domain/model/runner/export_test.go | 27 ++++++++ 2 files changed, 123 insertions(+) create mode 100644 domain/model/runner/builder_test.go create mode 100644 domain/model/runner/export_test.go diff --git a/domain/model/runner/builder_test.go b/domain/model/runner/builder_test.go new file mode 100644 index 00000000..a848f499 --- /dev/null +++ b/domain/model/runner/builder_test.go @@ -0,0 +1,96 @@ +package runner_test + +import ( + "context" + "fmt" + "github.com/duck8823/duci/domain/model/docker" + "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/runner" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "testing" +) + +func TestDefaultDockerRunnerBuilder(t *testing.T) { + // given + opts := []cmp.Option{ + cmp.AllowUnexported(runner.Builder{}), + cmp.Transformer("LogFunc", func(l runner.LogFunc) string { + return fmt.Sprint(l) + }), + cmpopts.IgnoreInterfaces(struct{ docker.Docker }{}), + } + + // and + want := &runner.Builder{} + defer want.SetLogFunc(runner.NothingToDo)() + + // when + got := runner.DefaultDockerRunnerBuilder() + + // then + if !cmp.Equal(want, got, opts...) { + t.Errorf("must be equal, but: %+v", cmp.Diff(want, got, opts...)) + } +} + +func TestBuilder_LogFunc(t *testing.T) { + // given + opts := []cmp.Option{ + cmp.AllowUnexported(runner.Builder{}), + cmp.Transformer("LogFunc", func(l runner.LogFunc) string { + return fmt.Sprint(l) + }), + cmpopts.IgnoreInterfaces(struct{ docker.Docker }{}), + } + + // and + var wantFunc runner.LogFunc = func(context.Context, job.Log) {} + + // and + want := &runner.Builder{} + defer want.SetLogFunc(wantFunc)() + + // and + sut := &runner.Builder{} + + // when + got := sut.LogFunc(wantFunc) + + // then + if !cmp.Equal(want, got, opts...) { + t.Errorf("must be equal, but: %+v", cmp.Diff(want, got, opts...)) + } + + // and + gotFunc := sut.GetLogFunc() + if !cmp.Equal(wantFunc, gotFunc, opts...) { + t.Errorf("must be equal, but: %+v", cmp.Diff(wantFunc, gotFunc, opts...)) + } + +} + +func TestBuilder_Build(t *testing.T) { + // given + opts := []cmp.Option{ + cmp.Transformer("LogFunc", func(l runner.LogFunc) string { + return fmt.Sprint(l) + }), + } + + // + want := &runner.DockerRunnerImpl{ + LogFunc: func(context.Context, job.Log) {}, + } + + // and + sut := &runner.Builder{} + + // when + got := sut.LogFunc(want.LogFunc).Build() + + // then + if !cmp.Equal(want, got, opts...) { + t.Errorf("must be equal, but: %+v", cmp.Diff(want, got, opts...)) + } +} diff --git a/domain/model/runner/export_test.go b/domain/model/runner/export_test.go new file mode 100644 index 00000000..d0387066 --- /dev/null +++ b/domain/model/runner/export_test.go @@ -0,0 +1,27 @@ +package runner + +import "github.com/duck8823/duci/domain/model/docker" + +type Builder = builder + +func (b *builder) SetDocker(docker docker.Docker) (reset func()) { + tmp := b.docker + b.docker = docker + return func() { + b.docker = tmp + } +} + +func (b *builder) GetLogFunc() LogFunc { + return b.logFunc +} + +func (b *builder) SetLogFunc(logFunc LogFunc) (reset func()) { + tmp := b.logFunc + b.logFunc = logFunc + return func() { + b.logFunc = tmp + } +} + +type DockerRunnerImpl = dockerRunnerImpl From edcbc7bd2ce338b79fd9d61c8d5eb24da1e8efe8 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Mon, 31 Dec 2018 15:20:22 +0900 Subject: [PATCH 077/135] Add generated mock --- domain/model/job/mock_job/log.go | 47 ++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 domain/model/job/mock_job/log.go diff --git a/domain/model/job/mock_job/log.go b/domain/model/job/mock_job/log.go new file mode 100644 index 00000000..17deca5b --- /dev/null +++ b/domain/model/job/mock_job/log.go @@ -0,0 +1,47 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: domain/model/job/log.go + +// Package mock_job is a generated GoMock package. +package mock_job + +import ( + job "github.com/duck8823/duci/domain/model/job" + gomock "github.com/golang/mock/gomock" + reflect "reflect" +) + +// MockLog is a mock of Log interface +type MockLog struct { + ctrl *gomock.Controller + recorder *MockLogMockRecorder +} + +// MockLogMockRecorder is the mock recorder for MockLog +type MockLogMockRecorder struct { + mock *MockLog +} + +// NewMockLog creates a new mock instance +func NewMockLog(ctrl *gomock.Controller) *MockLog { + mock := &MockLog{ctrl: ctrl} + mock.recorder = &MockLogMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockLog) EXPECT() *MockLogMockRecorder { + return m.recorder +} + +// ReadLine mocks base method +func (m *MockLog) ReadLine() (*job.LogLine, error) { + ret := m.ctrl.Call(m, "ReadLine") + ret0, _ := ret[0].(*job.LogLine) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ReadLine indicates an expected call of ReadLine +func (mr *MockLogMockRecorder) ReadLine() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadLine", reflect.TypeOf((*MockLog)(nil).ReadLine)) +} From a34d88f4acb568b29d9ced9ee1d201fe78b37f69 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Mon, 31 Dec 2018 15:20:41 +0900 Subject: [PATCH 078/135] Add test cases for runner --- domain/model/runner/export_test.go | 6 + domain/model/runner/function_test.go | 29 ++++ domain/model/runner/helper_test.go | 214 +++++++++++++++++++++++++++ 3 files changed, 249 insertions(+) create mode 100644 domain/model/runner/function_test.go create mode 100644 domain/model/runner/helper_test.go diff --git a/domain/model/runner/export_test.go b/domain/model/runner/export_test.go index d0387066..5e14900d 100644 --- a/domain/model/runner/export_test.go +++ b/domain/model/runner/export_test.go @@ -25,3 +25,9 @@ func (b *builder) SetLogFunc(logFunc LogFunc) (reset func()) { } type DockerRunnerImpl = dockerRunnerImpl + +var CreateTarball = createTarball + +var DockerfilePath = dockerfilePath + +var ExportedRuntimeOptions = runtimeOptions diff --git a/domain/model/runner/function_test.go b/domain/model/runner/function_test.go new file mode 100644 index 00000000..813b8245 --- /dev/null +++ b/domain/model/runner/function_test.go @@ -0,0 +1,29 @@ +package runner_test + +import ( + "context" + "github.com/duck8823/duci/domain/model/job/mock_job" + "github.com/duck8823/duci/domain/model/runner" + "github.com/golang/mock/gomock" + "testing" +) + +func TestNothingToDo(t *testing.T) { + // given + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + log := mock_job.NewMockLog(ctrl) + log.EXPECT(). + ReadLine(). + Times(0). + Do(func() { + t.Error("must not call this.") + }) + + // and + sut := runner.NothingToDo + + // expect + sut(context.Background(), log) +} diff --git a/domain/model/runner/helper_test.go b/domain/model/runner/helper_test.go new file mode 100644 index 00000000..ff32d128 --- /dev/null +++ b/domain/model/runner/helper_test.go @@ -0,0 +1,214 @@ +package runner_test + +import ( + "github.com/duck8823/duci/domain/model/docker" + "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/runner" + "github.com/google/go-cmp/cmp" + "github.com/labstack/gommon/random" + "os" + "path" + "testing" +) + +func TestCreateTarball(t *testing.T) { + t.Run("with correct directory", func(t *testing.T) { + // given + tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + + if err := os.MkdirAll(tmpDir, 0700); err != nil { + t.Fatalf("error occur: %+v", err) + } + defer os.RemoveAll(tmpDir) + + if _, err := os.Create(path.Join(tmpDir, "a")); err != nil { + t.Fatalf("error occur: %+v", err) + } + + // and + want := path.Join(tmpDir, "duci.tar") + + // when + got, err := runner.CreateTarball(job.WorkDir(tmpDir)) + + // then + if err != nil { + t.Fatalf("error must be nil, but got %+v", err) + } + defer got.Close() + + // and + if got.Name() != want { + t.Errorf("file name: want %s, but got %s", want, got.Name()) + } + }) + + t.Run("with invalid directory", func(t *testing.T) { + // given + tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + + // when + got, err := runner.CreateTarball(job.WorkDir(tmpDir)) + + // then + if err == nil { + t.Error("error must not be nil") + } + + // and + if got != nil { + t.Errorf("must be nil, but got %+v", got) + + got.Close() + } + }) +} + +func TestDockerfilePath(t *testing.T) { + // where + for _, tt := range []struct { + name string + given func(t *testing.T) (workDir job.WorkDir, cleanup func()) + want docker.Dockerfile + }{ + { + name: "when .duci directory not found", + given: func(t *testing.T) (workDir job.WorkDir, cleanup func()) { + t.Helper() + + tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + if err := os.MkdirAll(tmpDir, 0700); err != nil { + t.Fatalf("error occur: %+v", err) + } + + return job.WorkDir(tmpDir), func() { + _ = os.RemoveAll(tmpDir) + } + }, + want: "./Dockerfile", + }, + { + name: "when .duci directory found but .duci/Dockerfile not found", + given: func(t *testing.T) (workDir job.WorkDir, cleanup func()) { + t.Helper() + + tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + if err := os.MkdirAll(path.Join(tmpDir, ".duci"), 0700); err != nil { + t.Fatalf("error occur: %+v", err) + } + + return job.WorkDir(tmpDir), func() { + _ = os.RemoveAll(tmpDir) + } + }, + want: "./Dockerfile", + }, + { + name: "when .duci/Dockerfile found", + given: func(t *testing.T) (workDir job.WorkDir, cleanup func()) { + t.Helper() + + tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + if err := os.MkdirAll(path.Join(tmpDir, ".duci"), 0700); err != nil { + t.Fatalf("error occur: %+v", err) + } + if _, err := os.Create(path.Join(tmpDir, ".duci", "Dockerfile")); err != nil { + t.Fatalf("error occur: %+v", err) + } + + return job.WorkDir(tmpDir), func() { + _ = os.RemoveAll(tmpDir) + } + }, + want: ".duci/Dockerfile", + }, + } { + t.Run(tt.name, func(t *testing.T) { + // given + in, cleanup := tt.given(t) + + // when + got := runner.DockerfilePath(in) + + // then + if got != tt.want { + t.Errorf("must be equal, but %+v", cmp.Diff(got, tt.want)) + } + + // cleanup + cleanup() + }) + } +} + +func TestRuntimeOptions(t *testing.T) { + // where + for _, tt := range []struct { + name string + given func(t *testing.T) (workDir job.WorkDir, cleanup func()) + want docker.RuntimeOptions + }{ + { + name: "when .duci/config.yml not found", + given: func(t *testing.T) (workDir job.WorkDir, cleanup func()) { + t.Helper() + + tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + if err := os.MkdirAll(tmpDir, 0700); err != nil { + t.Fatalf("error occur: %+v", err) + } + + return job.WorkDir(tmpDir), func() { + _ = os.RemoveAll(tmpDir) + } + }, + want: docker.RuntimeOptions{}, + }, + { + name: "when .duci/config.yml found", + given: func(t *testing.T) (workDir job.WorkDir, cleanup func()) { + t.Helper() + + tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + if err := os.MkdirAll(path.Join(tmpDir, ".duci"), 0700); err != nil { + t.Fatalf("error occur: %+v", err) + } + + file, err := os.OpenFile(path.Join(tmpDir, ".duci", "config.yml"), os.O_RDWR|os.O_CREATE, 0400) + if err != nil { + t.Fatalf("%+v", err) + } + defer file.Close() + + file.WriteString(`--- +volumes: + - hoge:fuga +`) + + return job.WorkDir(tmpDir), func() { + _ = os.RemoveAll(tmpDir) + } + }, + want: docker.RuntimeOptions{ + Volumes: docker.Volumes{"hoge:fuga"}, + }, + }, + // TODO: error pattern + } { + t.Run(tt.name, func(t *testing.T) { + // given + in, cleanup := tt.given(t) + + // when + got, _ := runner.ExportedRuntimeOptions(in) + + // then + if !cmp.Equal(got, tt.want) { + t.Errorf("must be equal, but %+v", cmp.Diff(got, tt.want)) + } + + // cleanup + cleanup() + }) + } +} From 3197cf2cb684ad741f829dbab095126aaf42a837 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Tue, 1 Jan 2019 01:03:15 +0900 Subject: [PATCH 079/135] Change to private field --- domain/model/runner/builder.go | 4 ++-- domain/model/runner/builder_test.go | 9 ++++----- domain/model/runner/export_test.go | 20 ++++++++++++++++++++ domain/model/runner/runner.go | 16 ++++++++-------- domain/model/runner/runner_test.go | 11 +++++++++++ 5 files changed, 45 insertions(+), 15 deletions(-) create mode 100644 domain/model/runner/runner_test.go diff --git a/domain/model/runner/builder.go b/domain/model/runner/builder.go index e6761f81..1a66b9e0 100644 --- a/domain/model/runner/builder.go +++ b/domain/model/runner/builder.go @@ -24,7 +24,7 @@ func (b *builder) LogFunc(f LogFunc) *builder { // Build returns a docker runner func (b *builder) Build() *dockerRunnerImpl { return &dockerRunnerImpl{ - Docker: b.docker, - LogFunc: b.logFunc, + docker: b.docker, + logFunc: b.logFunc, } } diff --git a/domain/model/runner/builder_test.go b/domain/model/runner/builder_test.go index a848f499..d63edda9 100644 --- a/domain/model/runner/builder_test.go +++ b/domain/model/runner/builder_test.go @@ -78,16 +78,15 @@ func TestBuilder_Build(t *testing.T) { }), } - // - want := &runner.DockerRunnerImpl{ - LogFunc: func(context.Context, job.Log) {}, - } + // and + want := &runner.DockerRunnerImpl{} + defer want.SetLogFunc(func(context.Context, job.Log) {})() // and sut := &runner.Builder{} // when - got := sut.LogFunc(want.LogFunc).Build() + got := sut.LogFunc(want.GetLogFunc()).Build() // then if !cmp.Equal(want, got, opts...) { diff --git a/domain/model/runner/export_test.go b/domain/model/runner/export_test.go index 5e14900d..02c9619f 100644 --- a/domain/model/runner/export_test.go +++ b/domain/model/runner/export_test.go @@ -26,6 +26,26 @@ func (b *builder) SetLogFunc(logFunc LogFunc) (reset func()) { type DockerRunnerImpl = dockerRunnerImpl +func (r *DockerRunnerImpl) SetDocker(docker docker.Docker) (reset func()) { + tmp := r.docker + r.docker = docker + return func() { + r.docker = tmp + } +} + +func (r *DockerRunnerImpl) GetLogFunc() LogFunc { + return r.logFunc +} + +func (r *DockerRunnerImpl) SetLogFunc(logFunc LogFunc) (reset func()) { + tmp := r.logFunc + r.logFunc = logFunc + return func() { + r.logFunc = tmp + } +} + var CreateTarball = createTarball var DockerfilePath = dockerfilePath diff --git a/domain/model/runner/runner.go b/domain/model/runner/runner.go index 16032fba..67d1d83c 100644 --- a/domain/model/runner/runner.go +++ b/domain/model/runner/runner.go @@ -14,8 +14,8 @@ type DockerRunner interface { // dockerRunnerImpl is a implement of DockerRunner type dockerRunnerImpl struct { - docker.Docker - LogFunc + docker docker.Docker + logFunc LogFunc } // Run task in docker container @@ -30,11 +30,11 @@ func (r *dockerRunnerImpl) Run(ctx context.Context, dir job.WorkDir, tag docker. return errors.WithStack(err) } - code, err := r.Docker.ExitCode(ctx, conID) + code, err := r.docker.ExitCode(ctx, conID) if err != nil { return errors.WithStack(err) } - if err := r.Docker.RemoveContainer(ctx, conID); err != nil { + if err := r.docker.RemoveContainer(ctx, conID); err != nil { return errors.WithStack(err) } if code != 0 { @@ -52,11 +52,11 @@ func (r *dockerRunnerImpl) dockerBuild(ctx context.Context, dir job.WorkDir, tag } defer tarball.Close() - buildLog, err := r.Docker.Build(ctx, tarball, docker.Tag(tag), dockerfilePath(dir)) + buildLog, err := r.docker.Build(ctx, tarball, docker.Tag(tag), dockerfilePath(dir)) if err != nil { return errors.WithStack(err) } - r.LogFunc(ctx, buildLog) + r.logFunc(ctx, buildLog) return nil } @@ -67,10 +67,10 @@ func (r *dockerRunnerImpl) dockerRun(ctx context.Context, dir job.WorkDir, tag d return "", errors.WithStack(err) } - conID, runLog, err := r.Docker.Run(ctx, opts, tag, cmd) + conID, runLog, err := r.docker.Run(ctx, opts, tag, cmd) if err != nil { return conID, errors.WithStack(err) } - r.LogFunc(ctx, runLog) + r.logFunc(ctx, runLog) return conID, nil } diff --git a/domain/model/runner/runner_test.go b/domain/model/runner/runner_test.go new file mode 100644 index 00000000..aa9e8f2f --- /dev/null +++ b/domain/model/runner/runner_test.go @@ -0,0 +1,11 @@ +package runner + +import "testing" + +func TestDockerRunnerImpl_Run(t *testing.T) { + // given + + // when + + // then +} From 08d502def7bea3cc789b8a657d553784d6f983f5 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Tue, 1 Jan 2019 01:04:03 +0900 Subject: [PATCH 080/135] Add pattern --- domain/model/runner/helper_test.go | 64 +++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/domain/model/runner/helper_test.go b/domain/model/runner/helper_test.go index ff32d128..835253b8 100644 --- a/domain/model/runner/helper_test.go +++ b/domain/model/runner/helper_test.go @@ -144,9 +144,10 @@ func TestDockerfilePath(t *testing.T) { func TestRuntimeOptions(t *testing.T) { // where for _, tt := range []struct { - name string - given func(t *testing.T) (workDir job.WorkDir, cleanup func()) - want docker.RuntimeOptions + name string + given func(t *testing.T) (workDir job.WorkDir, cleanup func()) + want docker.RuntimeOptions + wantErr bool }{ { name: "when .duci/config.yml not found", @@ -162,7 +163,8 @@ func TestRuntimeOptions(t *testing.T) { _ = os.RemoveAll(tmpDir) } }, - want: docker.RuntimeOptions{}, + want: docker.RuntimeOptions{}, + wantErr: false, }, { name: "when .duci/config.yml found", @@ -192,17 +194,67 @@ volumes: want: docker.RuntimeOptions{ Volumes: docker.Volumes{"hoge:fuga"}, }, + wantErr: false, + }, + { + name: "when .duci/config.yml is directory", + given: func(t *testing.T) (workDir job.WorkDir, cleanup func()) { + t.Helper() + + tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + if err := os.MkdirAll(path.Join(tmpDir, ".duci", "config.yml"), 0700); err != nil { + t.Fatalf("error occur: %+v", err) + } + + return job.WorkDir(tmpDir), func() { + _ = os.RemoveAll(tmpDir) + } + }, + want: docker.RuntimeOptions{}, + wantErr: true, + }, + { + name: "when .duci/config.yml is invalid format", + given: func(t *testing.T) (workDir job.WorkDir, cleanup func()) { + t.Helper() + + tmpDir := path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + if err := os.MkdirAll(path.Join(tmpDir, ".duci"), 0700); err != nil { + t.Fatalf("error occur: %+v", err) + } + + file, err := os.OpenFile(path.Join(tmpDir, ".duci", "config.yml"), os.O_RDWR|os.O_CREATE, 0400) + if err != nil { + t.Fatalf("%+v", err) + } + defer file.Close() + + file.WriteString("invalid format") + + return job.WorkDir(tmpDir), func() { + _ = os.RemoveAll(tmpDir) + } + }, + want: docker.RuntimeOptions{}, + wantErr: true, }, - // TODO: error pattern } { t.Run(tt.name, func(t *testing.T) { // given in, cleanup := tt.given(t) // when - got, _ := runner.ExportedRuntimeOptions(in) + got, err := runner.ExportedRuntimeOptions(in) // then + if tt.wantErr && err == nil { + t.Error("error must not be nil") + } + if !tt.wantErr && err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and if !cmp.Equal(got, tt.want) { t.Errorf("must be equal, but %+v", cmp.Diff(got, tt.want)) } From 4fae99449b2aea09830b28d7485f32500e0c703b Mon Sep 17 00:00:00 2001 From: duck8823 Date: Tue, 1 Jan 2019 11:13:19 +0900 Subject: [PATCH 081/135] Separate interface and implementation --- domain/model/docker/docker.go | 103 +--------------------------- domain/model/docker/docker_impl.go | 104 +++++++++++++++++++++++++++++ domain/model/docker/export_test.go | 2 +- 3 files changed, 108 insertions(+), 101 deletions(-) create mode 100644 domain/model/docker/docker_impl.go diff --git a/domain/model/docker/docker.go b/domain/model/docker/docker.go index 9d3f73a1..730e4ca9 100644 --- a/domain/model/docker/docker.go +++ b/domain/model/docker/docker.go @@ -2,113 +2,16 @@ package docker import ( "context" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - moby "github.com/docker/docker/client" - . "github.com/duck8823/duci/domain/model/job" - "github.com/pkg/errors" + "github.com/duck8823/duci/domain/model/job" "io" ) // Docker is a interface describe docker service. type Docker interface { - Build(ctx context.Context, file io.Reader, tag Tag, dockerfile Dockerfile) (Log, error) - Run(ctx context.Context, opts RuntimeOptions, tag Tag, cmd Command) (ContainerID, Log, error) + Build(ctx context.Context, file io.Reader, tag Tag, dockerfile Dockerfile) (job.Log, error) + Run(ctx context.Context, opts RuntimeOptions, tag Tag, cmd Command) (ContainerID, job.Log, error) RemoveContainer(ctx context.Context, containerID ContainerID) error RemoveImage(ctx context.Context, tag Tag) error ExitCode(ctx context.Context, containerID ContainerID) (ExitCode, error) Status() error } - -type client struct { - moby Moby -} - -// New returns instance of docker client -func New() (Docker, error) { - cli, err := moby.NewClientWithOpts(moby.FromEnv) - if err != nil { - return nil, errors.WithStack(err) - } - return &client{moby: cli}, nil -} - -// Build a docker image. -func (c *client) Build(ctx context.Context, file io.Reader, tag Tag, dockerfile Dockerfile) (Log, error) { - opts := types.ImageBuildOptions{ - Tags: []string{tag.String()}, - Dockerfile: dockerfile.String(), - Remove: true, - } - resp, err := c.moby.ImageBuild(ctx, file, opts) - if err != nil { - return nil, errors.WithStack(err) - } - - return NewBuildLog(resp.Body), nil -} - -// Run docker container with command. -func (c *client) Run(ctx context.Context, opts RuntimeOptions, tag Tag, cmd Command) (ContainerID, Log, error) { - con, err := c.moby.ContainerCreate(ctx, &container.Config{ - Image: tag.String(), - Env: opts.Environments.Array(), - Volumes: opts.Volumes.Map(), - Cmd: cmd.Slice(), - }, &container.HostConfig{ - Binds: opts.Volumes, - }, nil, "") - if err != nil { - return "", nil, errors.WithStack(err) - } - - if err := c.moby.ContainerStart(ctx, con.ID, types.ContainerStartOptions{}); err != nil { - return ContainerID(con.ID), nil, errors.WithStack(err) - } - - logs, err := c.moby.ContainerLogs(ctx, con.ID, types.ContainerLogsOptions{ - ShowStdout: true, - ShowStderr: true, - Follow: true, - }) - if err != nil { - return ContainerID(con.ID), nil, errors.WithStack(err) - } - - return ContainerID(con.ID), NewRunLog(logs), nil -} - -// RemoveContainer remove docker container. -func (c *client) RemoveContainer(ctx context.Context, conID ContainerID) error { - if err := c.moby.ContainerRemove(ctx, conID.String(), types.ContainerRemoveOptions{}); err != nil { - return errors.WithStack(err) - } - return nil -} - -// RemoveImage remove docker image. -func (c *client) RemoveImage(ctx context.Context, tag Tag) error { - if _, err := c.moby.ImageRemove(ctx, tag.String(), types.ImageRemoveOptions{}); err != nil { - return errors.WithStack(err) - } - return nil -} - -// ExitCode returns exit code specific container id. -func (c *client) ExitCode(ctx context.Context, conID ContainerID) (ExitCode, error) { - body, err := c.moby.ContainerWait(ctx, conID.String(), container.WaitConditionNotRunning) - select { - case b := <-body: - return ExitCode(b.StatusCode), nil - case e := <-err: - return -1, errors.WithStack(e) - } -} - -// Status returns error of docker daemon status. -func (c *client) Status() error { - if _, err := c.moby.Info(context.Background()); err != nil { - return errors.Wrap(err, "Couldn't connect to Docker daemon.") - } - return nil -} diff --git a/domain/model/docker/docker_impl.go b/domain/model/docker/docker_impl.go new file mode 100644 index 00000000..7879d460 --- /dev/null +++ b/domain/model/docker/docker_impl.go @@ -0,0 +1,104 @@ +package docker + +import ( + "context" + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + moby "github.com/docker/docker/client" + . "github.com/duck8823/duci/domain/model/job" + "github.com/pkg/errors" + "io" +) + +type dockerImpl struct { + moby Moby +} + +// New returns instance of docker dockerImpl +func New() (Docker, error) { + cli, err := moby.NewClientWithOpts(moby.FromEnv) + if err != nil { + return nil, errors.WithStack(err) + } + return &dockerImpl{moby: cli}, nil +} + +// Build a docker image. +func (c *dockerImpl) Build(ctx context.Context, file io.Reader, tag Tag, dockerfile Dockerfile) (Log, error) { + opts := types.ImageBuildOptions{ + Tags: []string{tag.String()}, + Dockerfile: dockerfile.String(), + Remove: true, + } + resp, err := c.moby.ImageBuild(ctx, file, opts) + if err != nil { + return nil, errors.WithStack(err) + } + + return NewBuildLog(resp.Body), nil +} + +// Run docker container with command. +func (c *dockerImpl) Run(ctx context.Context, opts RuntimeOptions, tag Tag, cmd Command) (ContainerID, Log, error) { + con, err := c.moby.ContainerCreate(ctx, &container.Config{ + Image: tag.String(), + Env: opts.Environments.Array(), + Volumes: opts.Volumes.Map(), + Cmd: cmd.Slice(), + }, &container.HostConfig{ + Binds: opts.Volumes, + }, nil, "") + if err != nil { + return "", nil, errors.WithStack(err) + } + + if err := c.moby.ContainerStart(ctx, con.ID, types.ContainerStartOptions{}); err != nil { + return ContainerID(con.ID), nil, errors.WithStack(err) + } + + logs, err := c.moby.ContainerLogs(ctx, con.ID, types.ContainerLogsOptions{ + ShowStdout: true, + ShowStderr: true, + Follow: true, + }) + if err != nil { + return ContainerID(con.ID), nil, errors.WithStack(err) + } + + return ContainerID(con.ID), NewRunLog(logs), nil +} + +// RemoveContainer remove docker container. +func (c *dockerImpl) RemoveContainer(ctx context.Context, conID ContainerID) error { + if err := c.moby.ContainerRemove(ctx, conID.String(), types.ContainerRemoveOptions{}); err != nil { + return errors.WithStack(err) + } + return nil +} + +// RemoveImage remove docker image. +func (c *dockerImpl) RemoveImage(ctx context.Context, tag Tag) error { + if _, err := c.moby.ImageRemove(ctx, tag.String(), types.ImageRemoveOptions{}); err != nil { + return errors.WithStack(err) + } + return nil +} + +// ExitCode returns exit code specific container id. +func (c *dockerImpl) ExitCode(ctx context.Context, conID ContainerID) (ExitCode, error) { + body, err := c.moby.ContainerWait(ctx, conID.String(), container.WaitConditionNotRunning) + select { + case b := <-body: + return ExitCode(b.StatusCode), nil + case e := <-err: + return -1, errors.WithStack(e) + } +} + +// Status returns error of docker daemon status. +func (c *dockerImpl) Status() error { + if _, err := c.moby.Info(context.Background()); err != nil { + return errors.Wrap(err, "Couldn't connect to Docker daemon.") + } + return nil +} diff --git a/domain/model/docker/export_test.go b/domain/model/docker/export_test.go index 50dd10c1..43158380 100644 --- a/domain/model/docker/export_test.go +++ b/domain/model/docker/export_test.go @@ -5,7 +5,7 @@ import ( "time" ) -type Client = client +type Client = dockerImpl func (c *Client) SetMoby(moby Moby) (reset func()) { tmp := c.moby From 91117636655c8d8c7944a1f401c9043242bc14ce Mon Sep 17 00:00:00 2001 From: duck8823 Date: Tue, 1 Jan 2019 11:13:30 +0900 Subject: [PATCH 082/135] Add docker mock --- domain/model/docker/mock_docker/docker.go | 113 ++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 domain/model/docker/mock_docker/docker.go diff --git a/domain/model/docker/mock_docker/docker.go b/domain/model/docker/mock_docker/docker.go new file mode 100644 index 00000000..5a77b39d --- /dev/null +++ b/domain/model/docker/mock_docker/docker.go @@ -0,0 +1,113 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: domain/model/docker/docker.go + +// Package mock_docker is a generated GoMock package. +package mock_docker + +import ( + context "context" + docker "github.com/duck8823/duci/domain/model/docker" + job "github.com/duck8823/duci/domain/model/job" + gomock "github.com/golang/mock/gomock" + io "io" + reflect "reflect" +) + +// MockDocker is a mock of Docker interface +type MockDocker struct { + ctrl *gomock.Controller + recorder *MockDockerMockRecorder +} + +// MockDockerMockRecorder is the mock recorder for MockDocker +type MockDockerMockRecorder struct { + mock *MockDocker +} + +// NewMockDocker creates a new mock instance +func NewMockDocker(ctrl *gomock.Controller) *MockDocker { + mock := &MockDocker{ctrl: ctrl} + mock.recorder = &MockDockerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockDocker) EXPECT() *MockDockerMockRecorder { + return m.recorder +} + +// Build mocks base method +func (m *MockDocker) Build(ctx context.Context, file io.Reader, tag docker.Tag, dockerfile docker.Dockerfile) (job.Log, error) { + ret := m.ctrl.Call(m, "Build", ctx, file, tag, dockerfile) + ret0, _ := ret[0].(job.Log) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Build indicates an expected call of Build +func (mr *MockDockerMockRecorder) Build(ctx, file, tag, dockerfile interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Build", reflect.TypeOf((*MockDocker)(nil).Build), ctx, file, tag, dockerfile) +} + +// Run mocks base method +func (m *MockDocker) Run(ctx context.Context, opts docker.RuntimeOptions, tag docker.Tag, cmd docker.Command) (docker.ContainerID, job.Log, error) { + ret := m.ctrl.Call(m, "Run", ctx, opts, tag, cmd) + ret0, _ := ret[0].(docker.ContainerID) + ret1, _ := ret[1].(job.Log) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// Run indicates an expected call of Run +func (mr *MockDockerMockRecorder) Run(ctx, opts, tag, cmd interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Run", reflect.TypeOf((*MockDocker)(nil).Run), ctx, opts, tag, cmd) +} + +// RemoveContainer mocks base method +func (m *MockDocker) RemoveContainer(ctx context.Context, containerID docker.ContainerID) error { + ret := m.ctrl.Call(m, "RemoveContainer", ctx, containerID) + ret0, _ := ret[0].(error) + return ret0 +} + +// RemoveContainer indicates an expected call of RemoveContainer +func (mr *MockDockerMockRecorder) RemoveContainer(ctx, containerID interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveContainer", reflect.TypeOf((*MockDocker)(nil).RemoveContainer), ctx, containerID) +} + +// RemoveImage mocks base method +func (m *MockDocker) RemoveImage(ctx context.Context, tag docker.Tag) error { + ret := m.ctrl.Call(m, "RemoveImage", ctx, tag) + ret0, _ := ret[0].(error) + return ret0 +} + +// RemoveImage indicates an expected call of RemoveImage +func (mr *MockDockerMockRecorder) RemoveImage(ctx, tag interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveImage", reflect.TypeOf((*MockDocker)(nil).RemoveImage), ctx, tag) +} + +// ExitCode mocks base method +func (m *MockDocker) ExitCode(ctx context.Context, containerID docker.ContainerID) (docker.ExitCode, error) { + ret := m.ctrl.Call(m, "ExitCode", ctx, containerID) + ret0, _ := ret[0].(docker.ExitCode) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ExitCode indicates an expected call of ExitCode +func (mr *MockDockerMockRecorder) ExitCode(ctx, containerID interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExitCode", reflect.TypeOf((*MockDocker)(nil).ExitCode), ctx, containerID) +} + +// Status mocks base method +func (m *MockDocker) Status() error { + ret := m.ctrl.Call(m, "Status") + ret0, _ := ret[0].(error) + return ret0 +} + +// Status indicates an expected call of Status +func (mr *MockDockerMockRecorder) Status() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Status", reflect.TypeOf((*MockDocker)(nil).Status)) +} From b72c8145088eb70d7ebd680bf7860124c97107ff Mon Sep 17 00:00:00 2001 From: duck8823 Date: Tue, 1 Jan 2019 11:14:27 +0900 Subject: [PATCH 083/135] Add runner test --- domain/model/runner/export_test.go | 3 ++ domain/model/runner/runner_test.go | 66 +++++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/domain/model/runner/export_test.go b/domain/model/runner/export_test.go index 02c9619f..2a1d7e87 100644 --- a/domain/model/runner/export_test.go +++ b/domain/model/runner/export_test.go @@ -51,3 +51,6 @@ var CreateTarball = createTarball var DockerfilePath = dockerfilePath var ExportedRuntimeOptions = runtimeOptions + +type StubLog struct { +} diff --git a/domain/model/runner/runner_test.go b/domain/model/runner/runner_test.go index aa9e8f2f..32e15ef8 100644 --- a/domain/model/runner/runner_test.go +++ b/domain/model/runner/runner_test.go @@ -1,11 +1,73 @@ -package runner +package runner_test -import "testing" +import ( + "context" + "github.com/duck8823/duci/domain/model/docker" + "github.com/duck8823/duci/domain/model/docker/mock_docker" + "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/job/mock_job" + "github.com/duck8823/duci/domain/model/runner" + "github.com/golang/mock/gomock" + "github.com/labstack/gommon/random" + "io" + "os" + "path" + "testing" + "time" +) func TestDockerRunnerImpl_Run(t *testing.T) { // given + dir := job.WorkDir(path.Join(os.TempDir(), random.String(16, random.Alphanumeric))) + if err := os.MkdirAll(dir.String(), 0700); err != nil { + t.Fatalf("error occur: %+v", err) + } + defer func() { + _ = os.RemoveAll(dir.String()) + }() + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + // and + log := mock_job.NewMockLog(ctrl) + log.EXPECT(). + ReadLine(). + AnyTimes(). + Return(&job.LogLine{Timestamp: time.Now(), Message: "Hello Test"}, io.EOF) + + // and + containerID := docker.ContainerID(random.String(16, random.Alphanumeric)) + + mockDocker := mock_docker.NewMockDocker(ctrl) + mockDocker.EXPECT(). + Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Return(log, nil) + mockDocker.EXPECT(). + Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Return(containerID, log, nil) + mockDocker.EXPECT(). + ExitCode(gomock.Any(), gomock.Eq(containerID)). + Times(1). + Return(docker.ExitCode(0), nil) + mockDocker.EXPECT(). + RemoveContainer(gomock.Any(), gomock.Eq(containerID)). + Times(1). + Return(nil) + + // and + sut := runner.DockerRunnerImpl{} + defer sut.SetDocker(mockDocker)() + defer sut.SetLogFunc(runner.NothingToDo)() // when + err := sut.Run(context.Background(), dir, "", []string{""}) // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } } From ca63afac726051256697032d261a1297b57db988 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Tue, 1 Jan 2019 13:56:00 +0900 Subject: [PATCH 084/135] Fix allow unexported structure --- domain/model/runner/builder_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/domain/model/runner/builder_test.go b/domain/model/runner/builder_test.go index d63edda9..7400819b 100644 --- a/domain/model/runner/builder_test.go +++ b/domain/model/runner/builder_test.go @@ -73,6 +73,7 @@ func TestBuilder_LogFunc(t *testing.T) { func TestBuilder_Build(t *testing.T) { // given opts := []cmp.Option{ + cmp.AllowUnexported(runner.DockerRunnerImpl{}), cmp.Transformer("LogFunc", func(l runner.LogFunc) string { return fmt.Sprint(l) }), From cd496068145a0a7d6fdd46d53e82ad4cb045f54f Mon Sep 17 00:00:00 2001 From: duck8823 Date: Tue, 1 Jan 2019 15:37:34 +0900 Subject: [PATCH 085/135] Add test pattern --- domain/model/runner/runner.go | 2 +- domain/model/runner/runner_test.go | 403 ++++++++++++++++++++++++++--- 2 files changed, 362 insertions(+), 43 deletions(-) diff --git a/domain/model/runner/runner.go b/domain/model/runner/runner.go index 67d1d83c..32069f23 100644 --- a/domain/model/runner/runner.go +++ b/domain/model/runner/runner.go @@ -37,7 +37,7 @@ func (r *dockerRunnerImpl) Run(ctx context.Context, dir job.WorkDir, tag docker. if err := r.docker.RemoveContainer(ctx, conID); err != nil { return errors.WithStack(err) } - if code != 0 { + if code.IsFailure() { return ErrFailure } diff --git a/domain/model/runner/runner_test.go b/domain/model/runner/runner_test.go index 32e15ef8..9df7beb9 100644 --- a/domain/model/runner/runner_test.go +++ b/domain/model/runner/runner_test.go @@ -2,6 +2,7 @@ package runner_test import ( "context" + "fmt" "github.com/duck8823/duci/domain/model/docker" "github.com/duck8823/duci/domain/model/docker/mock_docker" "github.com/duck8823/duci/domain/model/job" @@ -9,6 +10,7 @@ import ( "github.com/duck8823/duci/domain/model/runner" "github.com/golang/mock/gomock" "github.com/labstack/gommon/random" + "github.com/pkg/errors" "io" "os" "path" @@ -17,57 +19,374 @@ import ( ) func TestDockerRunnerImpl_Run(t *testing.T) { - // given - dir := job.WorkDir(path.Join(os.TempDir(), random.String(16, random.Alphanumeric))) + t.Run("with no error", func(t *testing.T) { + // given + dir, cleanup := tmpDir(t) + defer cleanup() + + tag := docker.Tag(fmt.Sprintf("duci/test:%s", random.String(8))) + cmd := docker.Command{"echo", "test"} + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + // and + log := stubLog(t, ctrl) + conID := docker.ContainerID(random.String(16, random.Alphanumeric)) + + mockDocker := mock_docker.NewMockDocker(ctrl) + mockDocker.EXPECT(). + Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Return(log, nil) + mockDocker.EXPECT(). + Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Return(conID, log, nil) + mockDocker.EXPECT(). + ExitCode(gomock.Any(), gomock.Eq(conID)). + Times(1). + Return(docker.ExitCode(0), nil) + mockDocker.EXPECT(). + RemoveContainer(gomock.Any(), gomock.Eq(conID)). + Times(1). + Return(nil) + + // and + sut := runner.DockerRunnerImpl{} + defer sut.SetDocker(mockDocker)() + defer sut.SetLogFunc(runner.NothingToDo)() + + // when + err := sut.Run(context.Background(), dir, tag, cmd) + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + }) + + t.Run("when failure create tarball", func(t *testing.T) { + // given + dir, cleanup := tmpDir(t) + defer cleanup() + + tag := docker.Tag(fmt.Sprintf("duci/test:%s", random.String(8))) + cmd := docker.Command{"echo", "test"} + + // and + if err := os.MkdirAll(path.Join(dir.String(), "duci.tar"), 0700); err != nil { + t.Fatalf("error occur: %+v", err) + } + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + // and + mockDocker := mock_docker.NewMockDocker(ctrl) + mockDocker.EXPECT(). + Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(0) + + // and + sut := runner.DockerRunnerImpl{} + defer sut.SetDocker(mockDocker)() + defer sut.SetLogFunc(runner.NothingToDo)() + + // when + err := sut.Run(context.Background(), dir, tag, cmd) + + // then + if err == nil { + t.Errorf("error must not be nil") + } + }) + + t.Run("when failure load runtime options", func(t *testing.T) { + // given + dir, cleanup := tmpDir(t) + defer cleanup() + + tag := docker.Tag(fmt.Sprintf("duci/test:%s", random.String(8))) + cmd := docker.Command{"echo", "test"} + + // and + if err := os.MkdirAll(path.Join(dir.String(), ".duci", "config.yml"), 0700); err != nil { + t.Fatalf("error occur: %+v", err) + } + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + // and + log := stubLog(t, ctrl) + + mockDocker := mock_docker.NewMockDocker(ctrl) + mockDocker.EXPECT(). + Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Return(log, nil) + mockDocker.EXPECT(). + Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(0) + + // and + sut := runner.DockerRunnerImpl{} + defer sut.SetDocker(mockDocker)() + defer sut.SetLogFunc(runner.NothingToDo)() + + // expect + if err := sut.Run(context.Background(), dir, tag, cmd); err == nil { + t.Errorf("error must not be nil") + } + }) + + t.Run("when failure docker build", func(t *testing.T) { + // given + dir, cleanup := tmpDir(t) + defer cleanup() + + tag := docker.Tag(fmt.Sprintf("duci/test:%s", random.String(8))) + cmd := docker.Command{"echo", "test"} + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + // and + mockDocker := mock_docker.NewMockDocker(ctrl) + mockDocker.EXPECT(). + Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Return(nil, errors.New("error test")) + mockDocker.EXPECT(). + Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(0) + + // and + sut := runner.DockerRunnerImpl{} + defer sut.SetDocker(mockDocker)() + defer sut.SetLogFunc(runner.NothingToDo)() + + // when + err := sut.Run(context.Background(), dir, tag, cmd) + + // then + if err == nil { + t.Errorf("error must not be nil") + } + }) + + t.Run("when failure docker run", func(t *testing.T) { + // given + dir, cleanup := tmpDir(t) + defer cleanup() + + tag := docker.Tag(fmt.Sprintf("duci/test:%s", random.String(8))) + cmd := docker.Command{"echo", "test"} + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + // and + log := stubLog(t, ctrl) + conID := docker.ContainerID(random.String(16, random.Alphanumeric)) + + mockDocker := mock_docker.NewMockDocker(ctrl) + mockDocker.EXPECT(). + Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Return(log, nil) + mockDocker.EXPECT(). + Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Return(conID, nil, errors.New("test error")) + mockDocker.EXPECT(). + ExitCode(gomock.Any(), gomock.Eq(conID)). + Times(0) + + // and + sut := runner.DockerRunnerImpl{} + defer sut.SetDocker(mockDocker)() + defer sut.SetLogFunc(runner.NothingToDo)() + + // when + err := sut.Run(context.Background(), dir, tag, cmd) + + // then + if err == nil { + t.Error("error must not be nil") + } + }) + + t.Run("when failure to get exit code", func(t *testing.T) { + // given + dir, cleanup := tmpDir(t) + defer cleanup() + + tag := docker.Tag(fmt.Sprintf("duci/test:%s", random.String(8))) + cmd := docker.Command{"echo", "test"} + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + // and + log := stubLog(t, ctrl) + conID := docker.ContainerID(random.String(16, random.Alphanumeric)) + + mockDocker := mock_docker.NewMockDocker(ctrl) + mockDocker.EXPECT(). + Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Return(log, nil) + mockDocker.EXPECT(). + Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Return(conID, log, nil) + mockDocker.EXPECT(). + ExitCode(gomock.Any(), gomock.Eq(conID)). + Times(1). + Return(docker.ExitCode(0), errors.New("test error")) + mockDocker.EXPECT(). + RemoveContainer(gomock.Any(), gomock.Eq(conID)). + Times(0). + Return(nil) + + // and + sut := runner.DockerRunnerImpl{} + defer sut.SetDocker(mockDocker)() + defer sut.SetLogFunc(runner.NothingToDo)() + + // when + err := sut.Run(context.Background(), dir, tag, cmd) + + // then + if err == nil { + t.Error("error must not be nil") + } + }) + + t.Run("when exit code is not zero", func(t *testing.T) { + // given + dir, cleanup := tmpDir(t) + defer cleanup() + + tag := docker.Tag(fmt.Sprintf("duci/test:%s", random.String(8))) + cmd := docker.Command{"echo", "test"} + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + // and + log := stubLog(t, ctrl) + conID := docker.ContainerID(random.String(16, random.Alphanumeric)) + + mockDocker := mock_docker.NewMockDocker(ctrl) + mockDocker.EXPECT(). + Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Return(log, nil) + mockDocker.EXPECT(). + Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Return(conID, log, nil) + mockDocker.EXPECT(). + ExitCode(gomock.Any(), gomock.Eq(conID)). + Times(1). + Return(docker.ExitCode(-1), nil) + mockDocker.EXPECT(). + RemoveContainer(gomock.Any(), gomock.Eq(conID)). + Times(1). + Return(nil) + + // and + sut := runner.DockerRunnerImpl{} + defer sut.SetDocker(mockDocker)() + defer sut.SetLogFunc(runner.NothingToDo)() + + // when + err := sut.Run(context.Background(), dir, tag, cmd) + + // then + if err != runner.ErrFailure { + t.Errorf("error must be ErrFailure, but got %+v", err) + } + }) + + t.Run("when failure docker remove container", func(t *testing.T) { + // given + dir, cleanup := tmpDir(t) + defer cleanup() + + tag := docker.Tag(fmt.Sprintf("duci/test:%s", random.String(8))) + cmd := docker.Command{"echo", "test"} + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + // and + log := stubLog(t, ctrl) + conID := docker.ContainerID(random.String(16, random.Alphanumeric)) + + mockDocker := mock_docker.NewMockDocker(ctrl) + mockDocker.EXPECT(). + Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Return(log, nil) + mockDocker.EXPECT(). + Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Return(conID, log, nil) + mockDocker.EXPECT(). + ExitCode(gomock.Any(), gomock.Eq(conID)). + Times(1). + Return(docker.ExitCode(0), nil) + mockDocker.EXPECT(). + RemoveContainer(gomock.Any(), gomock.Eq(conID)). + Times(1). + Return(errors.New("test error")) + + // and + sut := runner.DockerRunnerImpl{} + defer sut.SetDocker(mockDocker)() + defer sut.SetLogFunc(runner.NothingToDo)() + + // when + err := sut.Run(context.Background(), dir, tag, cmd) + + // then + if err == nil { + t.Error("error must not be nil") + } + }) +} + +func tmpDir(t *testing.T) (workDir job.WorkDir, clean func()) { + t.Helper() + + dir := job.WorkDir(path.Join(os.TempDir(), random.String(16))) if err := os.MkdirAll(dir.String(), 0700); err != nil { t.Fatalf("error occur: %+v", err) } - defer func() { + return dir, func() { _ = os.RemoveAll(dir.String()) - }() + } +} - // and - ctrl := gomock.NewController(t) - defer ctrl.Finish() +func stubLog(t *testing.T, ctrl *gomock.Controller) *mock_job.MockLog { + t.Helper() - // and log := mock_job.NewMockLog(ctrl) log.EXPECT(). ReadLine(). AnyTimes(). Return(&job.LogLine{Timestamp: time.Now(), Message: "Hello Test"}, io.EOF) - - // and - containerID := docker.ContainerID(random.String(16, random.Alphanumeric)) - - mockDocker := mock_docker.NewMockDocker(ctrl) - mockDocker.EXPECT(). - Build(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - Return(log, nil) - mockDocker.EXPECT(). - Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Times(1). - Return(containerID, log, nil) - mockDocker.EXPECT(). - ExitCode(gomock.Any(), gomock.Eq(containerID)). - Times(1). - Return(docker.ExitCode(0), nil) - mockDocker.EXPECT(). - RemoveContainer(gomock.Any(), gomock.Eq(containerID)). - Times(1). - Return(nil) - - // and - sut := runner.DockerRunnerImpl{} - defer sut.SetDocker(mockDocker)() - defer sut.SetLogFunc(runner.NothingToDo)() - - // when - err := sut.Run(context.Background(), dir, "", []string{""}) - - // then - if err != nil { - t.Errorf("error must be nil, but got %+v", err) - } + return log } From e43363be7ba5ea3de82f7be695366fd1ed79b218 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Tue, 1 Jan 2019 17:52:36 +0900 Subject: [PATCH 086/135] Add test case --- infrastructure/job/data_source_test.go | 64 ++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/infrastructure/job/data_source_test.go b/infrastructure/job/data_source_test.go index ffc0852e..6fd29f87 100644 --- a/infrastructure/job/data_source_test.go +++ b/infrastructure/job/data_source_test.go @@ -143,6 +143,70 @@ func TestDataSource_FindBy(t *testing.T) { t.Errorf("must be nil, but got %+v", got) } }) + + t.Run("when leveldb.ErrNotFound", func(t *testing.T) { + // given + id := job.ID(uuid.New()) + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + db := mock_job.NewMockLevelDB(ctrl) + db.EXPECT(). + Get(gomock.Eq([]byte(uuid.UUID(id).String())), gomock.Nil()). + Times(1). + Return(nil, leveldb.ErrNotFound) + + // and + sut := &DataSource{} + defer sut.SetDB(db)() + + // when + got, err := sut.FindBy(id) + + // then + if err == nil { + t.Error("error must not be nil") + } + + // and + if got != nil { + t.Errorf("must be nil, but got %+v", got) + } + }) + + t.Run("when stored data is invalid format", func(t *testing.T) { + // given + id := job.ID(uuid.New()) + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + db := mock_job.NewMockLevelDB(ctrl) + db.EXPECT(). + Get(gomock.Eq([]byte(uuid.UUID(id).String())), gomock.Nil()). + Times(1). + Return([]byte("invalid format"), nil) + + // and + sut := &DataSource{} + defer sut.SetDB(db)() + + // when + got, err := sut.FindBy(id) + + // then + if err == nil { + t.Error("error must not be nil") + } + + // and + if got != nil { + t.Errorf("must be nil, but got %+v", got) + } + }) } func TestDataSource_Save(t *testing.T) { From 820eb25625f9842616dd5fd3c8a784e750581b7c Mon Sep 17 00:00:00 2001 From: duck8823 Date: Tue, 1 Jan 2019 18:01:42 +0900 Subject: [PATCH 087/135] Remove unused interface function --- infrastructure/job/mock_job/third_pirty.go | 25 ---------------------- infrastructure/job/third_pirty.go | 2 -- 2 files changed, 27 deletions(-) diff --git a/infrastructure/job/mock_job/third_pirty.go b/infrastructure/job/mock_job/third_pirty.go index 23d44493..64f6e437 100644 --- a/infrastructure/job/mock_job/third_pirty.go +++ b/infrastructure/job/mock_job/third_pirty.go @@ -46,19 +46,6 @@ func (mr *MockLevelDBMockRecorder) Get(key, ro interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockLevelDB)(nil).Get), key, ro) } -// Has mocks base method -func (m *MockLevelDB) Has(key []byte, ro *opt.ReadOptions) (bool, error) { - ret := m.ctrl.Call(m, "Has", key, ro) - ret0, _ := ret[0].(bool) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Has indicates an expected call of Has -func (mr *MockLevelDBMockRecorder) Has(key, ro interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Has", reflect.TypeOf((*MockLevelDB)(nil).Has), key, ro) -} - // Put mocks base method func (m *MockLevelDB) Put(key, value []byte, wo *opt.WriteOptions) error { ret := m.ctrl.Call(m, "Put", key, value, wo) @@ -70,15 +57,3 @@ func (m *MockLevelDB) Put(key, value []byte, wo *opt.WriteOptions) error { func (mr *MockLevelDBMockRecorder) Put(key, value, wo interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Put", reflect.TypeOf((*MockLevelDB)(nil).Put), key, value, wo) } - -// Close mocks base method -func (m *MockLevelDB) Close() error { - ret := m.ctrl.Call(m, "Close") - ret0, _ := ret[0].(error) - return ret0 -} - -// Close indicates an expected call of Close -func (mr *MockLevelDBMockRecorder) Close() *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockLevelDB)(nil).Close)) -} diff --git a/infrastructure/job/third_pirty.go b/infrastructure/job/third_pirty.go index 4de53a7c..9f5a3410 100644 --- a/infrastructure/job/third_pirty.go +++ b/infrastructure/job/third_pirty.go @@ -7,7 +7,5 @@ import ( // LevelDB is a interface represents key-value store. type LevelDB interface { Get(key []byte, ro *opt.ReadOptions) (value []byte, err error) - Has(key []byte, ro *opt.ReadOptions) (ret bool, err error) Put(key, value []byte, wo *opt.WriteOptions) error - Close() error } From 41032e3eb4ef34bfa18d223bc3df4df9b287ca13 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Tue, 1 Jan 2019 18:44:10 +0900 Subject: [PATCH 088/135] Use generated mock --- domain/model/job/target/git/export_test.go | 23 ------- .../model/job/target/git/http_client_test.go | 60 +++++++++++++++++-- .../model/job/target/git/ssh_client_test.go | 59 ++++++++++++++++-- 3 files changed, 111 insertions(+), 31 deletions(-) diff --git a/domain/model/job/target/git/export_test.go b/domain/model/job/target/git/export_test.go index fa6a1371..08d2488a 100644 --- a/domain/model/job/target/git/export_test.go +++ b/domain/model/job/target/git/export_test.go @@ -4,7 +4,6 @@ import ( "bufio" "context" "gopkg.in/src-d/go-git.v4" - "gopkg.in/src-d/go-git.v4/plumbing" "time" ) @@ -38,28 +37,6 @@ func SetNowFunc(f func() time.Time) (reset func()) { } } -type MockTargetSource struct { - URL string - Ref string - SHA plumbing.Hash -} - -func (t *MockTargetSource) GetCloneURL() string { - return t.URL -} - -func (t *MockTargetSource) GetSSHURL() string { - return t.URL -} - -func (t *MockTargetSource) GetRef() string { - return t.Ref -} - -func (t *MockTargetSource) GetSHA() plumbing.Hash { - return t.SHA -} - func (l *ProgressLogger) SetContext(ctx context.Context) (reset func()) { tmp := l.ctx l.ctx = ctx diff --git a/domain/model/job/target/git/http_client_test.go b/domain/model/job/target/git/http_client_test.go index ed989d66..a0b718ad 100644 --- a/domain/model/job/target/git/http_client_test.go +++ b/domain/model/job/target/git/http_client_test.go @@ -5,8 +5,10 @@ import ( "errors" "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/job/target/git" + "github.com/duck8823/duci/domain/model/job/target/git/mock_git" "github.com/duck8823/duci/domain/model/runner" "github.com/duck8823/duci/internal/container" + "github.com/golang/mock/gomock" "github.com/labstack/gommon/random" go_git "gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4/plumbing" @@ -53,6 +55,20 @@ func TestHttpGitClient_Clone(t *testing.T) { }) defer reset() + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + targetSrc := mock_git.NewMockTargetSource(ctrl) + targetSrc.EXPECT(). + GetCloneURL(). + Times(1). + Times(1).Return("http://github.com/duck8823/duci.git") + targetSrc.EXPECT(). + GetRef(). + Times(1). + Return("HEAD") + // and sut := &git.HttpGitClient{LogFunc: runner.NothingToDo} @@ -60,7 +76,7 @@ func TestHttpGitClient_Clone(t *testing.T) { if err := sut.Clone( context.Background(), "/path/to/dummy", - &git.MockTargetSource{}, + targetSrc, ); err == nil { t.Error("error must not nil.") } @@ -93,11 +109,29 @@ func TestHttpGitClient_Clone(t *testing.T) { tmpDir, reset := createTmpDir(t) defer reset() - // amd + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + targetSrc := mock_git.NewMockTargetSource(ctrl) + targetSrc.EXPECT(). + GetCloneURL(). + Times(1). + Times(1).Return("http://github.com/duck8823/duci.git") + targetSrc.EXPECT(). + GetRef(). + Times(1). + Return("HEAD") + targetSrc.EXPECT(). + GetSHA(). + Times(1). + Return(hash) + + // and sut := &git.HttpGitClient{LogFunc: runner.NothingToDo} // expect - if err := sut.Clone(context.Background(), tmpDir, &git.MockTargetSource{Ref: "HEAD", SHA: hash}); err != nil { + if err := sut.Clone(context.Background(), tmpDir, targetSrc); err != nil { t.Errorf("error must be nil, but got %+v", err) } }) @@ -117,11 +151,29 @@ func TestHttpGitClient_Clone(t *testing.T) { tmpDir, reset := createTmpDir(t) defer reset() + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + targetSrc := mock_git.NewMockTargetSource(ctrl) + targetSrc.EXPECT(). + GetCloneURL(). + Times(1). + Return("http://github.com/duck8823/duci.git") + targetSrc.EXPECT(). + GetRef(). + Times(1). + Return("HEAD") + targetSrc.EXPECT(). + GetSHA(). + Times(1). + Return(plumbing.ZeroHash) + // and sut := &git.HttpGitClient{LogFunc: runner.NothingToDo} // expect - if err := sut.Clone(context.Background(), tmpDir, &git.MockTargetSource{Ref: "HEAD"}); err == nil { + if err := sut.Clone(context.Background(), tmpDir, targetSrc); err == nil { t.Error("error must not be nil") } }) diff --git a/domain/model/job/target/git/ssh_client_test.go b/domain/model/job/target/git/ssh_client_test.go index 822f97f7..32ec406f 100644 --- a/domain/model/job/target/git/ssh_client_test.go +++ b/domain/model/job/target/git/ssh_client_test.go @@ -9,8 +9,10 @@ import ( "errors" "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/job/target/git" + "github.com/duck8823/duci/domain/model/job/target/git/mock_git" "github.com/duck8823/duci/domain/model/runner" "github.com/duck8823/duci/internal/container" + "github.com/golang/mock/gomock" "github.com/labstack/gommon/random" go_git "gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4/plumbing" @@ -80,6 +82,20 @@ func TestSshGitClient_Clone(t *testing.T) { }) defer reset() + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + targetSrc := mock_git.NewMockTargetSource(ctrl) + targetSrc.EXPECT(). + GetSSHURL(). + Times(1). + Return("git@github.com:duck8823/duci.git") + targetSrc.EXPECT(). + GetRef(). + Times(1). + Return("HEAD") + // and sut := &git.SshGitClient{LogFunc: runner.NothingToDo} @@ -87,7 +103,7 @@ func TestSshGitClient_Clone(t *testing.T) { if err := sut.Clone( context.Background(), "/path/to/dummy", - &git.MockTargetSource{}, + targetSrc, ); err == nil { t.Error("error must not nil.") } @@ -120,11 +136,28 @@ func TestSshGitClient_Clone(t *testing.T) { tmpDir, reset := createTmpDir(t) defer reset() - // amd + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + targetSrc := mock_git.NewMockTargetSource(ctrl) + targetSrc.EXPECT(). + GetSSHURL(). + Times(1) + targetSrc.EXPECT(). + GetRef(). + Times(1). + Return("HEAD") + targetSrc.EXPECT(). + GetSHA(). + Times(1). + Return(hash) + + // and sut := &git.SshGitClient{LogFunc: runner.NothingToDo} // expect - if err := sut.Clone(context.Background(), tmpDir, &git.MockTargetSource{Ref: "HEAD", SHA: hash}); err != nil { + if err := sut.Clone(context.Background(), tmpDir, targetSrc); err != nil { t.Errorf("error must be nil, but got %+v", err) } }) @@ -144,11 +177,29 @@ func TestSshGitClient_Clone(t *testing.T) { tmpDir, reset := createTmpDir(t) defer reset() + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + targetSrc := mock_git.NewMockTargetSource(ctrl) + targetSrc.EXPECT(). + GetSSHURL(). + Times(1). + Return("git@github.com:duck8823/duci.git") + targetSrc.EXPECT(). + GetRef(). + Times(1). + Return("HEAD") + targetSrc.EXPECT(). + GetSHA(). + Times(1). + Return(plumbing.ZeroHash) + // and sut := &git.SshGitClient{LogFunc: runner.NothingToDo} // expect - if err := sut.Clone(context.Background(), tmpDir, &git.MockTargetSource{Ref: "HEAD"}); err == nil { + if err := sut.Clone(context.Background(), tmpDir, targetSrc); err == nil { t.Error("error must not be nil") } }) From 766d513acae9a5b68da595fa0ade389ada97335b Mon Sep 17 00:00:00 2001 From: duck8823 Date: Wed, 2 Jan 2019 01:32:38 +0900 Subject: [PATCH 089/135] Move package --- main.go | 2 +- {application => presentation}/cmd/config.go | 0 {application => presentation}/cmd/health.go | 0 {application => presentation}/cmd/root.go | 0 {application => presentation}/cmd/server.go | 0 {application => presentation}/cmd/version.go | 0 6 files changed, 1 insertion(+), 1 deletion(-) rename {application => presentation}/cmd/config.go (100%) rename {application => presentation}/cmd/health.go (100%) rename {application => presentation}/cmd/root.go (100%) rename {application => presentation}/cmd/server.go (100%) rename {application => presentation}/cmd/version.go (100%) diff --git a/main.go b/main.go index d71b1ebe..af0d184e 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,7 @@ package main import ( - "github.com/duck8823/duci/application/cmd" + "github.com/duck8823/duci/presentation/cmd" "os" ) diff --git a/application/cmd/config.go b/presentation/cmd/config.go similarity index 100% rename from application/cmd/config.go rename to presentation/cmd/config.go diff --git a/application/cmd/health.go b/presentation/cmd/health.go similarity index 100% rename from application/cmd/health.go rename to presentation/cmd/health.go diff --git a/application/cmd/root.go b/presentation/cmd/root.go similarity index 100% rename from application/cmd/root.go rename to presentation/cmd/root.go diff --git a/application/cmd/server.go b/presentation/cmd/server.go similarity index 100% rename from application/cmd/server.go rename to presentation/cmd/server.go diff --git a/application/cmd/version.go b/presentation/cmd/version.go similarity index 100% rename from application/cmd/version.go rename to presentation/cmd/version.go From 0f07c07909f2b304a34807b522a20c67188417ee Mon Sep 17 00:00:00 2001 From: duck8823 Date: Wed, 2 Jan 2019 10:11:06 +0900 Subject: [PATCH 090/135] Add handler test --- .../executor/mock_executor/executor.go | 52 ++++++ presentation/controller/health/export_test.go | 13 ++ .../controller/health/handler_test.go | 125 +++++++++++++ presentation/controller/job/export_test.go | 13 ++ presentation/controller/job/handler_test.go | 167 ++++++++++++++++++ .../controller/webhook/export_test.go | 15 ++ .../controller/webhook/handler_test.go | 114 ++++++++++++ .../webhook/testdata/push.correct.json | 135 ++++++++++++++ 8 files changed, 634 insertions(+) create mode 100644 application/service/executor/mock_executor/executor.go create mode 100644 presentation/controller/health/export_test.go create mode 100644 presentation/controller/health/handler_test.go create mode 100644 presentation/controller/job/export_test.go create mode 100644 presentation/controller/job/handler_test.go create mode 100644 presentation/controller/webhook/export_test.go create mode 100644 presentation/controller/webhook/handler_test.go create mode 100644 presentation/controller/webhook/testdata/push.correct.json diff --git a/application/service/executor/mock_executor/executor.go b/application/service/executor/mock_executor/executor.go new file mode 100644 index 00000000..0550d8de --- /dev/null +++ b/application/service/executor/mock_executor/executor.go @@ -0,0 +1,52 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: application/service/executor/executor.go + +// Package mock_executor is a generated GoMock package. +package mock_executor + +import ( + context "context" + job "github.com/duck8823/duci/domain/model/job" + gomock "github.com/golang/mock/gomock" + reflect "reflect" +) + +// MockExecutor is a mock of Executor interface +type MockExecutor struct { + ctrl *gomock.Controller + recorder *MockExecutorMockRecorder +} + +// MockExecutorMockRecorder is the mock recorder for MockExecutor +type MockExecutorMockRecorder struct { + mock *MockExecutor +} + +// NewMockExecutor creates a new mock instance +func NewMockExecutor(ctrl *gomock.Controller) *MockExecutor { + mock := &MockExecutor{ctrl: ctrl} + mock.recorder = &MockExecutorMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockExecutor) EXPECT() *MockExecutorMockRecorder { + return m.recorder +} + +// Execute mocks base method +func (m *MockExecutor) Execute(ctx context.Context, target job.Target, cmd ...string) error { + varargs := []interface{}{ctx, target} + for _, a := range cmd { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Execute", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Execute indicates an expected call of Execute +func (mr *MockExecutorMockRecorder) Execute(ctx, target interface{}, cmd ...interface{}) *gomock.Call { + varargs := append([]interface{}{ctx, target}, cmd...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Execute", reflect.TypeOf((*MockExecutor)(nil).Execute), varargs...) +} diff --git a/presentation/controller/health/export_test.go b/presentation/controller/health/export_test.go new file mode 100644 index 00000000..c1044e30 --- /dev/null +++ b/presentation/controller/health/export_test.go @@ -0,0 +1,13 @@ +package health + +import "github.com/duck8823/duci/domain/model/docker" + +type Handler = handler + +func (c *Handler) SetDocker(docker docker.Docker) (reset func()) { + tmp := c.docker + c.docker = docker + return func() { + c.docker = tmp + } +} diff --git a/presentation/controller/health/handler_test.go b/presentation/controller/health/handler_test.go new file mode 100644 index 00000000..162c0afa --- /dev/null +++ b/presentation/controller/health/handler_test.go @@ -0,0 +1,125 @@ +package health_test + +import ( + "github.com/duck8823/duci/domain/model/docker" + "github.com/duck8823/duci/domain/model/docker/mock_docker" + "github.com/duck8823/duci/presentation/controller/health" + "github.com/golang/mock/gomock" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/pkg/errors" + "net/http" + "net/http/httptest" + "os" + "testing" +) + +func TestNewHandler(t *testing.T) { + t.Run("with default", func(t *testing.T) { + // given + defaultDocker, err := docker.New() + if err != nil { + t.Fatalf("error occur: %+v", err) + } + + // and + want := &health.Handler{} + defer want.SetDocker(defaultDocker)() + + // when + got, err := health.NewHandler() + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + opts := cmp.Options{ + cmp.AllowUnexported(health.Handler{}), + cmpopts.IgnoreInterfaces(struct{ docker.Moby }{}), + } + if !cmp.Equal(got, want, opts) { + t.Errorf("must be equal, but: %+v", cmp.Diff(got, want, opts)) + } + }) + + t.Run("with invalid environment variable", func(t *testing.T) { + // given + DOCKER_HOST := os.Getenv("DOCKER_HOST") + if err := os.Setenv("DOCKER_HOST", "invalid host"); err != nil { + t.Fatalf("error occur: %+v", err) + } + defer os.Setenv("DOCKER_HOST", DOCKER_HOST) + + // when + got, err := health.NewHandler() + + // then + if err == nil { + t.Error("error must not be nil") + } + + // and + if got != nil { + t.Errorf("must be nil, but got %+v", got) + } + }) + +} + +func TestHandler_ServeHTTP(t *testing.T) { + t.Run("when docker status returns no error", func(t *testing.T) { + // given + rec := httptest.NewRecorder() + req := httptest.NewRequest("GET", "/", nil) + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + docker := mock_docker.NewMockDocker(ctrl) + docker.EXPECT(). + Status(). + Return(nil) + + // and + sut := &health.Handler{} + defer sut.SetDocker(docker)() + + // when + sut.ServeHTTP(rec, req) + + // then + if rec.Code != http.StatusOK { + t.Errorf("must be %d, but got %d", http.StatusOK, rec.Code) + } + }) + + t.Run("when docker status returns error", func(t *testing.T) { + // given + rec := httptest.NewRecorder() + req := httptest.NewRequest("GET", "/", nil) + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + docker := mock_docker.NewMockDocker(ctrl) + docker.EXPECT(). + Status(). + Return(errors.New("test error")) + + // and + sut := &health.Handler{} + defer sut.SetDocker(docker)() + + // when + sut.ServeHTTP(rec, req) + + // then + if rec.Code != http.StatusInternalServerError { + t.Errorf("response code must be %d, but got %d", http.StatusInternalServerError, rec.Code) + } + }) +} diff --git a/presentation/controller/job/export_test.go b/presentation/controller/job/export_test.go new file mode 100644 index 00000000..ee5c4e74 --- /dev/null +++ b/presentation/controller/job/export_test.go @@ -0,0 +1,13 @@ +package job + +import "github.com/duck8823/duci/application/service/job" + +type Handler = handler + +func (h *Handler) SetService(service job_service.Service) (reset func()) { + tmp := h.service + h.service = service + return func() { + h.service = tmp + } +} diff --git a/presentation/controller/job/handler_test.go b/presentation/controller/job/handler_test.go new file mode 100644 index 00000000..e930fbee --- /dev/null +++ b/presentation/controller/job/handler_test.go @@ -0,0 +1,167 @@ +package job_test + +import ( + "context" + "github.com/duck8823/duci/application/service/job" + "github.com/duck8823/duci/application/service/job/mock_job" + mdlJob "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/internal/container" + "github.com/duck8823/duci/presentation/controller/job" + "github.com/go-chi/chi" + "github.com/golang/mock/gomock" + "github.com/google/go-cmp/cmp" + "github.com/google/uuid" + "github.com/pkg/errors" + "net/http" + "net/http/httptest" + "testing" + "time" +) + +func TestNewHandler(t *testing.T) { + t.Run("when there is service in container", func(t *testing.T) { + // given + service := new(job_service.Service) + + container.Override(service) + defer container.Clear() + + // and + want := &job.Handler{} + defer want.SetService(*service)() + + // when + got, err := job.NewHandler() + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + opts := cmp.Options{ + cmp.AllowUnexported(job.Handler{}), + } + if !cmp.Equal(got, want, opts) { + t.Errorf("must be equal, but %+v", cmp.Diff(got, want, opts)) + } + }) + + t.Run("when there are no service in container", func(t *testing.T) { + // given + container.Clear() + + // when + got, err := job.NewHandler() + + // then + if err == nil { + t.Error("error must not be nil") + } + + // and + if got != nil { + t.Errorf("must be nil, but got %+v", got) + } + + }) +} + +func TestHandler_ServeHTTP(t *testing.T) { + t.Run("without error", func(t *testing.T) { + // given + rec := httptest.NewRecorder() + req := httptest.NewRequest("GET", "/", nil) + + // and + id := mdlJob.ID(uuid.New()) + + routeCtx := chi.NewRouteContext() + routeCtx.URLParams.Add("uuid", uuid.UUID(id).String()) + ctx := context.WithValue(context.Background(), chi.RouteCtxKey, routeCtx) + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + service := mock_job_service.NewMockService(ctrl) + service.EXPECT(). + FindBy(gomock.Eq(id)). + Times(1). + Return(&mdlJob.Job{ + ID: id, + Finished: true, + Stream: []mdlJob.LogLine{ + {Timestamp: time.Now(), Message: "Hello Test"}, + }, + }, nil) + + // and + sut := &job.Handler{} + defer sut.SetService(service)() + + // when + sut.ServeHTTP(rec, req.WithContext(ctx)) + + // then + if rec.Code != http.StatusOK { + t.Errorf("must be %d, but got %d", http.StatusOK, rec.Code) + } + }) + + t.Run("with invalid path param", func(t *testing.T) { + // given + rec := httptest.NewRecorder() + + routeCtx := chi.NewRouteContext() + routeCtx.URLParams.Add("uuid", "") + ctx := context.WithValue(context.Background(), chi.RouteCtxKey, routeCtx) + req := httptest.NewRequest("GET", "/", nil).WithContext(ctx) + + // and + sut := &job.Handler{} + + // when + sut.ServeHTTP(rec, req) + + // then + if rec.Code != http.StatusInternalServerError { + t.Errorf("must be %d, but got %d", http.StatusInternalServerError, rec.Code) + } + }) + + t.Run("when service returns error", func(t *testing.T) { + // given + rec := httptest.NewRecorder() + req := httptest.NewRequest("GET", "/", nil) + + // and + id := mdlJob.ID(uuid.New()) + + routeCtx := chi.NewRouteContext() + routeCtx.URLParams.Add("uuid", uuid.UUID(id).String()) + ctx := context.WithValue(context.Background(), chi.RouteCtxKey, routeCtx) + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + service := mock_job_service.NewMockService(ctrl) + service.EXPECT(). + FindBy(gomock.Eq(id)). + Times(1). + Return(nil, errors.New("test error")) + + // and + sut := &job.Handler{} + defer sut.SetService(service)() + + // when + sut.ServeHTTP(rec, req.WithContext(ctx)) + + // then + if rec.Code != http.StatusInternalServerError { + t.Errorf("response code must be %d, but got %d", http.StatusInternalServerError, rec.Code) + } + }) +} diff --git a/presentation/controller/webhook/export_test.go b/presentation/controller/webhook/export_test.go new file mode 100644 index 00000000..3b7f1b41 --- /dev/null +++ b/presentation/controller/webhook/export_test.go @@ -0,0 +1,15 @@ +package webhook + +import ( + "github.com/duck8823/duci/application/service/executor" +) + +type Handler = handler + +func (h *Handler) SetExecutor(executor executor.Executor) (reset func()) { + tmp := h.executor + h.executor = executor + return func() { + h.executor = tmp + } +} diff --git a/presentation/controller/webhook/handler_test.go b/presentation/controller/webhook/handler_test.go new file mode 100644 index 00000000..7561546b --- /dev/null +++ b/presentation/controller/webhook/handler_test.go @@ -0,0 +1,114 @@ +package webhook_test + +import ( + "context" + "github.com/duck8823/duci/application/service/executor/mock_executor" + "github.com/duck8823/duci/application/service/job" + "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/job/target/github" + "github.com/duck8823/duci/internal/container" + "github.com/duck8823/duci/presentation/controller/webhook" + "github.com/golang/mock/gomock" + "net/http" + "net/http/httptest" + "os" + "testing" +) + +func TestNewHandler(t *testing.T) { + t.Run("when there are job service and github in container", func(t *testing.T) { + // given + container.Override(new(job_service.Service)) + container.Override(new(github.GitHub)) + defer container.Clear() + + // when + _, err := webhook.NewHandler() + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + }) + + t.Run("when there are not enough instance in container", func(t *testing.T) { + // where + for _, tt := range []struct { + name string + given func() + }{ + { + name: "without job service", + given: func() { + container.Override(new(github.GitHub)) + }, + }, + { + name: "without github", + given: func() { + container.Override(new(job_service.Service)) + }, + }, + } { + t.Run(tt.name, func(t *testing.T) { + // given + container.Clear() + tt.given() + + // when + _, err := webhook.NewHandler() + + // then + if err == nil { + t.Error("error must not be nil") + } + + // cleanup + container.Clear() + }) + } + }) +} + +func TestHandler_PushEvent(t *testing.T) { + // given + rec := httptest.NewRecorder() + req := httptest.NewRequest("GET", "/", nil) + + // and + req.Header = http.Header{ + "X-Github-Delivery": []string{"72d3162e-cc78-11e3-81ab-4c9367dc0958"}, + } + + // and + f, err := os.Open("testdata/push.correct.json") + if err != nil { + t.Fatalf("error occur: %+v", err) + } + req.Body = f + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + executor := mock_executor.NewMockExecutor(ctrl) + executor.EXPECT(). + Execute(gomock.Any(), gomock.Any()). + Times(1). + Do(func(ctx context.Context, target job.Target) { + // TODO: check argument + }). + Return(nil) + + // and + sut := &webhook.Handler{} + defer sut.SetExecutor(executor)() + + // when + sut.PushEvent(rec, req) + + // then + if rec.Code != http.StatusOK { + t.Errorf("response code must be %d, but got %d", http.StatusOK, rec.Code) + } +} diff --git a/presentation/controller/webhook/testdata/push.correct.json b/presentation/controller/webhook/testdata/push.correct.json new file mode 100644 index 00000000..0d987d18 --- /dev/null +++ b/presentation/controller/webhook/testdata/push.correct.json @@ -0,0 +1,135 @@ +{ + "ref": "refs/tags/simple-tag", + "before": "a10867b14bb761a232cd80139fbd4c0d33264240", + "after": "0000000000000000000000000000000000000000", + "created": false, + "deleted": true, + "forced": false, + "base_ref": null, + "compare": "https://github.com/Codertocat/Hello-World/compare/a10867b14bb7...000000000000", + "commits": [ + + ], + "head_commit": null, + "repository": { + "id": 135493233, + "node_id": "MDEwOlJlcG9zaXRvcnkxMzU0OTMyMzM=", + "name": "Hello-World", + "full_name": "Codertocat/Hello-World", + "owner": { + "name": "Codertocat", + "email": "21031067+Codertocat@users.noreply.github.com", + "login": "Codertocat", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Codertocat", + "html_url": "https://github.com/Codertocat", + "followers_url": "https://api.github.com/users/Codertocat/followers", + "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", + "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", + "organizations_url": "https://api.github.com/users/Codertocat/orgs", + "repos_url": "https://api.github.com/users/Codertocat/repos", + "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/Codertocat/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/Codertocat/Hello-World", + "description": null, + "fork": false, + "url": "https://github.com/Codertocat/Hello-World", + "forks_url": "https://api.github.com/repos/Codertocat/Hello-World/forks", + "keys_url": "https://api.github.com/repos/Codertocat/Hello-World/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Codertocat/Hello-World/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Codertocat/Hello-World/teams", + "hooks_url": "https://api.github.com/repos/Codertocat/Hello-World/hooks", + "issue_events_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/events{/number}", + "events_url": "https://api.github.com/repos/Codertocat/Hello-World/events", + "assignees_url": "https://api.github.com/repos/Codertocat/Hello-World/assignees{/user}", + "branches_url": "https://api.github.com/repos/Codertocat/Hello-World/branches{/branch}", + "tags_url": "https://api.github.com/repos/Codertocat/Hello-World/tags", + "blobs_url": "https://api.github.com/repos/Codertocat/Hello-World/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Codertocat/Hello-World/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Codertocat/Hello-World/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Codertocat/Hello-World/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Codertocat/Hello-World/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Codertocat/Hello-World/languages", + "stargazers_url": "https://api.github.com/repos/Codertocat/Hello-World/stargazers", + "contributors_url": "https://api.github.com/repos/Codertocat/Hello-World/contributors", + "subscribers_url": "https://api.github.com/repos/Codertocat/Hello-World/subscribers", + "subscription_url": "https://api.github.com/repos/Codertocat/Hello-World/subscription", + "commits_url": "https://api.github.com/repos/Codertocat/Hello-World/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Codertocat/Hello-World/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Codertocat/Hello-World/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Codertocat/Hello-World/contents/{+path}", + "compare_url": "https://api.github.com/repos/Codertocat/Hello-World/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Codertocat/Hello-World/merges", + "archive_url": "https://api.github.com/repos/Codertocat/Hello-World/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Codertocat/Hello-World/downloads", + "issues_url": "https://api.github.com/repos/Codertocat/Hello-World/issues{/number}", + "pulls_url": "https://api.github.com/repos/Codertocat/Hello-World/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Codertocat/Hello-World/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Codertocat/Hello-World/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Codertocat/Hello-World/labels{/name}", + "releases_url": "https://api.github.com/repos/Codertocat/Hello-World/releases{/id}", + "deployments_url": "https://api.github.com/repos/Codertocat/Hello-World/deployments", + "created_at": 1527711484, + "updated_at": "2018-05-30T20:18:35Z", + "pushed_at": 1527711528, + "git_url": "git://github.com/Codertocat/Hello-World.git", + "ssh_url": "git@github.com:Codertocat/Hello-World.git", + "clone_url": "https://github.com/Codertocat/Hello-World.git", + "svn_url": "https://github.com/Codertocat/Hello-World", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "open_issues_count": 2, + "license": null, + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "master", + "stargazers": 0, + "master_branch": "master" + }, + "pusher": { + "name": "Codertocat", + "email": "21031067+Codertocat@users.noreply.github.com" + }, + "sender": { + "login": "Codertocat", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Codertocat", + "html_url": "https://github.com/Codertocat", + "followers_url": "https://api.github.com/users/Codertocat/followers", + "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", + "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", + "organizations_url": "https://api.github.com/users/Codertocat/orgs", + "repos_url": "https://api.github.com/users/Codertocat/repos", + "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/Codertocat/received_events", + "type": "User", + "site_admin": false + } +} \ No newline at end of file From a5b8c817bbb1a82a59dbf4279afdbd795356457d Mon Sep 17 00:00:00 2001 From: duck8823 Date: Thu, 3 Jan 2019 11:36:44 +0900 Subject: [PATCH 091/135] Add assertion --- .../controller/webhook/export_test.go | 35 +++++++++++++++++ .../controller/webhook/handler_test.go | 38 ++++++++++++++++++- 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/presentation/controller/webhook/export_test.go b/presentation/controller/webhook/export_test.go index 3b7f1b41..486236a2 100644 --- a/presentation/controller/webhook/export_test.go +++ b/presentation/controller/webhook/export_test.go @@ -2,6 +2,10 @@ package webhook import ( "github.com/duck8823/duci/application/service/executor" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "net/url" + "reflect" ) type Handler = handler @@ -13,3 +17,34 @@ func (h *Handler) SetExecutor(executor executor.Executor) (reset func()) { h.executor = tmp } } + +func URLMust(url *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + return url +} + +func CmpOptsAllowFields(typ interface{}, names ...string) cmp.Option { + return cmpopts.IgnoreFields(typ, func() []string { + var ignoreFields []string + + t := reflect.TypeOf(typ) + for i := 0; i < t.NumField(); i++ { + name := t.Field(i).Name + if !contains(names, name) { + ignoreFields = append(ignoreFields, name) + } + } + return ignoreFields + }()...) +} + +func contains(s []string, e string) bool { + for _, v := range s { + if v == e { + return true + } + } + return false +} diff --git a/presentation/controller/webhook/handler_test.go b/presentation/controller/webhook/handler_test.go index 7561546b..24bbcd97 100644 --- a/presentation/controller/webhook/handler_test.go +++ b/presentation/controller/webhook/handler_test.go @@ -2,6 +2,7 @@ package webhook_test import ( "context" + "github.com/duck8823/duci/application" "github.com/duck8823/duci/application/service/executor/mock_executor" "github.com/duck8823/duci/application/service/job" "github.com/duck8823/duci/domain/model/job" @@ -9,9 +10,15 @@ import ( "github.com/duck8823/duci/internal/container" "github.com/duck8823/duci/presentation/controller/webhook" "github.com/golang/mock/gomock" + "github.com/google/go-cmp/cmp" + go_github "github.com/google/go-github/github" + "github.com/google/uuid" + "gopkg.in/src-d/go-git.v4/plumbing" "net/http" "net/http/httptest" + "net/url" "os" + "reflect" "testing" ) @@ -96,7 +103,36 @@ func TestHandler_PushEvent(t *testing.T) { Execute(gomock.Any(), gomock.Any()). Times(1). Do(func(ctx context.Context, target job.Target) { - // TODO: check argument + got, err := application.BuildJobFromContext(ctx) + if err != nil { + t.Errorf("must not be nil, but got %+v", err) + } + + want := &application.BuildJob{ + ID: job.ID(uuid.Must(uuid.Parse("72d3162e-cc78-11e3-81ab-4c9367dc0958"))), + TargetSource: &github.TargetSource{ + Repository: &go_github.PushEventRepository{ + ID: go_github.Int64(135493233), + FullName: go_github.String("Codertocat/Hello-World"), + SSHURL: go_github.String("git@github.com:Codertocat/Hello-World.git"), + CloneURL: go_github.String("https://github.com/Codertocat/Hello-World.git"), + }, + Ref: "refs/tags/simple-tag", + SHA: plumbing.ZeroHash, + }, + TaskName: "duci/push", + TargetURL: webhook.URLMust(url.Parse("http://example.com/")), + } + + opt := webhook.CmpOptsAllowFields(go_github.PushEventRepository{}, "ID", "FullName", "SSHURL", "CloneURL") + if !cmp.Equal(got, want, opt) { + t.Errorf("must be equal but: %+v", cmp.Diff(got, want, opt)) + } + + typ := reflect.TypeOf(target).String() + if typ != "*target.GitHub" { + t.Errorf("type must be *target.GitHub, but got %s", typ) + } }). Return(nil) From f34955bbf42a7d5b38c1e8b8203f84be4af85cbf Mon Sep 17 00:00:00 2001 From: duck8823 Date: Thu, 3 Jan 2019 11:51:17 +0900 Subject: [PATCH 092/135] Change to execute job in goroutine --- presentation/controller/webhook/handler.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/presentation/controller/webhook/handler.go b/presentation/controller/webhook/handler.go index a762004e..8f3ade36 100644 --- a/presentation/controller/webhook/handler.go +++ b/presentation/controller/webhook/handler.go @@ -77,10 +77,7 @@ func (h *handler) PushEvent(w http.ResponseWriter, r *http.Request) { Point: event, } - if err := h.executor.Execute(ctx, tgt); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } + go h.executor.Execute(ctx, tgt) w.WriteHeader(http.StatusOK) } From 2a69e4a0a65c3566df70f1cd7100d11bfdbed9ac Mon Sep 17 00:00:00 2001 From: duck8823 Date: Thu, 3 Jan 2019 11:51:59 +0900 Subject: [PATCH 093/135] Add test pattern --- .../controller/webhook/handler_test.go | 216 ++++++++++++------ 1 file changed, 148 insertions(+), 68 deletions(-) diff --git a/presentation/controller/webhook/handler_test.go b/presentation/controller/webhook/handler_test.go index 24bbcd97..5b56060e 100644 --- a/presentation/controller/webhook/handler_test.go +++ b/presentation/controller/webhook/handler_test.go @@ -2,6 +2,7 @@ package webhook_test import ( "context" + "github.com/docker/docker/pkg/ioutils" "github.com/duck8823/duci/application" "github.com/duck8823/duci/application/service/executor/mock_executor" "github.com/duck8823/duci/application/service/job" @@ -19,6 +20,7 @@ import ( "net/url" "os" "reflect" + "strings" "testing" ) @@ -78,73 +80,151 @@ func TestNewHandler(t *testing.T) { } func TestHandler_PushEvent(t *testing.T) { - // given - rec := httptest.NewRecorder() - req := httptest.NewRequest("GET", "/", nil) - - // and - req.Header = http.Header{ - "X-Github-Delivery": []string{"72d3162e-cc78-11e3-81ab-4c9367dc0958"}, - } - - // and - f, err := os.Open("testdata/push.correct.json") - if err != nil { - t.Fatalf("error occur: %+v", err) - } - req.Body = f - - // and - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - executor := mock_executor.NewMockExecutor(ctrl) - executor.EXPECT(). - Execute(gomock.Any(), gomock.Any()). - Times(1). - Do(func(ctx context.Context, target job.Target) { - got, err := application.BuildJobFromContext(ctx) - if err != nil { - t.Errorf("must not be nil, but got %+v", err) - } - - want := &application.BuildJob{ - ID: job.ID(uuid.Must(uuid.Parse("72d3162e-cc78-11e3-81ab-4c9367dc0958"))), - TargetSource: &github.TargetSource{ - Repository: &go_github.PushEventRepository{ - ID: go_github.Int64(135493233), - FullName: go_github.String("Codertocat/Hello-World"), - SSHURL: go_github.String("git@github.com:Codertocat/Hello-World.git"), - CloneURL: go_github.String("https://github.com/Codertocat/Hello-World.git"), + t.Run("with no error", func(t *testing.T) { + // given + rec := httptest.NewRecorder() + req := httptest.NewRequest("GET", "/", nil) + + // and + req.Header = http.Header{ + "X-Github-Delivery": []string{"72d3162e-cc78-11e3-81ab-4c9367dc0958"}, + } + + // and + f, err := os.Open("testdata/push.correct.json") + if err != nil { + t.Fatalf("error occur: %+v", err) + } + req.Body = f + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + executor := mock_executor.NewMockExecutor(ctrl) + executor.EXPECT(). + Execute(gomock.Any(), gomock.Any()). + Times(1). + Do(func(ctx context.Context, target job.Target) { + got, err := application.BuildJobFromContext(ctx) + if err != nil { + t.Errorf("must not be nil, but got %+v", err) + } + + want := &application.BuildJob{ + ID: job.ID(uuid.Must(uuid.Parse("72d3162e-cc78-11e3-81ab-4c9367dc0958"))), + TargetSource: &github.TargetSource{ + Repository: &go_github.PushEventRepository{ + ID: go_github.Int64(135493233), + FullName: go_github.String("Codertocat/Hello-World"), + SSHURL: go_github.String("git@github.com:Codertocat/Hello-World.git"), + CloneURL: go_github.String("https://github.com/Codertocat/Hello-World.git"), + }, + Ref: "refs/tags/simple-tag", + SHA: plumbing.ZeroHash, }, - Ref: "refs/tags/simple-tag", - SHA: plumbing.ZeroHash, - }, - TaskName: "duci/push", - TargetURL: webhook.URLMust(url.Parse("http://example.com/")), - } - - opt := webhook.CmpOptsAllowFields(go_github.PushEventRepository{}, "ID", "FullName", "SSHURL", "CloneURL") - if !cmp.Equal(got, want, opt) { - t.Errorf("must be equal but: %+v", cmp.Diff(got, want, opt)) - } - - typ := reflect.TypeOf(target).String() - if typ != "*target.GitHub" { - t.Errorf("type must be *target.GitHub, but got %s", typ) - } - }). - Return(nil) - - // and - sut := &webhook.Handler{} - defer sut.SetExecutor(executor)() - - // when - sut.PushEvent(rec, req) - - // then - if rec.Code != http.StatusOK { - t.Errorf("response code must be %d, but got %d", http.StatusOK, rec.Code) - } + TaskName: "duci/push", + TargetURL: webhook.URLMust(url.Parse("http://example.com/")), + } + + opt := webhook.CmpOptsAllowFields(go_github.PushEventRepository{}, "ID", "FullName", "SSHURL", "CloneURL") + if !cmp.Equal(got, want, opt) { + t.Errorf("must be equal but: %+v", cmp.Diff(got, want, opt)) + } + + typ := reflect.TypeOf(target).String() + if typ != "*target.GitHub" { + t.Errorf("type must be *target.GitHub, but got %s", typ) + } + }). + Return(nil) + + // and + sut := &webhook.Handler{} + defer sut.SetExecutor(executor)() + + // when + sut.PushEvent(rec, req) + + // then + if rec.Code != http.StatusOK { + t.Errorf("response code must be %d, but got %d", http.StatusOK, rec.Code) + } + }) + + t.Run("when url param is invalid format uuid", func(t *testing.T) { + // given + rec := httptest.NewRecorder() + req := httptest.NewRequest("GET", "/", nil) + + // and + req.Header = http.Header{ + "X-Github-Delivery": []string{"invalid format"}, + } + + // and + f, err := os.Open("testdata/push.correct.json") + if err != nil { + t.Fatalf("error occur: %+v", err) + } + req.Body = f + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + executor := mock_executor.NewMockExecutor(ctrl) + executor.EXPECT(). + Execute(gomock.Any(), gomock.Any()). + Times(0) + + // and + sut := &webhook.Handler{} + defer sut.SetExecutor(executor)() + + // when + sut.PushEvent(rec, req) + + // then + if rec.Code != http.StatusBadRequest { + t.Errorf("response code must be %d, but got %d", http.StatusBadRequest, rec.Code) + } + }) + + t.Run("when url param is invalid format uuid", func(t *testing.T) { + // given + rec := httptest.NewRecorder() + req := httptest.NewRequest("GET", "/", nil) + + // and + req.Header = http.Header{ + "X-Github-Delivery": []string{"72d3162e-cc78-11e3-81ab-4c9367dc0958"}, + } + + // and + req.Body = ioutils.NewReadCloserWrapper(strings.NewReader("invalid payload"), func() error { + return nil + }) + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + executor := mock_executor.NewMockExecutor(ctrl) + executor.EXPECT(). + Execute(gomock.Any(), gomock.Any()). + Times(0) + + // and + sut := &webhook.Handler{} + defer sut.SetExecutor(executor)() + + // when + sut.PushEvent(rec, req) + + // then + if rec.Code != http.StatusInternalServerError { + t.Errorf("response code must be %d, but got %d", http.StatusInternalServerError, rec.Code) + } + }) } From b40a82c947eb91443bd83bc08936cb942932fdae Mon Sep 17 00:00:00 2001 From: duck8823 Date: Thu, 3 Jan 2019 12:09:03 +0900 Subject: [PATCH 094/135] Fix missing call func goroutine --- presentation/controller/webhook/handler_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/presentation/controller/webhook/handler_test.go b/presentation/controller/webhook/handler_test.go index 5b56060e..a56173e8 100644 --- a/presentation/controller/webhook/handler_test.go +++ b/presentation/controller/webhook/handler_test.go @@ -22,6 +22,7 @@ import ( "reflect" "strings" "testing" + "time" ) func TestNewHandler(t *testing.T) { @@ -99,7 +100,10 @@ func TestHandler_PushEvent(t *testing.T) { // and ctrl := gomock.NewController(t) - defer ctrl.Finish() + defer func() { + time.Sleep(10 * time.Millisecond) // for goroutine + ctrl.Finish() + }() executor := mock_executor.NewMockExecutor(ctrl) executor.EXPECT(). From c60d366ed73f9b7a9a27ab83588d1ac755a36bbc Mon Sep 17 00:00:00 2001 From: duck8823 Date: Thu, 3 Jan 2019 18:15:23 +0900 Subject: [PATCH 095/135] Update gomock --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 7d9fd897..39e2bcc3 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/go-chi/chi v3.3.3+incompatible github.com/gogo/protobuf v1.1.1 // indirect github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect - github.com/golang/mock v1.1.1 + github.com/golang/mock v1.2.0 github.com/golang/protobuf v1.1.0 // indirect github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect github.com/google/go-cmp v0.2.0 From d4acd46076fe42db24c36fdd779db00c5d1e7bcc Mon Sep 17 00:00:00 2001 From: duck8823 Date: Thu, 3 Jan 2019 19:02:27 +0900 Subject: [PATCH 096/135] Add test cases --- .../controller/webhook/handler_test.go | 296 +++++++++++++++++- .../testdata/issue_comment.correct.json | 202 ++++++++++++ .../testdata/issue_comment.deleted.json | 202 ++++++++++++ .../testdata/issue_comment.skip_comment.json | 202 ++++++++++++ 4 files changed, 901 insertions(+), 1 deletion(-) create mode 100644 presentation/controller/webhook/testdata/issue_comment.correct.json create mode 100644 presentation/controller/webhook/testdata/issue_comment.deleted.json create mode 100644 presentation/controller/webhook/testdata/issue_comment.skip_comment.json diff --git a/presentation/controller/webhook/handler_test.go b/presentation/controller/webhook/handler_test.go index a56173e8..529e2d26 100644 --- a/presentation/controller/webhook/handler_test.go +++ b/presentation/controller/webhook/handler_test.go @@ -14,6 +14,7 @@ import ( "github.com/google/go-cmp/cmp" go_github "github.com/google/go-github/github" "github.com/google/uuid" + "gopkg.in/h2non/gock.v1" "gopkg.in/src-d/go-git.v4/plumbing" "net/http" "net/http/httptest" @@ -195,7 +196,7 @@ func TestHandler_PushEvent(t *testing.T) { } }) - t.Run("when url param is invalid format uuid", func(t *testing.T) { + t.Run("with invalid payload", func(t *testing.T) { // given rec := httptest.NewRecorder() req := httptest.NewRequest("GET", "/", nil) @@ -232,3 +233,296 @@ func TestHandler_PushEvent(t *testing.T) { } }) } + +func TestHandler_IssueCommentEvent(t *testing.T) { + t.Run("with no error", func(t *testing.T) { + // given + rec := httptest.NewRecorder() + req := httptest.NewRequest("GET", "/", nil) + + // and + req.Header = http.Header{ + "X-Github-Delivery": []string{"72d3162e-cc78-11e3-81ab-4c9367dc0958"}, + } + + // and + f, err := os.Open("testdata/issue_comment.correct.json") + if err != nil { + t.Fatalf("error occur: %+v", err) + } + req.Body = f + + // and + if err := github.Initialize(""); err != nil { + t.Fatalf("error occur: %+v", err) + } + defer container.Clear() + + gock.New("https://api.github.com"). + Get("/repos/Codertocat/Hello-World/pulls/2"). + Reply(200). + JSON(&go_github.PullRequest{ + Head: &go_github.PullRequestBranch{ + Ref: go_github.String("refs/test/dummy"), + SHA: go_github.String("aa218f56b14c9653891f9e74264a383fa43fefbd"), + }, + }) + defer func() { + if !gock.IsDone() { + t.Errorf("must request pulls") + } + gock.Clean() + }() + + // and + ctrl := gomock.NewController(t) + defer func() { + time.Sleep(10 * time.Millisecond) // for goroutine + ctrl.Finish() + }() + + executor := mock_executor.NewMockExecutor(ctrl) + executor.EXPECT(). + Execute(gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Do(func(ctx context.Context, target job.Target, cmd ...string) { + got, err := application.BuildJobFromContext(ctx) + if err != nil { + t.Errorf("must not be nil, but got %+v", err) + } + + want := &application.BuildJob{ + ID: job.ID(uuid.Must(uuid.Parse("72d3162e-cc78-11e3-81ab-4c9367dc0958"))), + TargetSource: &github.TargetSource{ + Repository: &go_github.Repository{ + ID: go_github.Int64(135493233), + FullName: go_github.String("Codertocat/Hello-World"), + SSHURL: go_github.String("git@github.com:Codertocat/Hello-World.git"), + CloneURL: go_github.String("https://github.com/Codertocat/Hello-World.git"), + }, + Ref: "refs/test/dummy", + SHA: plumbing.NewHash("aa218f56b14c9653891f9e74264a383fa43fefbd"), + }, + TaskName: "duci/pr/build", + TargetURL: webhook.URLMust(url.Parse("http://example.com/")), + } + + opt := webhook.CmpOptsAllowFields(go_github.Repository{}, "ID", "FullName", "SSHURL", "CloneURL") + if !cmp.Equal(got, want, opt) { + t.Errorf("must be equal but: %+v", cmp.Diff(got, want, opt)) + } + + typ := reflect.TypeOf(target).String() + if typ != "*target.GitHub" { + t.Errorf("type must be *target.GitHub, but got %s", typ) + } + }). + Return(nil) + + // and + sut := &webhook.Handler{} + defer sut.SetExecutor(executor)() + + // when + sut.IssueCommentEvent(rec, req) + + // then + if rec.Code != http.StatusOK { + t.Errorf("response code must be %d, but got %d", http.StatusOK, rec.Code) + } + }) + + t.Run("when action is deleted", func(t *testing.T) { + // given + rec := httptest.NewRecorder() + req := httptest.NewRequest("GET", "/", nil) + + // and + req.Header = http.Header{ + "X-Github-Delivery": []string{"72d3162e-cc78-11e3-81ab-4c9367dc0958"}, + } + + // and + f, err := os.Open("testdata/issue_comment.deleted.json") + if err != nil { + t.Fatalf("error occur: %+v", err) + } + req.Body = f + + // and + ctrl := gomock.NewController(t) + defer func() { + time.Sleep(10 * time.Millisecond) // for goroutine + ctrl.Finish() + }() + + executor := mock_executor.NewMockExecutor(ctrl) + executor.EXPECT(). + Execute(gomock.Any(), gomock.Any(), gomock.Any()). + Times(0) + + // and + sut := &webhook.Handler{} + defer sut.SetExecutor(executor)() + + // when + sut.IssueCommentEvent(rec, req) + + // then + if rec.Code != http.StatusOK { + t.Errorf("response code must be %d, but got %d", http.StatusOK, rec.Code) + } + + // and + got := rec.Body.String() + if got != `{"message":"skip build"}` { + t.Errorf("must be equal. want %s, but got %s", `{"message":"skip build"}`, got) + } + }) + + t.Run("with invalid payload body", func(t *testing.T) { + // given + rec := httptest.NewRecorder() + req := httptest.NewRequest("GET", "/", nil) + + // and + req.Header = http.Header{ + "X-Github-Delivery": []string{"72d3162e-cc78-11e3-81ab-4c9367dc0958"}, + } + + // and + req.Body = ioutils.NewReadCloserWrapper(strings.NewReader("invalid payload"), func() error { + return nil + }) + + // and + ctrl := gomock.NewController(t) + defer func() { + time.Sleep(10 * time.Millisecond) // for goroutine + ctrl.Finish() + }() + + executor := mock_executor.NewMockExecutor(ctrl) + executor.EXPECT(). + Execute(gomock.Any(), gomock.Any(), gomock.Any()). + Times(0) + + // and + sut := &webhook.Handler{} + defer sut.SetExecutor(executor)() + + // when + sut.IssueCommentEvent(rec, req) + + // then + if rec.Code != http.StatusInternalServerError { + t.Errorf("response code must be %d, but got %d", http.StatusInternalServerError, rec.Code) + } + }) + + t.Run("when url param is invalid format uuid", func(t *testing.T) { + // given + rec := httptest.NewRecorder() + req := httptest.NewRequest("GET", "/", nil) + + // and + req.Header = http.Header{ + "X-Github-Delivery": []string{"invalid format"}, + } + + // and + f, err := os.Open("testdata/issue_comment.correct.json") + if err != nil { + t.Fatalf("error occur: %+v", err) + } + req.Body = f + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + executor := mock_executor.NewMockExecutor(ctrl) + executor.EXPECT(). + Execute(gomock.Any(), gomock.Any()). + Times(0) + + // and + sut := &webhook.Handler{} + defer sut.SetExecutor(executor)() + + // when + sut.IssueCommentEvent(rec, req) + + // then + if rec.Code != http.StatusBadRequest { + t.Errorf("response code must be %d, but got %d", http.StatusBadRequest, rec.Code) + } + }) + + t.Run("when url param is invalid format uuid", func(t *testing.T) { + // given + rec := httptest.NewRecorder() + req := httptest.NewRequest("GET", "/", nil) + + // and + req.Header = http.Header{ + "X-Github-Delivery": []string{"72d3162e-cc78-11e3-81ab-4c9367dc0958"}, + } + + // and + f, err := os.Open("testdata/issue_comment.skip_comment.json") + if err != nil { + t.Fatalf("error occur: %+v", err) + } + req.Body = f + + // and + if err := github.Initialize(""); err != nil { + t.Fatalf("error occur: %+v", err) + } + defer container.Clear() + + gock.New("https://api.github.com"). + Get("/repos/Codertocat/Hello-World/pulls/2"). + Reply(200). + JSON(&go_github.PullRequest{ + Head: &go_github.PullRequestBranch{ + Ref: go_github.String("refs/test/dummy"), + SHA: go_github.String("aa218f56b14c9653891f9e74264a383fa43fefbd"), + }, + }) + defer func() { + if !gock.IsDone() { + t.Errorf("must request pulls") + } + gock.Clean() + }() + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + executor := mock_executor.NewMockExecutor(ctrl) + executor.EXPECT(). + Execute(gomock.Any(), gomock.Any()). + Times(0) + + // and + sut := &webhook.Handler{} + defer sut.SetExecutor(executor)() + + // when + sut.IssueCommentEvent(rec, req) + + // then + if rec.Code != http.StatusOK { + t.Errorf("response code must be %d, but got %d", http.StatusOK, rec.Code) + } + + // and + got := rec.Body.String() + if got != `{"message":"skip build"}` { + t.Errorf("must be equal. want %s, but got %s", `{"message":"skip build"}`, got) + } + }) +} diff --git a/presentation/controller/webhook/testdata/issue_comment.correct.json b/presentation/controller/webhook/testdata/issue_comment.correct.json new file mode 100644 index 00000000..d281fa45 --- /dev/null +++ b/presentation/controller/webhook/testdata/issue_comment.correct.json @@ -0,0 +1,202 @@ +{ + "action": "created", + "issue": { + "url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2", + "repository_url": "https://api.github.com/repos/Codertocat/Hello-World", + "labels_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2/labels{/name}", + "comments_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2/comments", + "events_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2/events", + "html_url": "https://github.com/Codertocat/Hello-World/issues/2", + "id": 327883527, + "node_id": "MDU6SXNzdWUzMjc4ODM1Mjc=", + "number": 2, + "title": "Spelling error in the README file", + "user": { + "login": "Codertocat", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Codertocat", + "html_url": "https://github.com/Codertocat", + "followers_url": "https://api.github.com/users/Codertocat/followers", + "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", + "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", + "organizations_url": "https://api.github.com/users/Codertocat/orgs", + "repos_url": "https://api.github.com/users/Codertocat/repos", + "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/Codertocat/received_events", + "type": "User", + "site_admin": false + }, + "labels": [ + { + "id": 949737505, + "node_id": "MDU6TGFiZWw5NDk3Mzc1MDU=", + "url": "https://api.github.com/repos/Codertocat/Hello-World/labels/bug", + "name": "bug", + "color": "d73a4a", + "default": true + } + ], + "state": "open", + "locked": false, + "assignee": null, + "assignees": [ + + ], + "milestone": null, + "comments": 0, + "created_at": "2018-05-30T20:18:32Z", + "updated_at": "2018-05-30T20:18:32Z", + "closed_at": null, + "author_association": "OWNER", + "body": "It looks like you accidently spelled 'commit' with two 't's." + }, + "comment": { + "url": "https://api.github.com/repos/Codertocat/Hello-World/issues/comments/393304133", + "html_url": "https://github.com/Codertocat/Hello-World/issues/2#issuecomment-393304133", + "issue_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2", + "id": 393304133, + "node_id": "MDEyOklzc3VlQ29tbWVudDM5MzMwNDEzMw==", + "user": { + "login": "Codertocat", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Codertocat", + "html_url": "https://github.com/Codertocat", + "followers_url": "https://api.github.com/users/Codertocat/followers", + "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", + "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", + "organizations_url": "https://api.github.com/users/Codertocat/orgs", + "repos_url": "https://api.github.com/users/Codertocat/repos", + "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/Codertocat/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2018-05-30T20:18:32Z", + "updated_at": "2018-05-30T20:18:32Z", + "author_association": "OWNER", + "body": "ci build" + }, + "repository": { + "id": 135493233, + "node_id": "MDEwOlJlcG9zaXRvcnkxMzU0OTMyMzM=", + "name": "Hello-World", + "full_name": "Codertocat/Hello-World", + "owner": { + "login": "Codertocat", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Codertocat", + "html_url": "https://github.com/Codertocat", + "followers_url": "https://api.github.com/users/Codertocat/followers", + "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", + "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", + "organizations_url": "https://api.github.com/users/Codertocat/orgs", + "repos_url": "https://api.github.com/users/Codertocat/repos", + "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/Codertocat/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/Codertocat/Hello-World", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/Codertocat/Hello-World", + "forks_url": "https://api.github.com/repos/Codertocat/Hello-World/forks", + "keys_url": "https://api.github.com/repos/Codertocat/Hello-World/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Codertocat/Hello-World/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Codertocat/Hello-World/teams", + "hooks_url": "https://api.github.com/repos/Codertocat/Hello-World/hooks", + "issue_events_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/events{/number}", + "events_url": "https://api.github.com/repos/Codertocat/Hello-World/events", + "assignees_url": "https://api.github.com/repos/Codertocat/Hello-World/assignees{/user}", + "branches_url": "https://api.github.com/repos/Codertocat/Hello-World/branches{/branch}", + "tags_url": "https://api.github.com/repos/Codertocat/Hello-World/tags", + "blobs_url": "https://api.github.com/repos/Codertocat/Hello-World/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Codertocat/Hello-World/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Codertocat/Hello-World/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Codertocat/Hello-World/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Codertocat/Hello-World/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Codertocat/Hello-World/languages", + "stargazers_url": "https://api.github.com/repos/Codertocat/Hello-World/stargazers", + "contributors_url": "https://api.github.com/repos/Codertocat/Hello-World/contributors", + "subscribers_url": "https://api.github.com/repos/Codertocat/Hello-World/subscribers", + "subscription_url": "https://api.github.com/repos/Codertocat/Hello-World/subscription", + "commits_url": "https://api.github.com/repos/Codertocat/Hello-World/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Codertocat/Hello-World/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Codertocat/Hello-World/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Codertocat/Hello-World/contents/{+path}", + "compare_url": "https://api.github.com/repos/Codertocat/Hello-World/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Codertocat/Hello-World/merges", + "archive_url": "https://api.github.com/repos/Codertocat/Hello-World/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Codertocat/Hello-World/downloads", + "issues_url": "https://api.github.com/repos/Codertocat/Hello-World/issues{/number}", + "pulls_url": "https://api.github.com/repos/Codertocat/Hello-World/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Codertocat/Hello-World/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Codertocat/Hello-World/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Codertocat/Hello-World/labels{/name}", + "releases_url": "https://api.github.com/repos/Codertocat/Hello-World/releases{/id}", + "deployments_url": "https://api.github.com/repos/Codertocat/Hello-World/deployments", + "created_at": "2018-05-30T20:18:04Z", + "updated_at": "2018-05-30T20:18:10Z", + "pushed_at": "2018-05-30T20:18:30Z", + "git_url": "git://github.com/Codertocat/Hello-World.git", + "ssh_url": "git@github.com:Codertocat/Hello-World.git", + "clone_url": "https://github.com/Codertocat/Hello-World.git", + "svn_url": "https://github.com/Codertocat/Hello-World", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "open_issues_count": 2, + "license": null, + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "Codertocat", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Codertocat", + "html_url": "https://github.com/Codertocat", + "followers_url": "https://api.github.com/users/Codertocat/followers", + "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", + "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", + "organizations_url": "https://api.github.com/users/Codertocat/orgs", + "repos_url": "https://api.github.com/users/Codertocat/repos", + "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/Codertocat/received_events", + "type": "User", + "site_admin": false + } +} \ No newline at end of file diff --git a/presentation/controller/webhook/testdata/issue_comment.deleted.json b/presentation/controller/webhook/testdata/issue_comment.deleted.json new file mode 100644 index 00000000..078c7544 --- /dev/null +++ b/presentation/controller/webhook/testdata/issue_comment.deleted.json @@ -0,0 +1,202 @@ +{ + "action": "deleted", + "issue": { + "url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2", + "repository_url": "https://api.github.com/repos/Codertocat/Hello-World", + "labels_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2/labels{/name}", + "comments_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2/comments", + "events_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2/events", + "html_url": "https://github.com/Codertocat/Hello-World/issues/2", + "id": 327883527, + "node_id": "MDU6SXNzdWUzMjc4ODM1Mjc=", + "number": 2, + "title": "Spelling error in the README file", + "user": { + "login": "Codertocat", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Codertocat", + "html_url": "https://github.com/Codertocat", + "followers_url": "https://api.github.com/users/Codertocat/followers", + "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", + "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", + "organizations_url": "https://api.github.com/users/Codertocat/orgs", + "repos_url": "https://api.github.com/users/Codertocat/repos", + "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/Codertocat/received_events", + "type": "User", + "site_admin": false + }, + "labels": [ + { + "id": 949737505, + "node_id": "MDU6TGFiZWw5NDk3Mzc1MDU=", + "url": "https://api.github.com/repos/Codertocat/Hello-World/labels/bug", + "name": "bug", + "color": "d73a4a", + "default": true + } + ], + "state": "open", + "locked": false, + "assignee": null, + "assignees": [ + + ], + "milestone": null, + "comments": 0, + "created_at": "2018-05-30T20:18:32Z", + "updated_at": "2018-05-30T20:18:32Z", + "closed_at": null, + "author_association": "OWNER", + "body": "It looks like you accidently spelled 'commit' with two 't's." + }, + "comment": { + "url": "https://api.github.com/repos/Codertocat/Hello-World/issues/comments/393304133", + "html_url": "https://github.com/Codertocat/Hello-World/issues/2#issuecomment-393304133", + "issue_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2", + "id": 393304133, + "node_id": "MDEyOklzc3VlQ29tbWVudDM5MzMwNDEzMw==", + "user": { + "login": "Codertocat", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Codertocat", + "html_url": "https://github.com/Codertocat", + "followers_url": "https://api.github.com/users/Codertocat/followers", + "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", + "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", + "organizations_url": "https://api.github.com/users/Codertocat/orgs", + "repos_url": "https://api.github.com/users/Codertocat/repos", + "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/Codertocat/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2018-05-30T20:18:32Z", + "updated_at": "2018-05-30T20:18:32Z", + "author_association": "OWNER", + "body": "You are totally right! I'll get this fixed right away." + }, + "repository": { + "id": 135493233, + "node_id": "MDEwOlJlcG9zaXRvcnkxMzU0OTMyMzM=", + "name": "Hello-World", + "full_name": "Codertocat/Hello-World", + "owner": { + "login": "Codertocat", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Codertocat", + "html_url": "https://github.com/Codertocat", + "followers_url": "https://api.github.com/users/Codertocat/followers", + "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", + "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", + "organizations_url": "https://api.github.com/users/Codertocat/orgs", + "repos_url": "https://api.github.com/users/Codertocat/repos", + "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/Codertocat/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/Codertocat/Hello-World", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/Codertocat/Hello-World", + "forks_url": "https://api.github.com/repos/Codertocat/Hello-World/forks", + "keys_url": "https://api.github.com/repos/Codertocat/Hello-World/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Codertocat/Hello-World/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Codertocat/Hello-World/teams", + "hooks_url": "https://api.github.com/repos/Codertocat/Hello-World/hooks", + "issue_events_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/events{/number}", + "events_url": "https://api.github.com/repos/Codertocat/Hello-World/events", + "assignees_url": "https://api.github.com/repos/Codertocat/Hello-World/assignees{/user}", + "branches_url": "https://api.github.com/repos/Codertocat/Hello-World/branches{/branch}", + "tags_url": "https://api.github.com/repos/Codertocat/Hello-World/tags", + "blobs_url": "https://api.github.com/repos/Codertocat/Hello-World/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Codertocat/Hello-World/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Codertocat/Hello-World/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Codertocat/Hello-World/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Codertocat/Hello-World/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Codertocat/Hello-World/languages", + "stargazers_url": "https://api.github.com/repos/Codertocat/Hello-World/stargazers", + "contributors_url": "https://api.github.com/repos/Codertocat/Hello-World/contributors", + "subscribers_url": "https://api.github.com/repos/Codertocat/Hello-World/subscribers", + "subscription_url": "https://api.github.com/repos/Codertocat/Hello-World/subscription", + "commits_url": "https://api.github.com/repos/Codertocat/Hello-World/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Codertocat/Hello-World/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Codertocat/Hello-World/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Codertocat/Hello-World/contents/{+path}", + "compare_url": "https://api.github.com/repos/Codertocat/Hello-World/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Codertocat/Hello-World/merges", + "archive_url": "https://api.github.com/repos/Codertocat/Hello-World/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Codertocat/Hello-World/downloads", + "issues_url": "https://api.github.com/repos/Codertocat/Hello-World/issues{/number}", + "pulls_url": "https://api.github.com/repos/Codertocat/Hello-World/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Codertocat/Hello-World/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Codertocat/Hello-World/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Codertocat/Hello-World/labels{/name}", + "releases_url": "https://api.github.com/repos/Codertocat/Hello-World/releases{/id}", + "deployments_url": "https://api.github.com/repos/Codertocat/Hello-World/deployments", + "created_at": "2018-05-30T20:18:04Z", + "updated_at": "2018-05-30T20:18:10Z", + "pushed_at": "2018-05-30T20:18:30Z", + "git_url": "git://github.com/Codertocat/Hello-World.git", + "ssh_url": "git@github.com:Codertocat/Hello-World.git", + "clone_url": "https://github.com/Codertocat/Hello-World.git", + "svn_url": "https://github.com/Codertocat/Hello-World", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "open_issues_count": 2, + "license": null, + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "Codertocat", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Codertocat", + "html_url": "https://github.com/Codertocat", + "followers_url": "https://api.github.com/users/Codertocat/followers", + "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", + "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", + "organizations_url": "https://api.github.com/users/Codertocat/orgs", + "repos_url": "https://api.github.com/users/Codertocat/repos", + "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/Codertocat/received_events", + "type": "User", + "site_admin": false + } +} \ No newline at end of file diff --git a/presentation/controller/webhook/testdata/issue_comment.skip_comment.json b/presentation/controller/webhook/testdata/issue_comment.skip_comment.json new file mode 100644 index 00000000..e486dede --- /dev/null +++ b/presentation/controller/webhook/testdata/issue_comment.skip_comment.json @@ -0,0 +1,202 @@ +{ + "action": "created", + "issue": { + "url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2", + "repository_url": "https://api.github.com/repos/Codertocat/Hello-World", + "labels_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2/labels{/name}", + "comments_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2/comments", + "events_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2/events", + "html_url": "https://github.com/Codertocat/Hello-World/issues/2", + "id": 327883527, + "node_id": "MDU6SXNzdWUzMjc4ODM1Mjc=", + "number": 2, + "title": "Spelling error in the README file", + "user": { + "login": "Codertocat", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Codertocat", + "html_url": "https://github.com/Codertocat", + "followers_url": "https://api.github.com/users/Codertocat/followers", + "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", + "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", + "organizations_url": "https://api.github.com/users/Codertocat/orgs", + "repos_url": "https://api.github.com/users/Codertocat/repos", + "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/Codertocat/received_events", + "type": "User", + "site_admin": false + }, + "labels": [ + { + "id": 949737505, + "node_id": "MDU6TGFiZWw5NDk3Mzc1MDU=", + "url": "https://api.github.com/repos/Codertocat/Hello-World/labels/bug", + "name": "bug", + "color": "d73a4a", + "default": true + } + ], + "state": "open", + "locked": false, + "assignee": null, + "assignees": [ + + ], + "milestone": null, + "comments": 0, + "created_at": "2018-05-30T20:18:32Z", + "updated_at": "2018-05-30T20:18:32Z", + "closed_at": null, + "author_association": "OWNER", + "body": "It looks like you accidently spelled 'commit' with two 't's." + }, + "comment": { + "url": "https://api.github.com/repos/Codertocat/Hello-World/issues/comments/393304133", + "html_url": "https://github.com/Codertocat/Hello-World/issues/2#issuecomment-393304133", + "issue_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2", + "id": 393304133, + "node_id": "MDEyOklzc3VlQ29tbWVudDM5MzMwNDEzMw==", + "user": { + "login": "Codertocat", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Codertocat", + "html_url": "https://github.com/Codertocat", + "followers_url": "https://api.github.com/users/Codertocat/followers", + "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", + "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", + "organizations_url": "https://api.github.com/users/Codertocat/orgs", + "repos_url": "https://api.github.com/users/Codertocat/repos", + "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/Codertocat/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2018-05-30T20:18:32Z", + "updated_at": "2018-05-30T20:18:32Z", + "author_association": "OWNER", + "body": "You are totally right! I'll get this fixed right away." + }, + "repository": { + "id": 135493233, + "node_id": "MDEwOlJlcG9zaXRvcnkxMzU0OTMyMzM=", + "name": "Hello-World", + "full_name": "Codertocat/Hello-World", + "owner": { + "login": "Codertocat", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Codertocat", + "html_url": "https://github.com/Codertocat", + "followers_url": "https://api.github.com/users/Codertocat/followers", + "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", + "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", + "organizations_url": "https://api.github.com/users/Codertocat/orgs", + "repos_url": "https://api.github.com/users/Codertocat/repos", + "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/Codertocat/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/Codertocat/Hello-World", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/Codertocat/Hello-World", + "forks_url": "https://api.github.com/repos/Codertocat/Hello-World/forks", + "keys_url": "https://api.github.com/repos/Codertocat/Hello-World/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/Codertocat/Hello-World/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/Codertocat/Hello-World/teams", + "hooks_url": "https://api.github.com/repos/Codertocat/Hello-World/hooks", + "issue_events_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/events{/number}", + "events_url": "https://api.github.com/repos/Codertocat/Hello-World/events", + "assignees_url": "https://api.github.com/repos/Codertocat/Hello-World/assignees{/user}", + "branches_url": "https://api.github.com/repos/Codertocat/Hello-World/branches{/branch}", + "tags_url": "https://api.github.com/repos/Codertocat/Hello-World/tags", + "blobs_url": "https://api.github.com/repos/Codertocat/Hello-World/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/Codertocat/Hello-World/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/Codertocat/Hello-World/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/Codertocat/Hello-World/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/Codertocat/Hello-World/statuses/{sha}", + "languages_url": "https://api.github.com/repos/Codertocat/Hello-World/languages", + "stargazers_url": "https://api.github.com/repos/Codertocat/Hello-World/stargazers", + "contributors_url": "https://api.github.com/repos/Codertocat/Hello-World/contributors", + "subscribers_url": "https://api.github.com/repos/Codertocat/Hello-World/subscribers", + "subscription_url": "https://api.github.com/repos/Codertocat/Hello-World/subscription", + "commits_url": "https://api.github.com/repos/Codertocat/Hello-World/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/Codertocat/Hello-World/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/Codertocat/Hello-World/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/Codertocat/Hello-World/contents/{+path}", + "compare_url": "https://api.github.com/repos/Codertocat/Hello-World/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/Codertocat/Hello-World/merges", + "archive_url": "https://api.github.com/repos/Codertocat/Hello-World/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/Codertocat/Hello-World/downloads", + "issues_url": "https://api.github.com/repos/Codertocat/Hello-World/issues{/number}", + "pulls_url": "https://api.github.com/repos/Codertocat/Hello-World/pulls{/number}", + "milestones_url": "https://api.github.com/repos/Codertocat/Hello-World/milestones{/number}", + "notifications_url": "https://api.github.com/repos/Codertocat/Hello-World/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/Codertocat/Hello-World/labels{/name}", + "releases_url": "https://api.github.com/repos/Codertocat/Hello-World/releases{/id}", + "deployments_url": "https://api.github.com/repos/Codertocat/Hello-World/deployments", + "created_at": "2018-05-30T20:18:04Z", + "updated_at": "2018-05-30T20:18:10Z", + "pushed_at": "2018-05-30T20:18:30Z", + "git_url": "git://github.com/Codertocat/Hello-World.git", + "ssh_url": "git@github.com:Codertocat/Hello-World.git", + "clone_url": "https://github.com/Codertocat/Hello-World.git", + "svn_url": "https://github.com/Codertocat/Hello-World", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "open_issues_count": 2, + "license": null, + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "Codertocat", + "id": 21031067, + "node_id": "MDQ6VXNlcjIxMDMxMDY3", + "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/Codertocat", + "html_url": "https://github.com/Codertocat", + "followers_url": "https://api.github.com/users/Codertocat/followers", + "following_url": "https://api.github.com/users/Codertocat/following{/other_user}", + "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions", + "organizations_url": "https://api.github.com/users/Codertocat/orgs", + "repos_url": "https://api.github.com/users/Codertocat/repos", + "events_url": "https://api.github.com/users/Codertocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/Codertocat/received_events", + "type": "User", + "site_admin": false + } +} \ No newline at end of file From 09b5d709fc10cc6f59f269c590f2754e3160fb63 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Thu, 3 Jan 2019 20:57:47 +0900 Subject: [PATCH 097/135] Using gomock instead of gock --- .../controller/webhook/handler_test.go | 156 +++++++++++++----- 1 file changed, 114 insertions(+), 42 deletions(-) diff --git a/presentation/controller/webhook/handler_test.go b/presentation/controller/webhook/handler_test.go index 529e2d26..87b6678b 100644 --- a/presentation/controller/webhook/handler_test.go +++ b/presentation/controller/webhook/handler_test.go @@ -8,13 +8,14 @@ import ( "github.com/duck8823/duci/application/service/job" "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/job/target/github" + "github.com/duck8823/duci/domain/model/job/target/github/mock_github" "github.com/duck8823/duci/internal/container" "github.com/duck8823/duci/presentation/controller/webhook" "github.com/golang/mock/gomock" "github.com/google/go-cmp/cmp" go_github "github.com/google/go-github/github" "github.com/google/uuid" - "gopkg.in/h2non/gock.v1" + "github.com/pkg/errors" "gopkg.in/src-d/go-git.v4/plumbing" "net/http" "net/http/httptest" @@ -252,28 +253,6 @@ func TestHandler_IssueCommentEvent(t *testing.T) { } req.Body = f - // and - if err := github.Initialize(""); err != nil { - t.Fatalf("error occur: %+v", err) - } - defer container.Clear() - - gock.New("https://api.github.com"). - Get("/repos/Codertocat/Hello-World/pulls/2"). - Reply(200). - JSON(&go_github.PullRequest{ - Head: &go_github.PullRequestBranch{ - Ref: go_github.String("refs/test/dummy"), - SHA: go_github.String("aa218f56b14c9653891f9e74264a383fa43fefbd"), - }, - }) - defer func() { - if !gock.IsDone() { - t.Errorf("must request pulls") - } - gock.Clean() - }() - // and ctrl := gomock.NewController(t) defer func() { @@ -281,6 +260,19 @@ func TestHandler_IssueCommentEvent(t *testing.T) { ctrl.Finish() }() + gh := mock_github.NewMockGitHub(ctrl) + gh.EXPECT(). + GetPullRequest(gomock.Any(), gomock.Any(), gomock.Eq(2)). + Times(1). + Return(&go_github.PullRequest{ + Head: &go_github.PullRequestBranch{ + Ref: go_github.String("refs/test/dummy"), + SHA: go_github.String("aa218f56b14c9653891f9e74264a383fa43fefbd"), + }, + }, nil) + container.Override(gh) + defer container.Clear() + executor := mock_executor.NewMockExecutor(ctrl) executor.EXPECT(). Execute(gomock.Any(), gomock.Any(), gomock.Any()). @@ -477,30 +469,21 @@ func TestHandler_IssueCommentEvent(t *testing.T) { req.Body = f // and - if err := github.Initialize(""); err != nil { - t.Fatalf("error occur: %+v", err) - } - defer container.Clear() + ctrl := gomock.NewController(t) + defer ctrl.Finish() - gock.New("https://api.github.com"). - Get("/repos/Codertocat/Hello-World/pulls/2"). - Reply(200). - JSON(&go_github.PullRequest{ + gh := mock_github.NewMockGitHub(ctrl) + gh.EXPECT(). + GetPullRequest(gomock.Any(), gomock.Any(), gomock.Eq(2)). + Times(1). + Return(&go_github.PullRequest{ Head: &go_github.PullRequestBranch{ Ref: go_github.String("refs/test/dummy"), SHA: go_github.String("aa218f56b14c9653891f9e74264a383fa43fefbd"), }, - }) - defer func() { - if !gock.IsDone() { - t.Errorf("must request pulls") - } - gock.Clean() - }() - - // and - ctrl := gomock.NewController(t) - defer ctrl.Finish() + }, nil) + container.Override(gh) + defer container.Clear() executor := mock_executor.NewMockExecutor(ctrl) executor.EXPECT(). @@ -525,4 +508,93 @@ func TestHandler_IssueCommentEvent(t *testing.T) { t.Errorf("must be equal. want %s, but got %s", `{"message":"skip build"}`, got) } }) + + t.Run("when fail to get pull request", func(t *testing.T) { + // given + rec := httptest.NewRecorder() + req := httptest.NewRequest("GET", "/", nil) + + // and + req.Header = http.Header{ + "X-Github-Delivery": []string{"72d3162e-cc78-11e3-81ab-4c9367dc0958"}, + } + + // and + f, err := os.Open("testdata/issue_comment.skip_comment.json") + if err != nil { + t.Fatalf("error occur: %+v", err) + } + req.Body = f + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + gh := mock_github.NewMockGitHub(ctrl) + gh.EXPECT(). + GetPullRequest(gomock.Any(), gomock.Any(), gomock.Eq(2)). + Times(1). + Return(nil, errors.New("test error")) + container.Override(gh) + defer container.Clear() + + executor := mock_executor.NewMockExecutor(ctrl) + executor.EXPECT(). + Execute(gomock.Any(), gomock.Any()). + Times(0) + + // and + sut := &webhook.Handler{} + defer sut.SetExecutor(executor)() + + // when + sut.IssueCommentEvent(rec, req) + + // then + if rec.Code != http.StatusBadRequest { + t.Errorf("response code must be %d, but got %d", http.StatusBadRequest, rec.Code) + } + }) + + t.Run("when fail to get github instance", func(t *testing.T) { + // given + rec := httptest.NewRecorder() + req := httptest.NewRequest("GET", "/", nil) + + // and + req.Header = http.Header{ + "X-Github-Delivery": []string{"72d3162e-cc78-11e3-81ab-4c9367dc0958"}, + } + + // and + f, err := os.Open("testdata/issue_comment.skip_comment.json") + if err != nil { + t.Fatalf("error occur: %+v", err) + } + req.Body = f + + // and + container.Clear() + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + executor := mock_executor.NewMockExecutor(ctrl) + executor.EXPECT(). + Execute(gomock.Any(), gomock.Any()). + Times(0) + + // and + sut := &webhook.Handler{} + defer sut.SetExecutor(executor)() + + // when + sut.IssueCommentEvent(rec, req) + + // then + if rec.Code != http.StatusBadRequest { + t.Errorf("response code must be %d, but got %d", http.StatusBadRequest, rec.Code) + } + }) } From aac1e29b74793b288dac9d2082793709997d108b Mon Sep 17 00:00:00 2001 From: duck8823 Date: Fri, 4 Jan 2019 02:34:35 +0900 Subject: [PATCH 098/135] Add test cases --- .../controller/webhook/handler_test.go | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/presentation/controller/webhook/handler_test.go b/presentation/controller/webhook/handler_test.go index 87b6678b..befccda0 100644 --- a/presentation/controller/webhook/handler_test.go +++ b/presentation/controller/webhook/handler_test.go @@ -82,6 +82,124 @@ func TestNewHandler(t *testing.T) { }) } +func TestHandler_ServeHTTP(t *testing.T) { + t.Run("when push event", func(t *testing.T) { + // given + rec := httptest.NewRecorder() + req := httptest.NewRequest("GET", "/", nil) + + // and + req.Header.Set("X-GitHub-Event", "push") + req.Header.Set("X-GitHub-Delivery", "72d3162e-cc78-11e3-81ab-4c9367dc0958") + + // and + f, err := os.Open("testdata/push.correct.json") + if err != nil { + t.Fatalf("error occur: %+v", err) + } + req.Body = f + + // and + ctrl := gomock.NewController(t) + defer func() { + time.Sleep(10 * time.Millisecond) // for goroutine + ctrl.Finish() + }() + + executor := mock_executor.NewMockExecutor(ctrl) + executor.EXPECT(). + Execute(gomock.Any(), gomock.Any()). + Times(1). + Return(nil) + + // and + sut := &webhook.Handler{} + defer sut.SetExecutor(executor)() + + // when + sut.ServeHTTP(rec, req) + + // then + if rec.Code != http.StatusOK { + t.Errorf("response code must be %d, but got %d", http.StatusOK, rec.Code) + } + + println(rec.Body.String()) + }) + + t.Run("when pull request comment event", func(t *testing.T) { + // given + rec := httptest.NewRecorder() + req := httptest.NewRequest("GET", "/", nil) + + // and + req.Header.Set("X-GitHub-Event", "issue_comment") + req.Header.Set("X-GitHub-Delivery", "72d3162e-cc78-11e3-81ab-4c9367dc0958") + + // and + f, err := os.Open("testdata/issue_comment.correct.json") + if err != nil { + t.Fatalf("error occur: %+v", err) + } + req.Body = f + + // and + ctrl := gomock.NewController(t) + defer func() { + time.Sleep(10 * time.Millisecond) // for goroutine + ctrl.Finish() + }() + + gh := mock_github.NewMockGitHub(ctrl) + gh.EXPECT(). + GetPullRequest(gomock.Any(), gomock.Any(), gomock.Eq(2)). + Times(1). + Return(&go_github.PullRequest{ + Head: &go_github.PullRequestBranch{ + Ref: go_github.String("refs/test/dummy"), + SHA: go_github.String("aa218f56b14c9653891f9e74264a383fa43fefbd"), + }, + }, nil) + container.Override(gh) + defer container.Clear() + + executor := mock_executor.NewMockExecutor(ctrl) + executor.EXPECT(). + Execute(gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Return(nil) + + // and + sut := &webhook.Handler{} + defer sut.SetExecutor(executor)() + + // when + sut.ServeHTTP(rec, req) + + // then + if rec.Code != http.StatusOK { + t.Errorf("response code must be %d, but got %d", http.StatusOK, rec.Code) + } + }) + + t.Run("when other event", func(t *testing.T) { + // given + rec := httptest.NewRecorder() + req := httptest.NewRequest("GET", "/", nil) + + // and + sut := &webhook.Handler{} + + // when + sut.ServeHTTP(rec, req) + + // then + if rec.Code != http.StatusBadRequest { + t.Errorf("response code must be %d, but got %d", http.StatusBadRequest, rec.Code) + } + }) +} + func TestHandler_PushEvent(t *testing.T) { t.Run("with no error", func(t *testing.T) { // given From 2cab6e3b38f2987885809ef26f2dbb2dfc4297d9 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Fri, 4 Jan 2019 11:02:37 +0900 Subject: [PATCH 099/135] Add router test --- presentation/router/router_test.go | 64 ++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 presentation/router/router_test.go diff --git a/presentation/router/router_test.go b/presentation/router/router_test.go new file mode 100644 index 00000000..bebbce7c --- /dev/null +++ b/presentation/router/router_test.go @@ -0,0 +1,64 @@ +package router_test + +import ( + "github.com/duck8823/duci/application/service/job" + "github.com/duck8823/duci/domain/model/job/target/github" + "github.com/duck8823/duci/internal/container" + "github.com/duck8823/duci/presentation/router" + "os" + "testing" +) + +func TestNew(t *testing.T) { + t.Run("with no error", func(t *testing.T) { + // given + container.Override(new(job_service.Service)) + container.Override(new(github.GitHub)) + defer container.Clear() + + // when + _, err := router.New() + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + }) + + t.Run("when component not enough", func(t *testing.T) { + // given + container.Clear() + + // when + _, err := router.New() + + // then + if err == nil { + t.Error("error must not be nil") + } + }) + + t.Run("with invalid environment variable for docker client", func(t *testing.T) { + // given + container.Override(new(job_service.Service)) + container.Override(new(github.GitHub)) + defer container.Clear() + + // and + DOCKER_HOST := os.Getenv("DOCKER_HOST") + if err := os.Setenv("DOCKER_HOST", "invalid_host"); err != nil { + t.Fatalf("error occur: %+v", err) + } + defer func() { + _ = os.Setenv("DOCKER_HOST", DOCKER_HOST) + }() + + // when + _, err := router.New() + + // then + if err == nil { + t.Error("error must not be nil") + } + }) +} From 3779da088fc891851f5d78d625dc8f11b6df65b9 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Fri, 4 Jan 2019 11:49:28 +0900 Subject: [PATCH 100/135] Fix panic when failed cast --- application/context.go | 6 +++++- application/duci/duci.go | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/application/context.go b/application/context.go index a4b16dd7..d63d773d 100644 --- a/application/context.go +++ b/application/context.go @@ -29,5 +29,9 @@ func BuildJobFromContext(ctx context.Context) (*BuildJob, error) { if val == nil { return nil, fmt.Errorf("context value '%s' should not be null", ctxKey) } - return val.(*BuildJob), nil + buildJob, ok := val.(*BuildJob) + if !ok { + return nil, fmt.Errorf("invalid type in context '%s'", ctxKey) + } + return buildJob, nil } diff --git a/application/duci/duci.go b/application/duci/duci.go index cdda7a6e..87a75109 100644 --- a/application/duci/duci.go +++ b/application/duci/duci.go @@ -46,7 +46,7 @@ func New() (*duci, error) { func (d *duci) Start(ctx context.Context) { buildJob, err := application.BuildJobFromContext(ctx) if err != nil { - _ = d.jobService.Append(buildJob.ID, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) + // TODO: output error message return } if err := d.jobService.Start(buildJob.ID); err != nil { From 92f668d9d157c9605f2df17dc545b36e3bd6bc4f Mon Sep 17 00:00:00 2001 From: duck8823 Date: Fri, 4 Jan 2019 14:04:26 +0900 Subject: [PATCH 101/135] Fix logic when error --- application/duci/duci.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/application/duci/duci.go b/application/duci/duci.go index 87a75109..59f512e1 100644 --- a/application/duci/duci.go +++ b/application/duci/duci.go @@ -66,7 +66,7 @@ func (d *duci) Start(ctx context.Context) { func (d *duci) AppendLog(ctx context.Context, log job.Log) { buildJob, err := application.BuildJobFromContext(ctx) if err != nil { - _ = d.jobService.Append(buildJob.ID, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) + // TODO: output error message return } for line, err := log.ReadLine(); err == nil; line, err = log.ReadLine() { @@ -79,11 +79,11 @@ func (d *duci) AppendLog(ctx context.Context, log job.Log) { func (d *duci) End(ctx context.Context, e error) { buildJob, err := application.BuildJobFromContext(ctx) if err != nil { - _ = d.jobService.Append(buildJob.ID, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) + // TODO: output error message return } if err := d.jobService.Finish(buildJob.ID); err != nil { - println(fmt.Sprintf("%+v", err)) + _ = d.jobService.Append(buildJob.ID, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) return } From 5144e3f57e9d6b16945abd2f4f47aff4f460dc30 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Fri, 4 Jan 2019 14:05:11 +0900 Subject: [PATCH 102/135] Add test for duci --- application/duci/duci_test.go | 462 ++++++++++++++++++++++++++++++++ application/duci/export_test.go | 48 ++++ 2 files changed, 510 insertions(+) create mode 100644 application/duci/duci_test.go create mode 100644 application/duci/export_test.go diff --git a/application/duci/duci_test.go b/application/duci/duci_test.go new file mode 100644 index 00000000..7fc3b030 --- /dev/null +++ b/application/duci/duci_test.go @@ -0,0 +1,462 @@ +package duci_test + +import ( + "context" + "errors" + "github.com/duck8823/duci/application" + "github.com/duck8823/duci/application/duci" + "github.com/duck8823/duci/application/service/job" + "github.com/duck8823/duci/application/service/job/mock_job" + "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/job/target/github" + "github.com/duck8823/duci/domain/model/job/target/github/mock_github" + "github.com/duck8823/duci/domain/model/runner" + "github.com/duck8823/duci/internal/container" + "github.com/golang/mock/gomock" + "github.com/google/uuid" + "net/url" + "testing" +) + +func TestNew(t *testing.T) { + t.Run("when there are instances in container", func(t *testing.T) { + // given + container.Override(new(job_service.Service)) + container.Override(new(github.GitHub)) + defer container.Clear() + + // when + got, err := duci.New() + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + if got == nil { + t.Errorf("duci must not be nil") + } + }) + + t.Run("when instance not enough in container", func(t *testing.T) { + // where + for _, tt := range []struct { + name string + in []interface{} + }{ + { + name: "with only job_service.Service instance", + in: []interface{}{new(job_service.Service)}, + }, + { + name: "with only github.GitHub instance", + in: []interface{}{new(github.GitHub)}, + }, + } { + t.Run(tt.name, func(t *testing.T) { + // given + container.Clear() + + for _, ins := range tt.in { + container.Override(ins) + } + defer container.Clear() + + // when + got, err := duci.New() + + // then + if err == nil { + t.Error("error must not be nil") + } + + // and + if got != nil { + t.Errorf("duci must be nil, but got %+v", got) + } + }) + } + }) +} + +func TestDuci_Start(t *testing.T) { + t.Run("with no error", func(t *testing.T) { + // given + buildJob := &application.BuildJob{ + ID: job.ID(uuid.New()), + TargetSource: &github.TargetSource{}, + TaskName: "task/name", + TargetURL: duci.URLMust(url.Parse("http://example.com")), + } + ctx := context.WithValue(context.Background(), "duci_job", buildJob) + + // and + ctrl := gomock.NewController(t) + + service := mock_job_service.NewMockService(ctrl) + service.EXPECT(). + Start(gomock.Eq(buildJob.ID)). + Times(1). + Return(nil) + + hub := mock_github.NewMockGitHub(ctrl) + hub.EXPECT(). + CreateCommitStatus(gomock.Eq(ctx), gomock.Eq(github.CommitStatus{ + TargetSource: buildJob.TargetSource, + State: github.PENDING, + Description: "pending", + Context: buildJob.TaskName, + TargetURL: buildJob.TargetURL, + })). + Times(1). + Return(nil) + + // and + sut := &duci.Duci{} + defer sut.SetJobService(service)() + defer sut.SetGitHub(hub)() + + // when + sut.Start(ctx) + + // then + ctrl.Finish() + }) + + t.Run("when invalid build job value", func(t *testing.T) { + // given + ctx := context.WithValue(context.Background(), "duci_job", "invalid value") + + // and + ctrl := gomock.NewController(t) + + service := mock_job_service.NewMockService(ctrl) + service.EXPECT(). + Start(gomock.Any()). + Times(0) + service.EXPECT(). + Append(gomock.Any(), gomock.Any()). + Times(0) + + hub := mock_github.NewMockGitHub(ctrl) + hub.EXPECT(). + CreateCommitStatus(gomock.Any(), gomock.Any()). + Times(0) + + // and + sut := &duci.Duci{} + defer sut.SetJobService(service)() + defer sut.SetGitHub(hub)() + + // when + sut.Start(ctx) + + // then + ctrl.Finish() + }) + + t.Run("when failed to job_service.Service#Start", func(t *testing.T) { + // given + buildJob := &application.BuildJob{ + ID: job.ID(uuid.New()), + TargetSource: &github.TargetSource{}, + TaskName: "task/name", + TargetURL: duci.URLMust(url.Parse("http://example.com")), + } + ctx := context.WithValue(context.Background(), "duci_job", buildJob) + + // and + ctrl := gomock.NewController(t) + + service := mock_job_service.NewMockService(ctrl) + service.EXPECT(). + Start(gomock.Any()). + Times(1). + Return(errors.New("test error")) + service.EXPECT(). + Append(gomock.Any(), gomock.Any()). + Times(1). + Return(nil) + + hub := mock_github.NewMockGitHub(ctrl) + hub.EXPECT(). + CreateCommitStatus(gomock.Any(), gomock.Any()). + Times(0) + + // and + sut := &duci.Duci{} + defer sut.SetJobService(service)() + defer sut.SetGitHub(hub)() + + // when + sut.Start(ctx) + + // then + ctrl.Finish() + }) +} + +func TestDuci_AppendLog(t *testing.T) { + t.Run("with no error", func(t *testing.T) { + // given + buildJob := &application.BuildJob{ + ID: job.ID(uuid.New()), + TargetSource: &github.TargetSource{}, + TaskName: "task/name", + TargetURL: duci.URLMust(url.Parse("http://example.com")), + } + ctx := context.WithValue(context.Background(), "duci_job", buildJob) + + log := &duci.MockLog{Msgs: []string{"Hello", "World"}} + + // and + ctrl := gomock.NewController(t) + service := mock_job_service.NewMockService(ctrl) + service.EXPECT(). + Append(gomock.Eq(buildJob.ID), gomock.Any()). + Times(len(log.Msgs)). + Return(nil) + + // and + sut := &duci.Duci{} + defer sut.SetJobService(service)() + + // when + sut.AppendLog(ctx, log) + + // then + ctrl.Finish() + }) + + t.Run("when invalid build job value", func(t *testing.T) { + // given + ctx := context.WithValue(context.Background(), "duci_job", "invalid value") + log := &duci.MockLog{Msgs: []string{"Hello", "World"}} + + // and + ctrl := gomock.NewController(t) + service := mock_job_service.NewMockService(ctrl) + service.EXPECT(). + Append(gomock.Any(), gomock.Any()). + Times(0) + + // and + sut := &duci.Duci{} + defer sut.SetJobService(service)() + + // when + sut.AppendLog(ctx, log) + + // then + ctrl.Finish() + }) +} + +func TestDuci_End(t *testing.T) { + t.Run("when error is nil", func(t *testing.T) { + // given + buildJob := &application.BuildJob{ + ID: job.ID(uuid.New()), + TargetSource: &github.TargetSource{}, + TaskName: "task/name", + TargetURL: duci.URLMust(url.Parse("http://example.com")), + } + ctx := context.WithValue(context.Background(), "duci_job", buildJob) + var err error = nil + + // and + want := github.CommitStatus{ + TargetSource: buildJob.TargetSource, + State: github.SUCCESS, + Description: "success", + Context: buildJob.TaskName, + TargetURL: buildJob.TargetURL, + } + + // and + ctrl := gomock.NewController(t) + + service := mock_job_service.NewMockService(ctrl) + service.EXPECT(). + Finish(gomock.Any()). + Times(1). + Return(nil) + hub := mock_github.NewMockGitHub(ctrl) + hub.EXPECT(). + CreateCommitStatus(gomock.Eq(ctx), gomock.Eq(want)). + Times(1). + Return(nil) + + // and + sut := &duci.Duci{} + defer sut.SetJobService(service)() + defer sut.SetGitHub(hub)() + + // when + sut.End(ctx, err) + + // then + ctrl.Finish() + }) + + t.Run("when error is runner.Failure", func(t *testing.T) { + // given + buildJob := &application.BuildJob{ + ID: job.ID(uuid.New()), + TargetSource: &github.TargetSource{}, + TaskName: "task/name", + TargetURL: duci.URLMust(url.Parse("http://example.com")), + } + ctx := context.WithValue(context.Background(), "duci_job", buildJob) + err := runner.ErrFailure + + // and + want := github.CommitStatus{ + TargetSource: buildJob.TargetSource, + State: github.FAILURE, + Description: "failure", + Context: buildJob.TaskName, + TargetURL: buildJob.TargetURL, + } + + // and + ctrl := gomock.NewController(t) + + service := mock_job_service.NewMockService(ctrl) + service.EXPECT(). + Finish(gomock.Any()). + Times(1). + Return(nil) + hub := mock_github.NewMockGitHub(ctrl) + hub.EXPECT(). + CreateCommitStatus(gomock.Eq(ctx), gomock.Eq(want)). + Times(1). + Return(nil) + + // and + sut := &duci.Duci{} + defer sut.SetJobService(service)() + defer sut.SetGitHub(hub)() + + // when + sut.End(ctx, err) + + // then + ctrl.Finish() + }) + + t.Run("when error is not nil", func(t *testing.T) { + // given + buildJob := &application.BuildJob{ + ID: job.ID(uuid.New()), + TargetSource: &github.TargetSource{}, + TaskName: "task/name", + TargetURL: duci.URLMust(url.Parse("http://example.com")), + } + ctx := context.WithValue(context.Background(), "duci_job", buildJob) + err := errors.New("test error") + + // and + want := github.CommitStatus{ + TargetSource: buildJob.TargetSource, + State: github.ERROR, + Description: github.Description("error: test error"), + Context: buildJob.TaskName, + TargetURL: buildJob.TargetURL, + } + + // and + ctrl := gomock.NewController(t) + + service := mock_job_service.NewMockService(ctrl) + service.EXPECT(). + Finish(gomock.Any()). + Times(1). + Return(nil) + hub := mock_github.NewMockGitHub(ctrl) + hub.EXPECT(). + CreateCommitStatus(gomock.Eq(ctx), gomock.Eq(want)). + Times(1). + Return(nil) + + // and + sut := &duci.Duci{} + defer sut.SetJobService(service)() + defer sut.SetGitHub(hub)() + + // when + sut.End(ctx, err) + + // then + ctrl.Finish() + }) + + t.Run("when invalid build job value", func(t *testing.T) { + // given + ctx := context.WithValue(context.Background(), "duci_job", "invalid value") + + // and + ctrl := gomock.NewController(t) + + service := mock_job_service.NewMockService(ctrl) + service.EXPECT(). + Finish(gomock.Any()). + Times(0) + hub := mock_github.NewMockGitHub(ctrl) + hub.EXPECT(). + CreateCommitStatus(gomock.Any(), gomock.Any()). + Times(0) + + // and + sut := &duci.Duci{} + defer sut.SetJobService(service)() + defer sut.SetGitHub(hub)() + + // when + sut.End(ctx, nil) + + // then + ctrl.Finish() + }) + + t.Run("when failed to job_service.Service#Finish", func(t *testing.T) { + // given + buildJob := &application.BuildJob{ + ID: job.ID(uuid.New()), + TargetSource: &github.TargetSource{}, + TaskName: "task/name", + TargetURL: duci.URLMust(url.Parse("http://example.com")), + } + ctx := context.WithValue(context.Background(), "duci_job", buildJob) + + // and + ctrl := gomock.NewController(t) + + service := mock_job_service.NewMockService(ctrl) + service.EXPECT(). + Finish(gomock.Any()). + Times(1). + Return(errors.New("test error")) + service.EXPECT(). + Append(gomock.Any(), gomock.Any()). + Times(1). + Return(nil) + + hub := mock_github.NewMockGitHub(ctrl) + hub.EXPECT(). + CreateCommitStatus(gomock.Any(), gomock.Any()). + Times(0) + + // and + sut := &duci.Duci{} + defer sut.SetJobService(service)() + defer sut.SetGitHub(hub)() + + // when + sut.End(ctx, nil) + + // then + ctrl.Finish() + }) +} diff --git a/application/duci/export_test.go b/application/duci/export_test.go new file mode 100644 index 00000000..41e52a82 --- /dev/null +++ b/application/duci/export_test.go @@ -0,0 +1,48 @@ +package duci + +import ( + "github.com/duck8823/duci/application/service/job" + "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/job/target/github" + "io" + "net/url" + "time" +) + +type Duci = duci + +func (d *Duci) SetJobService(service job_service.Service) (reset func()) { + tmp := d.jobService + d.jobService = service + return func() { + d.jobService = tmp + } +} + +func (d *Duci) SetGitHub(hub github.GitHub) (reset func()) { + tmp := d.github + d.github = hub + return func() { + d.github = tmp + } +} + +func URLMust(url *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + return url +} + +type MockLog struct { + Msgs []string +} + +func (l *MockLog) ReadLine() (*job.LogLine, error) { + if len(l.Msgs) == 0 { + return nil, io.EOF + } + msg := l.Msgs[0] + l.Msgs = l.Msgs[1:] + return &job.LogLine{Timestamp: time.Now(), Message: msg}, nil +} From b1ca078b7a63694a32fe3fd915e1a2afc84f22cb Mon Sep 17 00:00:00 2001 From: duck8823 Date: Fri, 4 Jan 2019 17:43:05 +0900 Subject: [PATCH 103/135] Return error instead of panic --- application/duci/duci.go | 7 +++++- application/service/executor/builder.go | 30 ++++++++++++++++--------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/application/duci/duci.go b/application/duci/duci.go index 59f512e1..56b69a77 100644 --- a/application/duci/duci.go +++ b/application/duci/duci.go @@ -29,11 +29,16 @@ func New() (*duci, error) { if err != nil { return nil, errors.WithStack(err) } + builder, err := executor.DefaultExecutorBuilder() + if err != nil { + return nil, errors.WithStack(err) + } + duci := &duci{ jobService: jobService, github: github, } - duci.Executor = executor.DefaultExecutorBuilder(). + duci.Executor = builder. StartFunc(duci.Start). EndFunc(duci.End). LogFunc(duci.AppendLog). diff --git a/application/service/executor/builder.go b/application/service/executor/builder.go index 202614f8..8b8f79c1 100644 --- a/application/service/executor/builder.go +++ b/application/service/executor/builder.go @@ -4,6 +4,7 @@ import ( "context" "github.com/duck8823/duci/domain/model/docker" "github.com/duck8823/duci/domain/model/runner" + "github.com/pkg/errors" ) type builder struct { @@ -14,18 +15,17 @@ type builder struct { } // DefaultExecutorBuilder create new builder of docker runner -func DefaultExecutorBuilder() *builder { - cli, _ := docker.New() - return &builder{ - docker: cli, - logFunc: runner.NothingToDo, - startFunc: func(context.Context) { - // nothing to do - }, - endFunc: func(context.Context, error) { - // nothing to do - }, +func DefaultExecutorBuilder() (*builder, error) { + docker, err := docker.New() + if err != nil { + return nil, errors.WithStack(err) } + return &builder{ + docker: docker, + logFunc: runner.NothingToDo, + startFunc: nothingToDoStart, + endFunc: nothingToDoEnd, + }, nil } // LogFunc set a LogFunc @@ -58,3 +58,11 @@ func (b *builder) Build() *jobExecutor { EndFunc: b.endFunc, } } + +var nothingToDoStart = func(context.Context) { + // nothing to do +} + +var nothingToDoEnd = func(context.Context, error) { + // nothing to do +} From 89f74ac16415a58f9886c8fe943c17b61fca537c Mon Sep 17 00:00:00 2001 From: duck8823 Date: Fri, 4 Jan 2019 17:43:27 +0900 Subject: [PATCH 104/135] Add executor test --- application/service/executor/builder_test.go | 128 ++++++++++ application/service/executor/executor_test.go | 234 ++++++++++++++++++ application/service/executor/export_test.go | 81 ++++++ domain/model/runner/mock_runner/runner.go | 50 ++++ 4 files changed, 493 insertions(+) create mode 100644 application/service/executor/builder_test.go create mode 100644 application/service/executor/executor_test.go create mode 100644 application/service/executor/export_test.go create mode 100644 domain/model/runner/mock_runner/runner.go diff --git a/application/service/executor/builder_test.go b/application/service/executor/builder_test.go new file mode 100644 index 00000000..4d2ad1db --- /dev/null +++ b/application/service/executor/builder_test.go @@ -0,0 +1,128 @@ +package executor_test + +import ( + "context" + "github.com/duck8823/duci/application/service/executor" + "github.com/duck8823/duci/domain/model/docker" + "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/runner" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "reflect" + "testing" +) + +func TestDefaultExecutorBuilder(t *testing.T) { + // given + want := &executor.Builder{} + defer want.SetStartFunc(executor.NothingToDoStart)() + defer want.SetLogFunc(runner.NothingToDo)() + defer want.SetEndFunc(executor.NothingToDoEnd)() + + // when + got, err := executor.DefaultExecutorBuilder() + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + opts := cmp.Options{ + cmp.AllowUnexported(executor.Builder{}), + cmp.Transformer("startFuncToPointer", func(f func(context.Context)) uintptr { + return reflect.ValueOf(f).Pointer() + }), + cmp.Transformer("logFuncToPointer", func(f runner.LogFunc) uintptr { + return reflect.ValueOf(f).Pointer() + }), + cmp.Transformer("endFuncToPointer", func(f func(context.Context, error)) uintptr { + return reflect.ValueOf(f).Pointer() + }), + cmpopts.IgnoreInterfaces(struct{ docker.Docker }{}), + } + if !cmp.Equal(got, want, opts) { + t.Errorf("must be equal. but: %+v", cmp.Diff(got, want, opts)) + } +} + +func TestBuilder_StartFunc(t *testing.T) { + // given + startFunc := func(context.Context) {} + + // and + want := &executor.Builder{} + defer want.SetStartFunc(startFunc)() + + // and + sut := &executor.Builder{} + + // when + got := sut.StartFunc(startFunc) + + // then + opts := cmp.Options{ + cmp.AllowUnexported(executor.Builder{}), + cmp.Transformer("startFuncToPointer", func(f func(context.Context)) uintptr { + return reflect.ValueOf(f).Pointer() + }), + cmpopts.IgnoreInterfaces(struct{ docker.Docker }{}), + } + if !cmp.Equal(got, want, opts) { + t.Errorf("must be equal. but: %+v", cmp.Diff(got, want, opts)) + } +} + +func TestBuilder_LogFunc(t *testing.T) { + // given + logFunc := func(context.Context, job.Log) {} + + // and + want := &executor.Builder{} + defer want.SetLogFunc(logFunc)() + + // and + sut := &executor.Builder{} + + // when + got := sut.LogFunc(logFunc) + + // then + opts := cmp.Options{ + cmp.AllowUnexported(executor.Builder{}), + cmp.Transformer("logFuncToPointer", func(f runner.LogFunc) uintptr { + return reflect.ValueOf(f).Pointer() + }), + cmpopts.IgnoreInterfaces(struct{ docker.Docker }{}), + } + if !cmp.Equal(got, want, opts) { + t.Errorf("must be equal. but: %+v", cmp.Diff(got, want, opts)) + } +} + +func TestBuilder_EndFunc(t *testing.T) { + // given + endFunc := func(context.Context, error) {} + + // and + want := &executor.Builder{} + defer want.SetEndFunc(endFunc)() + + // and + sut := &executor.Builder{} + + // when + got := sut.EndFunc(endFunc) + + // then + opts := cmp.Options{ + cmp.AllowUnexported(executor.Builder{}), + cmp.Transformer("endFuncToPointer", func(f func(context.Context, error)) uintptr { + return reflect.ValueOf(f).Pointer() + }), + cmpopts.IgnoreInterfaces(struct{ docker.Docker }{}), + } + if !cmp.Equal(got, want, opts) { + t.Errorf("must be equal. but: %+v", cmp.Diff(got, want, opts)) + } +} diff --git a/application/service/executor/executor_test.go b/application/service/executor/executor_test.go new file mode 100644 index 00000000..51237bc7 --- /dev/null +++ b/application/service/executor/executor_test.go @@ -0,0 +1,234 @@ +package executor_test + +import ( + "context" + "github.com/duck8823/duci/application" + "github.com/duck8823/duci/application/service/executor" + "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/runner/mock_runner" + "github.com/golang/mock/gomock" + "github.com/labstack/gommon/random" + "github.com/pkg/errors" + "os" + "path" + "testing" + "time" +) + +func TestJobExecutor_Execute(t *testing.T) { + t.Run("with no error", func(t *testing.T) { + // given + ctx := context.Background() + target := &executor.StubTarget{ + Dir: job.WorkDir(path.Join(os.TempDir(), random.String(16))), + Cleanup: func() error { return nil }, + Err: nil, + } + + // and + var calledStartFunc, calledEndFunc bool + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + runner := mock_runner.NewMockDockerRunner(ctrl) + runner.EXPECT(). + Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Return(nil) + + // and + sut := &executor.JobExecutor{} + defer sut.SetDockerRunner(runner)() + defer sut.SetStartFunc(func(context.Context) { + calledStartFunc = true + })() + defer sut.SetEndFunc(func(context.Context, error) { + calledEndFunc = true + })() + + // when + err := sut.Execute(ctx, target) + + // then + if err != nil { + t.Errorf("must be nil, but got %+v", err) + } + + // and + if !calledStartFunc { + t.Errorf("must be called startFunc") + } + + // and + if !calledEndFunc { + t.Errorf("must be called endFunc") + } + }) + + t.Run("with error", func(t *testing.T) { + // given + ctx := context.Background() + target := &executor.StubTarget{ + Dir: job.WorkDir(path.Join(os.TempDir(), random.String(16))), + Cleanup: func() error { return nil }, + Err: nil, + } + + // and + wantErr := errors.New("test error") + + // and + var calledStartFunc, calledEndFunc bool + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + runner := mock_runner.NewMockDockerRunner(ctrl) + runner.EXPECT(). + Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Return(wantErr) + + // and + sut := &executor.JobExecutor{} + defer sut.SetDockerRunner(runner)() + defer sut.SetStartFunc(func(context.Context) { + calledStartFunc = true + })() + defer sut.SetEndFunc(func(context.Context, error) { + calledEndFunc = true + })() + + // when + err := sut.Execute(ctx, target) + + // then + if err != wantErr { + t.Errorf("must be equal. want %+v, but got %+v", wantErr, err) + } + + // and + if !calledStartFunc { + t.Errorf("must be called startFunc") + } + + // and + if !calledEndFunc { + t.Errorf("must be called endFunc") + } + }) + + t.Run("with timeout", func(t *testing.T) { + // given + timeout := application.Config.Timeout() + application.Config.Job.Timeout = 1 + defer func() { + application.Config.Job.Timeout = timeout.Nanoseconds() * 1000 * 1000 + }() + + // and + ctx := context.Background() + target := &executor.StubTarget{ + Dir: job.WorkDir(path.Join(os.TempDir(), random.String(16))), + Cleanup: func() error { return nil }, + Err: nil, + } + + // and + var calledStartFunc, calledEndFunc bool + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + runner := mock_runner.NewMockDockerRunner(ctrl) + runner.EXPECT(). + Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(1). + Do(func(_, _, _, _ interface{}) { + time.Sleep(5 * time.Second) + }). + Return(nil) + + // and + sut := &executor.JobExecutor{} + defer sut.SetDockerRunner(runner)() + defer sut.SetStartFunc(func(context.Context) { + calledStartFunc = true + })() + defer sut.SetEndFunc(func(context.Context, error) { + calledEndFunc = true + })() + + // when + err := sut.Execute(ctx, target) + + // then + if err != context.DeadlineExceeded { + t.Errorf("must be equal. want %+v, but got %+v", context.DeadlineExceeded, err) + } + + // and + if !calledStartFunc { + t.Errorf("must be called startFunc") + } + + // and + if !calledEndFunc { + t.Errorf("must be called endFunc") + } + }) + + t.Run("when prepare returns error", func(t *testing.T) { + // given + ctx := context.Background() + target := &executor.StubTarget{ + Dir: job.WorkDir(path.Join(os.TempDir(), random.String(16))), + Cleanup: func() error { return nil }, + Err: errors.New("test error"), + } + + // and + var calledStartFunc, calledEndFunc bool + + // and + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + runner := mock_runner.NewMockDockerRunner(ctrl) + runner.EXPECT(). + Run(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Times(0) + + // and + sut := &executor.JobExecutor{} + defer sut.SetDockerRunner(runner)() + defer sut.SetStartFunc(func(context.Context) { + calledStartFunc = true + })() + defer sut.SetEndFunc(func(context.Context, error) { + calledEndFunc = true + })() + + // when + err := sut.Execute(ctx, target) + + // then + if err == nil { + t.Error("must not be nil") + } + + // and + if !calledStartFunc { + t.Errorf("must be called startFunc") + } + + // and + if calledEndFunc { + t.Errorf("must not be called endFunc") + } + }) +} diff --git a/application/service/executor/export_test.go b/application/service/executor/export_test.go new file mode 100644 index 00000000..c1dbc20f --- /dev/null +++ b/application/service/executor/export_test.go @@ -0,0 +1,81 @@ +package executor + +import ( + "context" + "github.com/duck8823/duci/domain/model/docker" + "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/runner" +) + +type Builder = builder + +func (b *Builder) SetDocker(docker docker.Docker) (reset func()) { + tmp := b.docker + b.docker = docker + return func() { + b.docker = tmp + } +} + +func (b *Builder) SetStartFunc(startFunc func(context.Context)) (reset func()) { + tmp := b.startFunc + b.startFunc = startFunc + return func() { + b.startFunc = tmp + } +} + +func (b *Builder) SetLogFunc(logFunc func(context.Context, job.Log)) (reset func()) { + tmp := b.logFunc + b.logFunc = logFunc + return func() { + b.logFunc = tmp + } +} + +func (b *Builder) SetEndFunc(endFunc func(context.Context, error)) (reset func()) { + tmp := b.endFunc + b.endFunc = endFunc + return func() { + b.endFunc = tmp + } +} + +var NothingToDoStart = nothingToDoStart +var NothingToDoEnd = nothingToDoEnd + +type JobExecutor = jobExecutor + +func (r *JobExecutor) SetStartFunc(startFunc func(context.Context)) (reset func()) { + tmp := r.StartFunc + r.StartFunc = startFunc + return func() { + r.StartFunc = tmp + } +} + +func (r *JobExecutor) SetEndFunc(endFunc func(context.Context, error)) (reset func()) { + tmp := r.EndFunc + r.EndFunc = endFunc + return func() { + r.EndFunc = tmp + } +} + +func (r *JobExecutor) SetDockerRunner(runner runner.DockerRunner) (reset func()) { + tmp := r.DockerRunner + r.DockerRunner = runner + return func() { + r.DockerRunner = tmp + } +} + +type StubTarget struct { + Dir job.WorkDir + Cleanup job.Cleanup + Err error +} + +func (t *StubTarget) Prepare() (dir job.WorkDir, cleanup job.Cleanup, err error) { + return t.Dir, t.Cleanup, t.Err +} diff --git a/domain/model/runner/mock_runner/runner.go b/domain/model/runner/mock_runner/runner.go new file mode 100644 index 00000000..8d60120f --- /dev/null +++ b/domain/model/runner/mock_runner/runner.go @@ -0,0 +1,50 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: domain/model/runner/runner.go + +// Package mock_runner is a generated GoMock package. +package mock_runner + +import ( + context "context" + docker "github.com/duck8823/duci/domain/model/docker" + job "github.com/duck8823/duci/domain/model/job" + gomock "github.com/golang/mock/gomock" + reflect "reflect" +) + +// MockDockerRunner is a mock of DockerRunner interface +type MockDockerRunner struct { + ctrl *gomock.Controller + recorder *MockDockerRunnerMockRecorder +} + +// MockDockerRunnerMockRecorder is the mock recorder for MockDockerRunner +type MockDockerRunnerMockRecorder struct { + mock *MockDockerRunner +} + +// NewMockDockerRunner creates a new mock instance +func NewMockDockerRunner(ctrl *gomock.Controller) *MockDockerRunner { + mock := &MockDockerRunner{ctrl: ctrl} + mock.recorder = &MockDockerRunnerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockDockerRunner) EXPECT() *MockDockerRunnerMockRecorder { + return m.recorder +} + +// Run mocks base method +func (m *MockDockerRunner) Run(ctx context.Context, dir job.WorkDir, tag docker.Tag, cmd docker.Command) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Run", ctx, dir, tag, cmd) + ret0, _ := ret[0].(error) + return ret0 +} + +// Run indicates an expected call of Run +func (mr *MockDockerRunnerMockRecorder) Run(ctx, dir, tag, cmd interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Run", reflect.TypeOf((*MockDockerRunner)(nil).Run), ctx, dir, tag, cmd) +} From 8b8ea5cad85543365f7df40d85bb5ebfeeb44648 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Fri, 4 Jan 2019 18:54:59 +0900 Subject: [PATCH 105/135] Remove return value from job.Cleanup --- application/service/executor/executor_test.go | 8 ++++---- domain/model/job/target.go | 2 +- domain/model/job/target/local.go | 6 +++--- internal/logger/logger.go | 10 ++++++++++ 4 files changed, 18 insertions(+), 8 deletions(-) create mode 100644 internal/logger/logger.go diff --git a/application/service/executor/executor_test.go b/application/service/executor/executor_test.go index 51237bc7..63d4de7f 100644 --- a/application/service/executor/executor_test.go +++ b/application/service/executor/executor_test.go @@ -21,7 +21,7 @@ func TestJobExecutor_Execute(t *testing.T) { ctx := context.Background() target := &executor.StubTarget{ Dir: job.WorkDir(path.Join(os.TempDir(), random.String(16))), - Cleanup: func() error { return nil }, + Cleanup: func() {}, Err: nil, } @@ -72,7 +72,7 @@ func TestJobExecutor_Execute(t *testing.T) { ctx := context.Background() target := &executor.StubTarget{ Dir: job.WorkDir(path.Join(os.TempDir(), random.String(16))), - Cleanup: func() error { return nil }, + Cleanup: func() {}, Err: nil, } @@ -133,7 +133,7 @@ func TestJobExecutor_Execute(t *testing.T) { ctx := context.Background() target := &executor.StubTarget{ Dir: job.WorkDir(path.Join(os.TempDir(), random.String(16))), - Cleanup: func() error { return nil }, + Cleanup: func() {}, Err: nil, } @@ -187,7 +187,7 @@ func TestJobExecutor_Execute(t *testing.T) { ctx := context.Background() target := &executor.StubTarget{ Dir: job.WorkDir(path.Join(os.TempDir(), random.String(16))), - Cleanup: func() error { return nil }, + Cleanup: func() {}, Err: errors.New("test error"), } diff --git a/domain/model/job/target.go b/domain/model/job/target.go index 356b6616..3abc1aec 100644 --- a/domain/model/job/target.go +++ b/domain/model/job/target.go @@ -10,4 +10,4 @@ func (w WorkDir) String() string { return string(w) } -type Cleanup func() error +type Cleanup func() diff --git a/domain/model/job/target/local.go b/domain/model/job/target/local.go index ee54d364..550dc681 100644 --- a/domain/model/job/target/local.go +++ b/domain/model/job/target/local.go @@ -2,6 +2,7 @@ package target import ( "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/internal/logger" "github.com/labstack/gommon/random" "github.com/pkg/errors" "io" @@ -76,10 +77,9 @@ func copyFile(dstFile string, srcFile string) error { } func cleanupFunc(path string) job.Cleanup { - return func() error { + return func() { if err := os.RemoveAll(path); err != nil { - return errors.WithStack(err) + logger.Error(err) } - return nil } } diff --git a/internal/logger/logger.go b/internal/logger/logger.go new file mode 100644 index 00000000..fa9a7fa0 --- /dev/null +++ b/internal/logger/logger.go @@ -0,0 +1,10 @@ +package logger + +import ( + "fmt" + "os" +) + +func Error(err error) { + _, _ = os.Stderr.WriteString(fmt.Sprintf("%+v", err)) +} From 73e443db33427d611ab118a57619842d79bb1ef2 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Fri, 4 Jan 2019 19:15:23 +0900 Subject: [PATCH 106/135] Remove unused struct --- domain/model/runner/export_test.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/domain/model/runner/export_test.go b/domain/model/runner/export_test.go index 2a1d7e87..02c9619f 100644 --- a/domain/model/runner/export_test.go +++ b/domain/model/runner/export_test.go @@ -51,6 +51,3 @@ var CreateTarball = createTarball var DockerfilePath = dockerfilePath var ExportedRuntimeOptions = runtimeOptions - -type StubLog struct { -} From 3006a29660200985863e02bd5096967630d08e83 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Fri, 4 Jan 2019 21:40:23 +0900 Subject: [PATCH 107/135] Change transform func --- domain/model/runner/builder_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/domain/model/runner/builder_test.go b/domain/model/runner/builder_test.go index 7400819b..69714305 100644 --- a/domain/model/runner/builder_test.go +++ b/domain/model/runner/builder_test.go @@ -2,12 +2,12 @@ package runner_test import ( "context" - "fmt" "github.com/duck8823/duci/domain/model/docker" "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/runner" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" + "reflect" "testing" ) @@ -15,8 +15,8 @@ func TestDefaultDockerRunnerBuilder(t *testing.T) { // given opts := []cmp.Option{ cmp.AllowUnexported(runner.Builder{}), - cmp.Transformer("LogFunc", func(l runner.LogFunc) string { - return fmt.Sprint(l) + cmp.Transformer("LogFunc", func(f runner.LogFunc) uintptr { + return reflect.ValueOf(f).Pointer() }), cmpopts.IgnoreInterfaces(struct{ docker.Docker }{}), } @@ -38,8 +38,8 @@ func TestBuilder_LogFunc(t *testing.T) { // given opts := []cmp.Option{ cmp.AllowUnexported(runner.Builder{}), - cmp.Transformer("LogFunc", func(l runner.LogFunc) string { - return fmt.Sprint(l) + cmp.Transformer("LogFunc", func(f runner.LogFunc) uintptr { + return reflect.ValueOf(f).Pointer() }), cmpopts.IgnoreInterfaces(struct{ docker.Docker }{}), } @@ -74,8 +74,8 @@ func TestBuilder_Build(t *testing.T) { // given opts := []cmp.Option{ cmp.AllowUnexported(runner.DockerRunnerImpl{}), - cmp.Transformer("LogFunc", func(l runner.LogFunc) string { - return fmt.Sprint(l) + cmp.Transformer("LogFunc", func(f runner.LogFunc) uintptr { + return reflect.ValueOf(f).Pointer() }), } From 75cb4af46046afe5c64ae6b303a1238180c8d644 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Fri, 4 Jan 2019 23:03:12 +0900 Subject: [PATCH 108/135] Fix unhandled error --- application/config_test.go | 2 +- domain/model/docker/log.go | 5 ++++- domain/model/runner/helper_test.go | 4 ++-- infrastructure/job/data_source_test.go | 12 ++++++------ presentation/controller/job/handler.go | 5 ++++- presentation/controller/webhook/handler.go | 21 +++++++++++++++++---- 6 files changed, 34 insertions(+), 15 deletions(-) diff --git a/application/config_test.go b/application/config_test.go index 52394ecd..2b2366f7 100644 --- a/application/config_test.go +++ b/application/config_test.go @@ -56,7 +56,7 @@ func TestConfiguration_Set(t *testing.T) { expected := "hello world" // and - os.Setenv("TEST_CONF_ENV", expected) + _ = os.Setenv("TEST_CONF_ENV", expected) // err := application.Config.Set("testdata/config_with_env.yml") diff --git a/domain/model/docker/log.go b/domain/model/docker/log.go index 6e0be265..35f9fe74 100644 --- a/domain/model/docker/log.go +++ b/domain/model/docker/log.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" . "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/internal/logger" "github.com/pkg/errors" "io" "time" @@ -73,7 +74,9 @@ func extractMessage(line []byte) string { s := &struct { Stream string `json:"stream"` }{} - json.NewDecoder(bytes.NewReader(line)).Decode(s) + if err := json.NewDecoder(bytes.NewReader(line)).Decode(s); err != nil { + logger.Error(err) + } return s.Stream } diff --git a/domain/model/runner/helper_test.go b/domain/model/runner/helper_test.go index 835253b8..64fe243b 100644 --- a/domain/model/runner/helper_test.go +++ b/domain/model/runner/helper_test.go @@ -182,7 +182,7 @@ func TestRuntimeOptions(t *testing.T) { } defer file.Close() - file.WriteString(`--- + _, _ = file.WriteString(`--- volumes: - hoge:fuga `) @@ -229,7 +229,7 @@ volumes: } defer file.Close() - file.WriteString("invalid format") + _, _ = file.WriteString("invalid format") return job.WorkDir(tmpDir), func() { _ = os.RemoveAll(tmpDir) diff --git a/infrastructure/job/data_source_test.go b/infrastructure/job/data_source_test.go index 6fd29f87..02b71805 100644 --- a/infrastructure/job/data_source_test.go +++ b/infrastructure/job/data_source_test.go @@ -215,12 +215,12 @@ func TestDataSource_Save(t *testing.T) { id := job.ID(uuid.New()) // and - job := &job.Job{ + j := &job.Job{ ID: id, Finished: false, Stream: []job.LogLine{{Timestamp: time.Now(), Message: "Hello Test"}}, } - data, err := json.Marshal(job) + data, err := json.Marshal(j) if err != nil { t.Fatalf("error occurred: %+v", err) } @@ -240,7 +240,7 @@ func TestDataSource_Save(t *testing.T) { defer sut.SetDB(db)() // expect - if err := sut.Save(*job); err != nil { + if err := sut.Save(*j); err != nil { t.Errorf("error must be nil, but got %+v", err) } }) @@ -250,12 +250,12 @@ func TestDataSource_Save(t *testing.T) { id := job.ID(uuid.New()) // and - job := &job.Job{ + j := &job.Job{ ID: id, Finished: false, Stream: []job.LogLine{{Timestamp: time.Now(), Message: "Hello Test"}}, } - data, err := json.Marshal(job) + data, err := json.Marshal(j) if err != nil { t.Fatalf("error occurred: %+v", err) } @@ -275,7 +275,7 @@ func TestDataSource_Save(t *testing.T) { defer sut.SetDB(db)() // expect - if err := sut.Save(*job); err == nil { + if err := sut.Save(*j); err == nil { t.Error("error must not be nil") } }) diff --git a/presentation/controller/job/handler.go b/presentation/controller/job/handler.go index 5fca9d4b..a37f678d 100644 --- a/presentation/controller/job/handler.go +++ b/presentation/controller/job/handler.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/duck8823/duci/application/service/job" . "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/internal/logger" "github.com/go-chi/chi" "github.com/google/uuid" "github.com/pkg/errors" @@ -54,7 +55,9 @@ func (h *handler) logs(w http.ResponseWriter, id ID) error { return errors.WithStack(err) } for _, msg := range job.Stream[read:] { - json.NewEncoder(w).Encode(msg) + if err := json.NewEncoder(w).Encode(msg); err != nil { + logger.Error(err) + } f.Flush() read++ } diff --git a/presentation/controller/webhook/handler.go b/presentation/controller/webhook/handler.go index 8f3ade36..3f823805 100644 --- a/presentation/controller/webhook/handler.go +++ b/presentation/controller/webhook/handler.go @@ -9,6 +9,7 @@ import ( "github.com/duck8823/duci/application/service/executor" "github.com/duck8823/duci/domain/model/job/target" "github.com/duck8823/duci/domain/model/job/target/github" + "github.com/duck8823/duci/internal/logger" go_github "github.com/google/go-github/github" "github.com/pkg/errors" "gopkg.in/src-d/go-git.v4/plumbing" @@ -77,7 +78,11 @@ func (h *handler) PushEvent(w http.ResponseWriter, r *http.Request) { Point: event, } - go h.executor.Execute(ctx, tgt) + go func() { + if err := h.executor.Execute(ctx, tgt); err != nil { + logger.Error(err) + } + }() w.WriteHeader(http.StatusOK) } @@ -92,7 +97,9 @@ func (h *handler) IssueCommentEvent(w http.ResponseWriter, r *http.Request) { if !isValidAction(event.Action) { w.WriteHeader(http.StatusOK) - w.Write([]byte("{\"message\":\"skip build\"}")) + if _, err := w.Write([]byte("{\"message\":\"skip build\"}")); err != nil { + logger.Error(err) + } return } @@ -111,7 +118,9 @@ func (h *handler) IssueCommentEvent(w http.ResponseWriter, r *http.Request) { phrase, err := extractBuildPhrase(event.GetComment().GetBody()) if err == SkipBuild { w.WriteHeader(http.StatusOK) - w.Write([]byte("{\"message\":\"skip build\"}")) + if _, err := w.Write([]byte("{\"message\":\"skip build\"}")); err != nil { + logger.Error(err) + } return } else if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) @@ -134,7 +143,11 @@ func (h *handler) IssueCommentEvent(w http.ResponseWriter, r *http.Request) { Point: pnt, } - go h.executor.Execute(ctx, tgt, phrase.Command()...) + go func() { + if err := h.executor.Execute(ctx, tgt, phrase.Command()...); err != nil { + logger.Error(err) + } + }() w.WriteHeader(http.StatusOK) } From 5d7434ff1234e4294b09f9b8e21b4aa95dea72d5 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Fri, 4 Jan 2019 23:04:30 +0900 Subject: [PATCH 109/135] Add assertion --- domain/model/job/target/git/log_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/domain/model/job/target/git/log_test.go b/domain/model/job/target/git/log_test.go index 575d7473..6ab795db 100644 --- a/domain/model/job/target/git/log_test.go +++ b/domain/model/job/target/git/log_test.go @@ -50,6 +50,11 @@ func TestCloneLogger_ReadLine(t *testing.T) { if err != io.EOF { t.Errorf("must be equal io.EOF, but got %+v", err) } + + // and + if got != nil { + t.Errorf("must be nil, but got %+v", got) + } } func TestProgressLogger_Write(t *testing.T) { From ff9b4dbc2890093ab53a776289d445c081ce5ac5 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Fri, 4 Jan 2019 23:04:48 +0900 Subject: [PATCH 110/135] Remove redundant return --- internal/container/container.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/container/container.go b/internal/container/container.go index 8489ac8f..88785db6 100644 --- a/internal/container/container.go +++ b/internal/container/container.go @@ -74,12 +74,10 @@ func Override(val interface{}) { } instance.values[key] = val - return } // Reset instances in container // TODO: should not use in production code func Clear() { instance.values = make(map[string]interface{}) - return } From 28bb20b7094954ecb9e23f94b7acb36881ea35b5 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Fri, 4 Jan 2019 23:26:46 +0900 Subject: [PATCH 111/135] Use raw literal for regex --- presentation/controller/webhook/phrase.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/presentation/controller/webhook/phrase.go b/presentation/controller/webhook/phrase.go index c11d129f..ed349d3f 100644 --- a/presentation/controller/webhook/phrase.go +++ b/presentation/controller/webhook/phrase.go @@ -14,9 +14,9 @@ func (p phrase) Command() docker.Command { } func extractBuildPhrase(comment string) (phrase, error) { - if !regexp.MustCompile("^ci\\s+[^\\s]+").Match([]byte(comment)) { + if !regexp.MustCompile(`^ci\s+[^\\s]+`).Match([]byte(comment)) { return "", SkipBuild } - phrase := phrase(regexp.MustCompile("^ci\\s+").ReplaceAllString(comment, "")) + phrase := phrase(regexp.MustCompile(`^ci\s+`).ReplaceAllString(comment, "")) return phrase, nil } From 9c81f9f25cc884101fd94984143a380ced7097dd Mon Sep 17 00:00:00 2001 From: duck8823 Date: Fri, 4 Jan 2019 23:27:00 +0900 Subject: [PATCH 112/135] For more stable --- .../controller/webhook/handler_test.go | 68 ++++++++++--------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/presentation/controller/webhook/handler_test.go b/presentation/controller/webhook/handler_test.go index befccda0..88ed8702 100644 --- a/presentation/controller/webhook/handler_test.go +++ b/presentation/controller/webhook/handler_test.go @@ -101,10 +101,7 @@ func TestHandler_ServeHTTP(t *testing.T) { // and ctrl := gomock.NewController(t) - defer func() { - time.Sleep(10 * time.Millisecond) // for goroutine - ctrl.Finish() - }() + defer ctrl.Finish() executor := mock_executor.NewMockExecutor(ctrl) executor.EXPECT(). @@ -114,7 +111,11 @@ func TestHandler_ServeHTTP(t *testing.T) { // and sut := &webhook.Handler{} - defer sut.SetExecutor(executor)() + reset := sut.SetExecutor(executor) + defer func() { + time.Sleep(10 * time.Millisecond) // for goroutine + reset() + }() // when sut.ServeHTTP(rec, req) @@ -123,8 +124,6 @@ func TestHandler_ServeHTTP(t *testing.T) { if rec.Code != http.StatusOK { t.Errorf("response code must be %d, but got %d", http.StatusOK, rec.Code) } - - println(rec.Body.String()) }) t.Run("when pull request comment event", func(t *testing.T) { @@ -145,10 +144,7 @@ func TestHandler_ServeHTTP(t *testing.T) { // and ctrl := gomock.NewController(t) - defer func() { - time.Sleep(10 * time.Millisecond) // for goroutine - ctrl.Finish() - }() + defer ctrl.Finish() gh := mock_github.NewMockGitHub(ctrl) gh.EXPECT(). @@ -171,7 +167,11 @@ func TestHandler_ServeHTTP(t *testing.T) { // and sut := &webhook.Handler{} - defer sut.SetExecutor(executor)() + reset := sut.SetExecutor(executor) + defer func() { + time.Sleep(10 * time.Millisecond) // for goroutine + reset() + }() // when sut.ServeHTTP(rec, req) @@ -220,10 +220,7 @@ func TestHandler_PushEvent(t *testing.T) { // and ctrl := gomock.NewController(t) - defer func() { - time.Sleep(10 * time.Millisecond) // for goroutine - ctrl.Finish() - }() + defer ctrl.Finish() executor := mock_executor.NewMockExecutor(ctrl) executor.EXPECT(). @@ -265,7 +262,11 @@ func TestHandler_PushEvent(t *testing.T) { // and sut := &webhook.Handler{} - defer sut.SetExecutor(executor)() + reset := sut.SetExecutor(executor) + defer func() { + time.Sleep(10 * time.Millisecond) // for goroutine + reset() + }() // when sut.PushEvent(rec, req) @@ -373,10 +374,7 @@ func TestHandler_IssueCommentEvent(t *testing.T) { // and ctrl := gomock.NewController(t) - defer func() { - time.Sleep(10 * time.Millisecond) // for goroutine - ctrl.Finish() - }() + defer ctrl.Finish() gh := mock_github.NewMockGitHub(ctrl) gh.EXPECT(). @@ -431,7 +429,11 @@ func TestHandler_IssueCommentEvent(t *testing.T) { // and sut := &webhook.Handler{} - defer sut.SetExecutor(executor)() + reset := sut.SetExecutor(executor) + defer func() { + time.Sleep(10 * time.Millisecond) // for goroutine + reset() + }() // when sut.IssueCommentEvent(rec, req) @@ -461,10 +463,7 @@ func TestHandler_IssueCommentEvent(t *testing.T) { // and ctrl := gomock.NewController(t) - defer func() { - time.Sleep(10 * time.Millisecond) // for goroutine - ctrl.Finish() - }() + defer ctrl.Finish() executor := mock_executor.NewMockExecutor(ctrl) executor.EXPECT(). @@ -473,7 +472,11 @@ func TestHandler_IssueCommentEvent(t *testing.T) { // and sut := &webhook.Handler{} - defer sut.SetExecutor(executor)() + reset := sut.SetExecutor(executor) + defer func() { + time.Sleep(10 * time.Millisecond) // for goroutine + reset() + }() // when sut.IssueCommentEvent(rec, req) @@ -507,10 +510,7 @@ func TestHandler_IssueCommentEvent(t *testing.T) { // and ctrl := gomock.NewController(t) - defer func() { - time.Sleep(10 * time.Millisecond) // for goroutine - ctrl.Finish() - }() + defer ctrl.Finish() executor := mock_executor.NewMockExecutor(ctrl) executor.EXPECT(). @@ -519,7 +519,11 @@ func TestHandler_IssueCommentEvent(t *testing.T) { // and sut := &webhook.Handler{} - defer sut.SetExecutor(executor)() + reset := sut.SetExecutor(executor) + defer func() { + time.Sleep(10 * time.Millisecond) // for goroutine + reset() + }() // when sut.IssueCommentEvent(rec, req) From 7d5f184e6865f85d3f0cd3bacf595bfef22a255b Mon Sep 17 00:00:00 2001 From: duck8823 Date: Fri, 4 Jan 2019 23:52:15 +0900 Subject: [PATCH 113/135] Separate test case --- .../controller/webhook/handler_test.go | 100 +++++++++--------- 1 file changed, 51 insertions(+), 49 deletions(-) diff --git a/presentation/controller/webhook/handler_test.go b/presentation/controller/webhook/handler_test.go index 88ed8702..a52221d5 100644 --- a/presentation/controller/webhook/handler_test.go +++ b/presentation/controller/webhook/handler_test.go @@ -354,7 +354,7 @@ func TestHandler_PushEvent(t *testing.T) { }) } -func TestHandler_IssueCommentEvent(t *testing.T) { +func TestHandler_IssueCommentEvent_Normal(t *testing.T) { t.Run("with no error", func(t *testing.T) { // given rec := httptest.NewRecorder() @@ -444,7 +444,7 @@ func TestHandler_IssueCommentEvent(t *testing.T) { } }) - t.Run("when action is deleted", func(t *testing.T) { + t.Run("when no match comment", func(t *testing.T) { // given rec := httptest.NewRecorder() req := httptest.NewRequest("GET", "/", nil) @@ -455,7 +455,7 @@ func TestHandler_IssueCommentEvent(t *testing.T) { } // and - f, err := os.Open("testdata/issue_comment.deleted.json") + f, err := os.Open("testdata/issue_comment.skip_comment.json") if err != nil { t.Fatalf("error occur: %+v", err) } @@ -465,18 +465,27 @@ func TestHandler_IssueCommentEvent(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() + gh := mock_github.NewMockGitHub(ctrl) + gh.EXPECT(). + GetPullRequest(gomock.Any(), gomock.Any(), gomock.Eq(2)). + Times(1). + Return(&go_github.PullRequest{ + Head: &go_github.PullRequestBranch{ + Ref: go_github.String("refs/test/dummy"), + SHA: go_github.String("aa218f56b14c9653891f9e74264a383fa43fefbd"), + }, + }, nil) + container.Override(gh) + defer container.Clear() + executor := mock_executor.NewMockExecutor(ctrl) executor.EXPECT(). - Execute(gomock.Any(), gomock.Any(), gomock.Any()). + Execute(gomock.Any(), gomock.Any()). Times(0) // and sut := &webhook.Handler{} - reset := sut.SetExecutor(executor) - defer func() { - time.Sleep(10 * time.Millisecond) // for goroutine - reset() - }() + defer sut.SetExecutor(executor)() // when sut.IssueCommentEvent(rec, req) @@ -493,7 +502,7 @@ func TestHandler_IssueCommentEvent(t *testing.T) { } }) - t.Run("with invalid payload body", func(t *testing.T) { + t.Run("when action is deleted", func(t *testing.T) { // given rec := httptest.NewRecorder() req := httptest.NewRequest("GET", "/", nil) @@ -504,9 +513,11 @@ func TestHandler_IssueCommentEvent(t *testing.T) { } // and - req.Body = ioutils.NewReadCloserWrapper(strings.NewReader("invalid payload"), func() error { - return nil - }) + f, err := os.Open("testdata/issue_comment.deleted.json") + if err != nil { + t.Fatalf("error occur: %+v", err) + } + req.Body = f // and ctrl := gomock.NewController(t) @@ -529,27 +540,33 @@ func TestHandler_IssueCommentEvent(t *testing.T) { sut.IssueCommentEvent(rec, req) // then - if rec.Code != http.StatusInternalServerError { - t.Errorf("response code must be %d, but got %d", http.StatusInternalServerError, rec.Code) + if rec.Code != http.StatusOK { + t.Errorf("response code must be %d, but got %d", http.StatusOK, rec.Code) + } + + // and + got := rec.Body.String() + if got != `{"message":"skip build"}` { + t.Errorf("must be equal. want %s, but got %s", `{"message":"skip build"}`, got) } }) +} - t.Run("when url param is invalid format uuid", func(t *testing.T) { +func TestHandler_IssueCommentEvent_UnNormal(t *testing.T) { + t.Run("with invalid payload body", func(t *testing.T) { // given rec := httptest.NewRecorder() req := httptest.NewRequest("GET", "/", nil) // and req.Header = http.Header{ - "X-Github-Delivery": []string{"invalid format"}, + "X-Github-Delivery": []string{"72d3162e-cc78-11e3-81ab-4c9367dc0958"}, } // and - f, err := os.Open("testdata/issue_comment.correct.json") - if err != nil { - t.Fatalf("error occur: %+v", err) - } - req.Body = f + req.Body = ioutils.NewReadCloserWrapper(strings.NewReader("invalid payload"), func() error { + return nil + }) // and ctrl := gomock.NewController(t) @@ -557,19 +574,23 @@ func TestHandler_IssueCommentEvent(t *testing.T) { executor := mock_executor.NewMockExecutor(ctrl) executor.EXPECT(). - Execute(gomock.Any(), gomock.Any()). + Execute(gomock.Any(), gomock.Any(), gomock.Any()). Times(0) // and sut := &webhook.Handler{} - defer sut.SetExecutor(executor)() + reset := sut.SetExecutor(executor) + defer func() { + time.Sleep(10 * time.Millisecond) // for goroutine + reset() + }() // when sut.IssueCommentEvent(rec, req) // then - if rec.Code != http.StatusBadRequest { - t.Errorf("response code must be %d, but got %d", http.StatusBadRequest, rec.Code) + if rec.Code != http.StatusInternalServerError { + t.Errorf("response code must be %d, but got %d", http.StatusInternalServerError, rec.Code) } }) @@ -580,11 +601,11 @@ func TestHandler_IssueCommentEvent(t *testing.T) { // and req.Header = http.Header{ - "X-Github-Delivery": []string{"72d3162e-cc78-11e3-81ab-4c9367dc0958"}, + "X-Github-Delivery": []string{"invalid format"}, } // and - f, err := os.Open("testdata/issue_comment.skip_comment.json") + f, err := os.Open("testdata/issue_comment.correct.json") if err != nil { t.Fatalf("error occur: %+v", err) } @@ -594,19 +615,6 @@ func TestHandler_IssueCommentEvent(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - gh := mock_github.NewMockGitHub(ctrl) - gh.EXPECT(). - GetPullRequest(gomock.Any(), gomock.Any(), gomock.Eq(2)). - Times(1). - Return(&go_github.PullRequest{ - Head: &go_github.PullRequestBranch{ - Ref: go_github.String("refs/test/dummy"), - SHA: go_github.String("aa218f56b14c9653891f9e74264a383fa43fefbd"), - }, - }, nil) - container.Override(gh) - defer container.Clear() - executor := mock_executor.NewMockExecutor(ctrl) executor.EXPECT(). Execute(gomock.Any(), gomock.Any()). @@ -620,14 +628,8 @@ func TestHandler_IssueCommentEvent(t *testing.T) { sut.IssueCommentEvent(rec, req) // then - if rec.Code != http.StatusOK { - t.Errorf("response code must be %d, but got %d", http.StatusOK, rec.Code) - } - - // and - got := rec.Body.String() - if got != `{"message":"skip build"}` { - t.Errorf("must be equal. want %s, but got %s", `{"message":"skip build"}`, got) + if rec.Code != http.StatusBadRequest { + t.Errorf("response code must be %d, but got %d", http.StatusBadRequest, rec.Code) } }) From 7a12a0cc00a875b70f25fad8416a7c1f8a680a4c Mon Sep 17 00:00:00 2001 From: duck8823 Date: Sat, 5 Jan 2019 00:04:53 +0900 Subject: [PATCH 114/135] Change context key to use pointer --- application/context.go | 4 ++-- application/duci/duci_test.go | 20 ++++++++++---------- application/duci/export_test.go | 4 ++++ application/export_test.go | 4 ++-- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/application/context.go b/application/context.go index d63d773d..ea2b7165 100644 --- a/application/context.go +++ b/application/context.go @@ -20,12 +20,12 @@ type BuildJob struct { // ContextWithJob set parent context BuildJob and returns it. func ContextWithJob(parent context.Context, job *BuildJob) context.Context { - return context.WithValue(parent, ctxKey, job) + return context.WithValue(parent, &ctxKey, job) } // BuildJobFromContext extract BuildJob from context func BuildJobFromContext(ctx context.Context) (*BuildJob, error) { - val := ctx.Value(ctxKey) + val := ctx.Value(&ctxKey) if val == nil { return nil, fmt.Errorf("context value '%s' should not be null", ctxKey) } diff --git a/application/duci/duci_test.go b/application/duci/duci_test.go index 7fc3b030..3e2ead30 100644 --- a/application/duci/duci_test.go +++ b/application/duci/duci_test.go @@ -89,7 +89,7 @@ func TestDuci_Start(t *testing.T) { TaskName: "task/name", TargetURL: duci.URLMust(url.Parse("http://example.com")), } - ctx := context.WithValue(context.Background(), "duci_job", buildJob) + ctx := application.ContextWithJob(context.Background(), buildJob) // and ctrl := gomock.NewController(t) @@ -126,7 +126,7 @@ func TestDuci_Start(t *testing.T) { t.Run("when invalid build job value", func(t *testing.T) { // given - ctx := context.WithValue(context.Background(), "duci_job", "invalid value") + ctx := context.WithValue(context.Background(), duci.String("duci_job"), "invalid value") // and ctrl := gomock.NewController(t) @@ -164,7 +164,7 @@ func TestDuci_Start(t *testing.T) { TaskName: "task/name", TargetURL: duci.URLMust(url.Parse("http://example.com")), } - ctx := context.WithValue(context.Background(), "duci_job", buildJob) + ctx := application.ContextWithJob(context.Background(), buildJob) // and ctrl := gomock.NewController(t) @@ -206,7 +206,7 @@ func TestDuci_AppendLog(t *testing.T) { TaskName: "task/name", TargetURL: duci.URLMust(url.Parse("http://example.com")), } - ctx := context.WithValue(context.Background(), "duci_job", buildJob) + ctx := application.ContextWithJob(context.Background(), buildJob) log := &duci.MockLog{Msgs: []string{"Hello", "World"}} @@ -231,7 +231,7 @@ func TestDuci_AppendLog(t *testing.T) { t.Run("when invalid build job value", func(t *testing.T) { // given - ctx := context.WithValue(context.Background(), "duci_job", "invalid value") + ctx := context.WithValue(context.Background(), duci.String("duci_job"), "invalid value") log := &duci.MockLog{Msgs: []string{"Hello", "World"}} // and @@ -262,7 +262,7 @@ func TestDuci_End(t *testing.T) { TaskName: "task/name", TargetURL: duci.URLMust(url.Parse("http://example.com")), } - ctx := context.WithValue(context.Background(), "duci_job", buildJob) + ctx := application.ContextWithJob(context.Background(), buildJob) var err error = nil // and @@ -308,7 +308,7 @@ func TestDuci_End(t *testing.T) { TaskName: "task/name", TargetURL: duci.URLMust(url.Parse("http://example.com")), } - ctx := context.WithValue(context.Background(), "duci_job", buildJob) + ctx := application.ContextWithJob(context.Background(), buildJob) err := runner.ErrFailure // and @@ -354,7 +354,7 @@ func TestDuci_End(t *testing.T) { TaskName: "task/name", TargetURL: duci.URLMust(url.Parse("http://example.com")), } - ctx := context.WithValue(context.Background(), "duci_job", buildJob) + ctx := application.ContextWithJob(context.Background(), buildJob) err := errors.New("test error") // and @@ -394,7 +394,7 @@ func TestDuci_End(t *testing.T) { t.Run("when invalid build job value", func(t *testing.T) { // given - ctx := context.WithValue(context.Background(), "duci_job", "invalid value") + ctx := context.WithValue(context.Background(), duci.String("duci_job"), "invalid value") // and ctrl := gomock.NewController(t) @@ -428,7 +428,7 @@ func TestDuci_End(t *testing.T) { TaskName: "task/name", TargetURL: duci.URLMust(url.Parse("http://example.com")), } - ctx := context.WithValue(context.Background(), "duci_job", buildJob) + ctx := application.ContextWithJob(context.Background(), buildJob) // and ctrl := gomock.NewController(t) diff --git a/application/duci/export_test.go b/application/duci/export_test.go index 41e52a82..09e2ebcd 100644 --- a/application/duci/export_test.go +++ b/application/duci/export_test.go @@ -46,3 +46,7 @@ func (l *MockLog) ReadLine() (*job.LogLine, error) { l.Msgs = l.Msgs[1:] return &job.LogLine{Timestamp: time.Now(), Message: msg}, nil } + +func String(val string) *string { + return &val +} diff --git a/application/export_test.go b/application/export_test.go index b111f7ce..b0e74fb4 100644 --- a/application/export_test.go +++ b/application/export_test.go @@ -28,6 +28,6 @@ func TrimSuffix(tag string) string { return trimSuffix(tag) } -func GetCtxKey() string { - return ctxKey +func GetCtxKey() *string { + return &ctxKey } From 3c01661ea176bf27a32a5f7cb4677c84fcb96347 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Sat, 5 Jan 2019 00:08:24 +0900 Subject: [PATCH 115/135] Change return type to exported type --- application/duci/duci.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/duci/duci.go b/application/duci/duci.go index 56b69a77..bd76d88e 100644 --- a/application/duci/duci.go +++ b/application/duci/duci.go @@ -20,7 +20,7 @@ type duci struct { } // New returns duci instance -func New() (*duci, error) { +func New() (executor.Executor, error) { jobService, err := job_service.GetInstance() if err != nil { return nil, errors.WithStack(err) From 113190b5cb2b53cd523c41d318bf61bd5ff62d09 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Sat, 5 Jan 2019 00:09:58 +0900 Subject: [PATCH 116/135] Fix error messages --- application/semaphore/semaphore.go | 2 +- presentation/controller/job/handler.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/application/semaphore/semaphore.go b/application/semaphore/semaphore.go index a4a7eb45..f492ab7d 100644 --- a/application/semaphore/semaphore.go +++ b/application/semaphore/semaphore.go @@ -14,7 +14,7 @@ var ( // Make create semaphore with configuration func Make() error { if initialized { - return errors.New("semaphore already created.") + return errors.New("semaphore already created") } sem = make(chan struct{}, application.Config.Job.Concurrency) initialized = true diff --git a/presentation/controller/job/handler.go b/presentation/controller/job/handler.go index a37f678d..fa697c93 100644 --- a/presentation/controller/job/handler.go +++ b/presentation/controller/job/handler.go @@ -44,7 +44,7 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (h *handler) logs(w http.ResponseWriter, id ID) error { f, ok := w.(http.Flusher) if !ok { - return errors.New("Streaming unsupported!") + return errors.New("Streaming unsupported") } // TODO: add timeout From d5f3ef636730f3358227326f582d993033f4d269 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Sat, 5 Jan 2019 00:15:03 +0900 Subject: [PATCH 117/135] Change to exported type --- application/service/executor/builder.go | 17 +++++++++-------- application/service/executor/export_test.go | 2 -- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/application/service/executor/builder.go b/application/service/executor/builder.go index 8b8f79c1..ebbf8423 100644 --- a/application/service/executor/builder.go +++ b/application/service/executor/builder.go @@ -7,20 +7,21 @@ import ( "github.com/pkg/errors" ) -type builder struct { +// Builder is an executor builder +type Builder struct { docker docker.Docker logFunc runner.LogFunc startFunc func(context.Context) endFunc func(context.Context, error) } -// DefaultExecutorBuilder create new builder of docker runner -func DefaultExecutorBuilder() (*builder, error) { +// DefaultExecutorBuilder create new Builder of docker runner +func DefaultExecutorBuilder() (*Builder, error) { docker, err := docker.New() if err != nil { return nil, errors.WithStack(err) } - return &builder{ + return &Builder{ docker: docker, logFunc: runner.NothingToDo, startFunc: nothingToDoStart, @@ -29,25 +30,25 @@ func DefaultExecutorBuilder() (*builder, error) { } // LogFunc set a LogFunc -func (b *builder) LogFunc(f runner.LogFunc) *builder { +func (b *Builder) LogFunc(f runner.LogFunc) *Builder { b.logFunc = f return b } // StartFunc set a startFunc -func (b *builder) StartFunc(f func(context.Context)) *builder { +func (b *Builder) StartFunc(f func(context.Context)) *Builder { b.startFunc = f return b } // EndFunc set a endFunc -func (b *builder) EndFunc(f func(context.Context, error)) *builder { +func (b *Builder) EndFunc(f func(context.Context, error)) *Builder { b.endFunc = f return b } // Build returns a executor -func (b *builder) Build() *jobExecutor { +func (b *Builder) Build() Executor { r := runner.DefaultDockerRunnerBuilder(). LogFunc(b.logFunc). Build() diff --git a/application/service/executor/export_test.go b/application/service/executor/export_test.go index c1dbc20f..f2336ac4 100644 --- a/application/service/executor/export_test.go +++ b/application/service/executor/export_test.go @@ -7,8 +7,6 @@ import ( "github.com/duck8823/duci/domain/model/runner" ) -type Builder = builder - func (b *Builder) SetDocker(docker docker.Docker) (reset func()) { tmp := b.docker b.docker = docker From 7a688d071fcc975a3a0ed89c1f6380c7a9837bdd Mon Sep 17 00:00:00 2001 From: duck8823 Date: Sat, 5 Jan 2019 00:31:11 +0900 Subject: [PATCH 118/135] Change package name --- application/duci/duci_test.go | 6 ++-- application/duci/export_test.go | 4 +-- application/initialize.go | 4 +-- application/initialize_test.go | 4 +-- application/service/job/export_test.go | 2 +- application/service/job/service.go | 2 +- application/service/job/service_impl.go | 2 +- application/service/job/service_test.go | 36 +++++++++---------- presentation/controller/job/export_test.go | 2 +- presentation/controller/job/handler.go | 12 +++---- presentation/controller/job/handler_test.go | 30 ++++++++-------- .../controller/webhook/handler_test.go | 6 ++-- presentation/router/router_test.go | 4 +-- 13 files changed, 57 insertions(+), 57 deletions(-) diff --git a/application/duci/duci_test.go b/application/duci/duci_test.go index 3e2ead30..7545fded 100644 --- a/application/duci/duci_test.go +++ b/application/duci/duci_test.go @@ -5,7 +5,7 @@ import ( "errors" "github.com/duck8823/duci/application" "github.com/duck8823/duci/application/duci" - "github.com/duck8823/duci/application/service/job" + jobService "github.com/duck8823/duci/application/service/job" "github.com/duck8823/duci/application/service/job/mock_job" "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/job/target/github" @@ -21,7 +21,7 @@ import ( func TestNew(t *testing.T) { t.Run("when there are instances in container", func(t *testing.T) { // given - container.Override(new(job_service.Service)) + container.Override(new(jobService.Service)) container.Override(new(github.GitHub)) defer container.Clear() @@ -47,7 +47,7 @@ func TestNew(t *testing.T) { }{ { name: "with only job_service.Service instance", - in: []interface{}{new(job_service.Service)}, + in: []interface{}{new(jobService.Service)}, }, { name: "with only github.GitHub instance", diff --git a/application/duci/export_test.go b/application/duci/export_test.go index 09e2ebcd..62d7424b 100644 --- a/application/duci/export_test.go +++ b/application/duci/export_test.go @@ -1,7 +1,7 @@ package duci import ( - "github.com/duck8823/duci/application/service/job" + jobService "github.com/duck8823/duci/application/service/job" "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/job/target/github" "io" @@ -11,7 +11,7 @@ import ( type Duci = duci -func (d *Duci) SetJobService(service job_service.Service) (reset func()) { +func (d *Duci) SetJobService(service jobService.Service) (reset func()) { tmp := d.jobService d.jobService = service return func() { diff --git a/application/initialize.go b/application/initialize.go index 21f7ea1f..91092578 100644 --- a/application/initialize.go +++ b/application/initialize.go @@ -2,7 +2,7 @@ package application import ( "context" - "github.com/duck8823/duci/application/service/job" + jobService "github.com/duck8823/duci/application/service/job" "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/job/target/git" "github.com/duck8823/duci/domain/model/job/target/github" @@ -23,7 +23,7 @@ func Initialize() error { return errors.WithStack(err) } - if err := job_service.Initialize(Config.Server.DatabasePath); err != nil { + if err := jobService.Initialize(Config.Server.DatabasePath); err != nil { return errors.WithStack(err) } return nil diff --git a/application/initialize_test.go b/application/initialize_test.go index 347c707d..a537365c 100644 --- a/application/initialize_test.go +++ b/application/initialize_test.go @@ -41,7 +41,7 @@ func TestInitialize(t *testing.T) { } // and - jobService := new(job_service.Service) + jobService := new(job.Service) if err := container.Get(jobService); err != nil { t.Errorf("error must be nil, but got %+v", err) } @@ -86,7 +86,7 @@ func TestInitialize(t *testing.T) { application.Config.Server.DatabasePath = path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) // and - container.Override(new(job_service.Service)) + container.Override(new(job.Service)) defer container.Clear() // when diff --git a/application/service/job/export_test.go b/application/service/job/export_test.go index e778ef27..bf741f13 100644 --- a/application/service/job/export_test.go +++ b/application/service/job/export_test.go @@ -1,4 +1,4 @@ -package job_service +package job import "github.com/duck8823/duci/domain/model/job" diff --git a/application/service/job/service.go b/application/service/job/service.go index 38076a4c..51ed22a4 100644 --- a/application/service/job/service.go +++ b/application/service/job/service.go @@ -1,4 +1,4 @@ -package job_service +package job import "github.com/duck8823/duci/domain/model/job" diff --git a/application/service/job/service_impl.go b/application/service/job/service_impl.go index b31ae7ae..7e38e7f7 100644 --- a/application/service/job/service_impl.go +++ b/application/service/job/service_impl.go @@ -1,4 +1,4 @@ -package job_service +package job import ( . "github.com/duck8823/duci/domain/model/job" diff --git a/application/service/job/service_test.go b/application/service/job/service_test.go index 2f3af885..c5ceb7ba 100644 --- a/application/service/job/service_test.go +++ b/application/service/job/service_test.go @@ -1,7 +1,7 @@ -package job_service_test +package job_test import ( - "github.com/duck8823/duci/application/service/job" + jobService "github.com/duck8823/duci/application/service/job" "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/job/mock_job" "github.com/duck8823/duci/internal/container" @@ -25,7 +25,7 @@ func TestInitialize(t *testing.T) { }() // when - err := job_service.Initialize(tmpDir) + err := jobService.Initialize(tmpDir) // then if err != nil { @@ -41,7 +41,7 @@ func TestInitialize(t *testing.T) { }() // when - err := job_service.Initialize(tmpDir) + err := jobService.Initialize(tmpDir) // then if err == nil { @@ -56,7 +56,7 @@ func TestGetInstance(t *testing.T) { container.Clear() // when - got, err := job_service.GetInstance() + got, err := jobService.GetInstance() // then if err == nil { @@ -71,7 +71,7 @@ func TestGetInstance(t *testing.T) { t.Run("when instance is not nil", func(t *testing.T) { // given - want := &job_service.StubService{ + want := &jobService.StubService{ ID: random.String(16, random.Alphanumeric), } @@ -80,7 +80,7 @@ func TestGetInstance(t *testing.T) { defer container.Clear() // when - got, err := job_service.GetInstance() + got, err := jobService.GetInstance() // then if err != nil { @@ -122,7 +122,7 @@ func TestServiceImpl_FindBy(t *testing.T) { Return(want, nil) // and - sut := &job_service.ServiceImpl{} + sut := &jobService.ServiceImpl{} defer sut.SetRepo(repo)() // when @@ -154,7 +154,7 @@ func TestServiceImpl_FindBy(t *testing.T) { Return(nil, errors.New("test error")) // and - sut := &job_service.ServiceImpl{} + sut := &jobService.ServiceImpl{} defer sut.SetRepo(repo)() // when @@ -188,7 +188,7 @@ func TestServiceImpl_Start(t *testing.T) { Return(nil) // and - sut := &job_service.ServiceImpl{} + sut := &jobService.ServiceImpl{} defer sut.SetRepo(repo)() // when @@ -215,7 +215,7 @@ func TestServiceImpl_Start(t *testing.T) { Return(errors.New("test error")) // and - sut := &job_service.ServiceImpl{} + sut := &jobService.ServiceImpl{} defer sut.SetRepo(repo)() // when @@ -245,7 +245,7 @@ func TestServiceImpl_Append(t *testing.T) { Return(nil, errors.New("test error")) // and - sut := &job_service.ServiceImpl{} + sut := &jobService.ServiceImpl{} defer sut.SetRepo(repo)() // when @@ -277,7 +277,7 @@ func TestServiceImpl_Append(t *testing.T) { Return(errors.New("test error")) // and - sut := &job_service.ServiceImpl{} + sut := &jobService.ServiceImpl{} defer sut.SetRepo(repo)() // when @@ -309,7 +309,7 @@ func TestServiceImpl_Append(t *testing.T) { Return(errors.New("test error")) // and - sut := &job_service.ServiceImpl{} + sut := &jobService.ServiceImpl{} defer sut.SetRepo(repo)() // when @@ -343,7 +343,7 @@ func TestServiceImpl_Append(t *testing.T) { Return(nil) // and - sut := &job_service.ServiceImpl{} + sut := &jobService.ServiceImpl{} defer sut.SetRepo(repo)() // when @@ -372,7 +372,7 @@ func TestServiceImpl_Finish(t *testing.T) { Return(nil, errors.New("test error")) // and - sut := &job_service.ServiceImpl{} + sut := &jobService.ServiceImpl{} defer sut.SetRepo(repo)() // when @@ -403,7 +403,7 @@ func TestServiceImpl_Finish(t *testing.T) { Return(errors.New("test error")) // and - sut := &job_service.ServiceImpl{} + sut := &jobService.ServiceImpl{} defer sut.SetRepo(repo)() // when @@ -433,7 +433,7 @@ func TestServiceImpl_Finish(t *testing.T) { Return(nil) // and - sut := &job_service.ServiceImpl{} + sut := &jobService.ServiceImpl{} defer sut.SetRepo(repo)() // when diff --git a/presentation/controller/job/export_test.go b/presentation/controller/job/export_test.go index ee5c4e74..34531bcd 100644 --- a/presentation/controller/job/export_test.go +++ b/presentation/controller/job/export_test.go @@ -4,7 +4,7 @@ import "github.com/duck8823/duci/application/service/job" type Handler = handler -func (h *Handler) SetService(service job_service.Service) (reset func()) { +func (h *Handler) SetService(service job.Service) (reset func()) { tmp := h.service h.service = service return func() { diff --git a/presentation/controller/job/handler.go b/presentation/controller/job/handler.go index fa697c93..0ae718b9 100644 --- a/presentation/controller/job/handler.go +++ b/presentation/controller/job/handler.go @@ -3,8 +3,8 @@ package job import ( "encoding/json" "fmt" - "github.com/duck8823/duci/application/service/job" - . "github.com/duck8823/duci/domain/model/job" + jobService "github.com/duck8823/duci/application/service/job" + "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/internal/logger" "github.com/go-chi/chi" "github.com/google/uuid" @@ -13,12 +13,12 @@ import ( ) type handler struct { - service job_service.Service + service jobService.Service } // NewHandler returns implement of job func NewHandler() (*handler, error) { - service, err := job_service.GetInstance() + service, err := jobService.GetInstance() if err != nil { return nil, errors.WithStack(err) } @@ -35,13 +35,13 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - if err := h.logs(w, ID(id)); err != nil { + if err := h.logs(w, job.ID(id)); err != nil { http.Error(w, fmt.Sprintf(" Error occurred: %s", err.Error()), http.StatusInternalServerError) return } } -func (h *handler) logs(w http.ResponseWriter, id ID) error { +func (h *handler) logs(w http.ResponseWriter, id job.ID) error { f, ok := w.(http.Flusher) if !ok { return errors.New("Streaming unsupported") diff --git a/presentation/controller/job/handler_test.go b/presentation/controller/job/handler_test.go index e930fbee..2edf8c27 100644 --- a/presentation/controller/job/handler_test.go +++ b/presentation/controller/job/handler_test.go @@ -2,11 +2,11 @@ package job_test import ( "context" - "github.com/duck8823/duci/application/service/job" + jobService "github.com/duck8823/duci/application/service/job" "github.com/duck8823/duci/application/service/job/mock_job" - mdlJob "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/internal/container" - "github.com/duck8823/duci/presentation/controller/job" + jobController "github.com/duck8823/duci/presentation/controller/job" "github.com/go-chi/chi" "github.com/golang/mock/gomock" "github.com/google/go-cmp/cmp" @@ -21,17 +21,17 @@ import ( func TestNewHandler(t *testing.T) { t.Run("when there is service in container", func(t *testing.T) { // given - service := new(job_service.Service) + service := new(jobService.Service) container.Override(service) defer container.Clear() // and - want := &job.Handler{} + want := &jobController.Handler{} defer want.SetService(*service)() // when - got, err := job.NewHandler() + got, err := jobController.NewHandler() // then if err != nil { @@ -40,7 +40,7 @@ func TestNewHandler(t *testing.T) { // and opts := cmp.Options{ - cmp.AllowUnexported(job.Handler{}), + cmp.AllowUnexported(jobController.Handler{}), } if !cmp.Equal(got, want, opts) { t.Errorf("must be equal, but %+v", cmp.Diff(got, want, opts)) @@ -52,7 +52,7 @@ func TestNewHandler(t *testing.T) { container.Clear() // when - got, err := job.NewHandler() + got, err := jobController.NewHandler() // then if err == nil { @@ -74,7 +74,7 @@ func TestHandler_ServeHTTP(t *testing.T) { req := httptest.NewRequest("GET", "/", nil) // and - id := mdlJob.ID(uuid.New()) + id := job.ID(uuid.New()) routeCtx := chi.NewRouteContext() routeCtx.URLParams.Add("uuid", uuid.UUID(id).String()) @@ -88,16 +88,16 @@ func TestHandler_ServeHTTP(t *testing.T) { service.EXPECT(). FindBy(gomock.Eq(id)). Times(1). - Return(&mdlJob.Job{ + Return(&job.Job{ ID: id, Finished: true, - Stream: []mdlJob.LogLine{ + Stream: []job.LogLine{ {Timestamp: time.Now(), Message: "Hello Test"}, }, }, nil) // and - sut := &job.Handler{} + sut := &jobController.Handler{} defer sut.SetService(service)() // when @@ -119,7 +119,7 @@ func TestHandler_ServeHTTP(t *testing.T) { req := httptest.NewRequest("GET", "/", nil).WithContext(ctx) // and - sut := &job.Handler{} + sut := &jobController.Handler{} // when sut.ServeHTTP(rec, req) @@ -136,7 +136,7 @@ func TestHandler_ServeHTTP(t *testing.T) { req := httptest.NewRequest("GET", "/", nil) // and - id := mdlJob.ID(uuid.New()) + id := job.ID(uuid.New()) routeCtx := chi.NewRouteContext() routeCtx.URLParams.Add("uuid", uuid.UUID(id).String()) @@ -153,7 +153,7 @@ func TestHandler_ServeHTTP(t *testing.T) { Return(nil, errors.New("test error")) // and - sut := &job.Handler{} + sut := &jobController.Handler{} defer sut.SetService(service)() // when diff --git a/presentation/controller/webhook/handler_test.go b/presentation/controller/webhook/handler_test.go index a52221d5..a542e6d1 100644 --- a/presentation/controller/webhook/handler_test.go +++ b/presentation/controller/webhook/handler_test.go @@ -5,7 +5,7 @@ import ( "github.com/docker/docker/pkg/ioutils" "github.com/duck8823/duci/application" "github.com/duck8823/duci/application/service/executor/mock_executor" - "github.com/duck8823/duci/application/service/job" + jobService "github.com/duck8823/duci/application/service/job" "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/job/target/github" "github.com/duck8823/duci/domain/model/job/target/github/mock_github" @@ -30,7 +30,7 @@ import ( func TestNewHandler(t *testing.T) { t.Run("when there are job service and github in container", func(t *testing.T) { // given - container.Override(new(job_service.Service)) + container.Override(new(jobService.Service)) container.Override(new(github.GitHub)) defer container.Clear() @@ -58,7 +58,7 @@ func TestNewHandler(t *testing.T) { { name: "without github", given: func() { - container.Override(new(job_service.Service)) + container.Override(new(jobService.Service)) }, }, } { diff --git a/presentation/router/router_test.go b/presentation/router/router_test.go index bebbce7c..a68aa767 100644 --- a/presentation/router/router_test.go +++ b/presentation/router/router_test.go @@ -12,7 +12,7 @@ import ( func TestNew(t *testing.T) { t.Run("with no error", func(t *testing.T) { // given - container.Override(new(job_service.Service)) + container.Override(new(job.Service)) container.Override(new(github.GitHub)) defer container.Clear() @@ -40,7 +40,7 @@ func TestNew(t *testing.T) { t.Run("with invalid environment variable for docker client", func(t *testing.T) { // given - container.Override(new(job_service.Service)) + container.Override(new(job.Service)) container.Override(new(github.GitHub)) defer container.Clear() From b713db09f9e3c897e338f4b214492a1ee485f315 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Sat, 5 Jan 2019 00:35:34 +0900 Subject: [PATCH 119/135] Remove dot import --- application/duci/duci.go | 6 +++--- application/service/job/service_impl.go | 28 ++++++++++++------------- domain/model/docker/docker_impl.go | 6 +++--- domain/model/docker/log.go | 14 ++++++------- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/application/duci/duci.go b/application/duci/duci.go index bd76d88e..bc2eff27 100644 --- a/application/duci/duci.go +++ b/application/duci/duci.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/duck8823/duci/application" "github.com/duck8823/duci/application/service/executor" - "github.com/duck8823/duci/application/service/job" + jobService "github.com/duck8823/duci/application/service/job" "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/job/target/github" "github.com/duck8823/duci/domain/model/runner" @@ -15,13 +15,13 @@ import ( type duci struct { executor.Executor - jobService job_service.Service + jobService jobService.Service github github.GitHub } // New returns duci instance func New() (executor.Executor, error) { - jobService, err := job_service.GetInstance() + jobService, err := jobService.GetInstance() if err != nil { return nil, errors.WithStack(err) } diff --git a/application/service/job/service_impl.go b/application/service/job/service_impl.go index 7e38e7f7..fe770576 100644 --- a/application/service/job/service_impl.go +++ b/application/service/job/service_impl.go @@ -1,19 +1,19 @@ package job import ( - . "github.com/duck8823/duci/domain/model/job" - . "github.com/duck8823/duci/infrastructure/job" + "github.com/duck8823/duci/domain/model/job" + jobDataSource "github.com/duck8823/duci/infrastructure/job" "github.com/duck8823/duci/internal/container" "github.com/pkg/errors" ) type serviceImpl struct { - repo Repository + repo job.Repository } // Initialize implementation of job service func Initialize(path string) error { - dataSource, err := NewDataSource(path) + dataSource, err := jobDataSource.NewDataSource(path) if err != nil { return errors.WithStack(err) } @@ -36,7 +36,7 @@ func GetInstance() (Service, error) { } // FindBy returns job is found by ID -func (s *serviceImpl) FindBy(id ID) (*Job, error) { +func (s *serviceImpl) FindBy(id job.ID) (*job.Job, error) { job, err := s.repo.FindBy(id) if err != nil { return nil, errors.WithStack(err) @@ -45,8 +45,8 @@ func (s *serviceImpl) FindBy(id ID) (*Job, error) { } // Start store empty job -func (s *serviceImpl) Start(id ID) error { - job := Job{ID: id, Finished: false} +func (s *serviceImpl) Start(id job.ID) error { + job := job.Job{ID: id, Finished: false} if err := s.repo.Save(job); err != nil { return errors.WithStack(err) } @@ -54,7 +54,7 @@ func (s *serviceImpl) Start(id ID) error { } // Append log to job -func (s *serviceImpl) Append(id ID, line LogLine) error { +func (s *serviceImpl) Append(id job.ID, line job.LogLine) error { job, err := s.findOrInitialize(id) if err != nil { return errors.WithStack(err) @@ -68,19 +68,19 @@ func (s *serviceImpl) Append(id ID, line LogLine) error { return nil } -func (s *serviceImpl) findOrInitialize(id ID) (*Job, error) { - job, err := s.repo.FindBy(id) - if err == NotFound { - return &Job{ID: id, Finished: false}, nil +func (s *serviceImpl) findOrInitialize(id job.ID) (*job.Job, error) { + j, err := s.repo.FindBy(id) + if err == job.NotFound { + return &job.Job{ID: id, Finished: false}, nil } else if err != nil { return nil, errors.WithStack(err) } - return job, nil + return j, nil } // Finish store finished job -func (s *serviceImpl) Finish(id ID) error { +func (s *serviceImpl) Finish(id job.ID) error { job, err := s.repo.FindBy(id) if err != nil { return errors.WithStack(err) diff --git a/domain/model/docker/docker_impl.go b/domain/model/docker/docker_impl.go index 7879d460..ecab7da7 100644 --- a/domain/model/docker/docker_impl.go +++ b/domain/model/docker/docker_impl.go @@ -5,7 +5,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" moby "github.com/docker/docker/client" - . "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/job" "github.com/pkg/errors" "io" ) @@ -24,7 +24,7 @@ func New() (Docker, error) { } // Build a docker image. -func (c *dockerImpl) Build(ctx context.Context, file io.Reader, tag Tag, dockerfile Dockerfile) (Log, error) { +func (c *dockerImpl) Build(ctx context.Context, file io.Reader, tag Tag, dockerfile Dockerfile) (job.Log, error) { opts := types.ImageBuildOptions{ Tags: []string{tag.String()}, Dockerfile: dockerfile.String(), @@ -39,7 +39,7 @@ func (c *dockerImpl) Build(ctx context.Context, file io.Reader, tag Tag, dockerf } // Run docker container with command. -func (c *dockerImpl) Run(ctx context.Context, opts RuntimeOptions, tag Tag, cmd Command) (ContainerID, Log, error) { +func (c *dockerImpl) Run(ctx context.Context, opts RuntimeOptions, tag Tag, cmd Command) (ContainerID, job.Log, error) { con, err := c.moby.ContainerCreate(ctx, &container.Config{ Image: tag.String(), Env: opts.Environments.Array(), diff --git a/domain/model/docker/log.go b/domain/model/docker/log.go index 35f9fe74..2ba004ea 100644 --- a/domain/model/docker/log.go +++ b/domain/model/docker/log.go @@ -5,7 +5,7 @@ import ( "bytes" "encoding/json" "fmt" - . "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/internal/logger" "github.com/pkg/errors" "io" @@ -19,12 +19,12 @@ type buildLogger struct { } // NewBuildLog return a instance of Log. -func NewBuildLog(r io.Reader) Log { +func NewBuildLog(r io.Reader) job.Log { return &buildLogger{bufio.NewReader(r)} } // ReadLine returns LogLine. -func (l *buildLogger) ReadLine() (*LogLine, error) { +func (l *buildLogger) ReadLine() (*job.LogLine, error) { for { line, _, err := l.reader.ReadLine() if err != nil { @@ -36,7 +36,7 @@ func (l *buildLogger) ReadLine() (*LogLine, error) { continue } - return &LogLine{Timestamp: now(), Message: msg}, nil + return &job.LogLine{Timestamp: now(), Message: msg}, nil } } @@ -45,12 +45,12 @@ type runLogger struct { } // NewRunLog returns a instance of Log -func NewRunLog(r io.Reader) Log { +func NewRunLog(r io.Reader) job.Log { return &runLogger{bufio.NewReader(r)} } // ReadLine returns LogLine. -func (l *runLogger) ReadLine() (*LogLine, error) { +func (l *runLogger) ReadLine() (*job.LogLine, error) { for { line, _, err := l.reader.ReadLine() if err != nil { @@ -66,7 +66,7 @@ func (l *runLogger) ReadLine() (*LogLine, error) { // prevent to CR progress := bytes.Split(msg, []byte{'\r'}) - return &LogLine{Timestamp: now(), Message: string(progress[0])}, nil + return &job.LogLine{Timestamp: now(), Message: string(progress[0])}, nil } } From 97156f2d479eb65df2531d7f52c809d81fe78d2d Mon Sep 17 00:00:00 2001 From: duck8823 Date: Sat, 5 Jan 2019 00:36:58 +0900 Subject: [PATCH 120/135] Fix comments --- domain/model/job/job.go | 2 +- internal/container/container.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/domain/model/job/job.go b/domain/model/job/job.go index 45f37c5d..147f59c6 100644 --- a/domain/model/job/job.go +++ b/domain/model/job/job.go @@ -35,7 +35,7 @@ func (j *Job) ToBytes() ([]byte, error) { // ID is the identifier of job type ID uuid.UUID -// Slice returns slice value +// ToSlice returns slice value func (i ID) ToSlice() []byte { return []byte(uuid.UUID(i).String()) } diff --git a/internal/container/container.go b/internal/container/container.go index 88785db6..c53e7f23 100644 --- a/internal/container/container.go +++ b/internal/container/container.go @@ -76,7 +76,7 @@ func Override(val interface{}) { instance.values[key] = val } -// Reset instances in container +// Clear instances in container // TODO: should not use in production code func Clear() { instance.values = make(map[string]interface{}) From cd7a947991024c548a6f40cc3dcd0ad2d8902e5d Mon Sep 17 00:00:00 2001 From: duck8823 Date: Sat, 5 Jan 2019 00:39:40 +0900 Subject: [PATCH 121/135] Fix error type name --- application/service/job/service_impl.go | 2 +- application/service/job/service_test.go | 2 +- domain/model/job/repository.go | 3 ++- infrastructure/job/data_source.go | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/application/service/job/service_impl.go b/application/service/job/service_impl.go index fe770576..c428652d 100644 --- a/application/service/job/service_impl.go +++ b/application/service/job/service_impl.go @@ -70,7 +70,7 @@ func (s *serviceImpl) Append(id job.ID, line job.LogLine) error { func (s *serviceImpl) findOrInitialize(id job.ID) (*job.Job, error) { j, err := s.repo.FindBy(id) - if err == job.NotFound { + if err == job.ErrNotFound { return &job.Job{ID: id, Finished: false}, nil } else if err != nil { return nil, errors.WithStack(err) diff --git a/application/service/job/service_test.go b/application/service/job/service_test.go index c5ceb7ba..0a588199 100644 --- a/application/service/job/service_test.go +++ b/application/service/job/service_test.go @@ -302,7 +302,7 @@ func TestServiceImpl_Append(t *testing.T) { repo.EXPECT(). FindBy(gomock.Eq(id)). Times(1). - Return(nil, job.NotFound) + Return(nil, job.ErrNotFound) repo.EXPECT(). Save(gomock.Eq(job.Job{ID: id, Finished: false, Stream: []job.LogLine{line}})). Times(1). diff --git a/domain/model/job/repository.go b/domain/model/job/repository.go index 072c8568..e059017a 100644 --- a/domain/model/job/repository.go +++ b/domain/model/job/repository.go @@ -2,7 +2,8 @@ package job import "errors" -var NotFound = errors.New("job not found") +// ErrNotFound represents a job not found error +var ErrNotFound = errors.New("job not found") // Repository is Job Repository type Repository interface { diff --git a/infrastructure/job/data_source.go b/infrastructure/job/data_source.go index 4b36377f..15cd9209 100644 --- a/infrastructure/job/data_source.go +++ b/infrastructure/job/data_source.go @@ -25,7 +25,7 @@ func NewDataSource(path string) (*dataSource, error) { func (d *dataSource) FindBy(id ID) (*Job, error) { data, err := d.db.Get(id.ToSlice(), nil) if err == leveldb.ErrNotFound { - return nil, NotFound + return nil, ErrNotFound } else if err != nil { return nil, errors.WithStack(err) } From 5a5c46d1bc03132239bc8f06eb5fe4009706bedc Mon Sep 17 00:00:00 2001 From: duck8823 Date: Sat, 5 Jan 2019 00:41:18 +0900 Subject: [PATCH 122/135] Add comments --- domain/model/job/target.go | 4 ++++ domain/model/job/target/github/status.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/domain/model/job/target.go b/domain/model/job/target.go index 3abc1aec..f4026d3c 100644 --- a/domain/model/job/target.go +++ b/domain/model/job/target.go @@ -1,13 +1,17 @@ package job +// Target represents build target type Target interface { Prepare() (WorkDir, Cleanup, error) } +// WorkDir is a working directory for build job type WorkDir string +// String returns string value func (w WorkDir) String() string { return string(w) } +// Cleanup function for workdir type Cleanup func() diff --git a/domain/model/job/target/github/status.go b/domain/model/job/target/github/status.go index b051c0ec..b1603c55 100644 --- a/domain/model/job/target/github/status.go +++ b/domain/model/job/target/github/status.go @@ -5,12 +5,15 @@ import "net/url" // State represents state of commit status type State string +// String returns string value func (s State) String() string { return string(s) } +// Description explain a commit status type Description string +// TrimmedString returns length-fixed description func (d Description) TrimmedString() string { if len(d) > 50 { return string([]rune(d)[:47]) + "..." @@ -29,6 +32,7 @@ const ( FAILURE State = "failure" ) +// CommitStatus represents a commit status type CommitStatus struct { TargetSource *TargetSource State State From e8364a93ff4b391af47ef26d862ff87c9a8508c5 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Sat, 5 Jan 2019 00:46:50 +0900 Subject: [PATCH 123/135] Rename types --- domain/model/job/target/git/export_test.go | 4 ++-- domain/model/job/target/git/git_test.go | 2 +- domain/model/job/target/git/http_client_test.go | 8 ++++---- domain/model/job/target/git/ssh_client_test.go | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/domain/model/job/target/git/export_test.go b/domain/model/job/target/git/export_test.go index 08d2488a..af2fa41f 100644 --- a/domain/model/job/target/git/export_test.go +++ b/domain/model/job/target/git/export_test.go @@ -7,9 +7,9 @@ import ( "time" ) -type HttpGitClient = httpGitClient +type HTTPGitClient = httpGitClient -type SshGitClient = sshGitClient +type SSHGitClient = sshGitClient type CloneLogger = cloneLogger diff --git a/domain/model/job/target/git/git_test.go b/domain/model/job/target/git/git_test.go index aad54b3b..f8cdc19c 100644 --- a/domain/model/job/target/git/git_test.go +++ b/domain/model/job/target/git/git_test.go @@ -28,7 +28,7 @@ func TestGetInstance(t *testing.T) { t.Run("when instance is not nil", func(t *testing.T) { // given - want := &git.HttpGitClient{} + want := &git.HTTPGitClient{} // and container.Override(want) diff --git a/domain/model/job/target/git/http_client_test.go b/domain/model/job/target/git/http_client_test.go index a0b718ad..cba13194 100644 --- a/domain/model/job/target/git/http_client_test.go +++ b/domain/model/job/target/git/http_client_test.go @@ -34,7 +34,7 @@ func TestInitializeWithHTTP(t *testing.T) { t.Run("when instance is not nil", func(t *testing.T) { // given - container.Override(&git.HttpGitClient{}) + container.Override(&git.HTTPGitClient{}) defer container.Clear() // when @@ -70,7 +70,7 @@ func TestHttpGitClient_Clone(t *testing.T) { Return("HEAD") // and - sut := &git.HttpGitClient{LogFunc: runner.NothingToDo} + sut := &git.HTTPGitClient{LogFunc: runner.NothingToDo} // expect if err := sut.Clone( @@ -128,7 +128,7 @@ func TestHttpGitClient_Clone(t *testing.T) { Return(hash) // and - sut := &git.HttpGitClient{LogFunc: runner.NothingToDo} + sut := &git.HTTPGitClient{LogFunc: runner.NothingToDo} // expect if err := sut.Clone(context.Background(), tmpDir, targetSrc); err != nil { @@ -170,7 +170,7 @@ func TestHttpGitClient_Clone(t *testing.T) { Return(plumbing.ZeroHash) // and - sut := &git.HttpGitClient{LogFunc: runner.NothingToDo} + sut := &git.HTTPGitClient{LogFunc: runner.NothingToDo} // expect if err := sut.Clone(context.Background(), tmpDir, targetSrc); err == nil { diff --git a/domain/model/job/target/git/ssh_client_test.go b/domain/model/job/target/git/ssh_client_test.go index 32ec406f..55d95114 100644 --- a/domain/model/job/target/git/ssh_client_test.go +++ b/domain/model/job/target/git/ssh_client_test.go @@ -97,7 +97,7 @@ func TestSshGitClient_Clone(t *testing.T) { Return("HEAD") // and - sut := &git.SshGitClient{LogFunc: runner.NothingToDo} + sut := &git.SSHGitClient{LogFunc: runner.NothingToDo} // expect if err := sut.Clone( @@ -154,7 +154,7 @@ func TestSshGitClient_Clone(t *testing.T) { Return(hash) // and - sut := &git.SshGitClient{LogFunc: runner.NothingToDo} + sut := &git.SSHGitClient{LogFunc: runner.NothingToDo} // expect if err := sut.Clone(context.Background(), tmpDir, targetSrc); err != nil { @@ -196,7 +196,7 @@ func TestSshGitClient_Clone(t *testing.T) { Return(plumbing.ZeroHash) // and - sut := &git.SshGitClient{LogFunc: runner.NothingToDo} + sut := &git.SSHGitClient{LogFunc: runner.NothingToDo} // expect if err := sut.Clone(context.Background(), tmpDir, targetSrc); err == nil { From c1ee4acdcbbd8dd3f9358317a40d8bc73c5d26c9 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Sat, 5 Jan 2019 00:50:09 +0900 Subject: [PATCH 124/135] Change to exported types --- domain/model/runner/builder.go | 11 ++++++----- domain/model/runner/export_test.go | 8 +++----- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/domain/model/runner/builder.go b/domain/model/runner/builder.go index 1a66b9e0..9e11d6ba 100644 --- a/domain/model/runner/builder.go +++ b/domain/model/runner/builder.go @@ -4,25 +4,26 @@ import ( "github.com/duck8823/duci/domain/model/docker" ) -type builder struct { +// Builder represents a builder of docker runner +type Builder struct { docker docker.Docker logFunc LogFunc } // DefaultDockerRunnerBuilder create new builder of docker runner -func DefaultDockerRunnerBuilder() *builder { +func DefaultDockerRunnerBuilder() *Builder { cli, _ := docker.New() - return &builder{docker: cli, logFunc: NothingToDo} + return &Builder{docker: cli, logFunc: NothingToDo} } // LogFunc append a LogFunc -func (b *builder) LogFunc(f LogFunc) *builder { +func (b *Builder) LogFunc(f LogFunc) *Builder { b.logFunc = f return b } // Build returns a docker runner -func (b *builder) Build() *dockerRunnerImpl { +func (b *Builder) Build() DockerRunner { return &dockerRunnerImpl{ docker: b.docker, logFunc: b.logFunc, diff --git a/domain/model/runner/export_test.go b/domain/model/runner/export_test.go index 02c9619f..915769b0 100644 --- a/domain/model/runner/export_test.go +++ b/domain/model/runner/export_test.go @@ -2,9 +2,7 @@ package runner import "github.com/duck8823/duci/domain/model/docker" -type Builder = builder - -func (b *builder) SetDocker(docker docker.Docker) (reset func()) { +func (b *Builder) SetDocker(docker docker.Docker) (reset func()) { tmp := b.docker b.docker = docker return func() { @@ -12,11 +10,11 @@ func (b *builder) SetDocker(docker docker.Docker) (reset func()) { } } -func (b *builder) GetLogFunc() LogFunc { +func (b *Builder) GetLogFunc() LogFunc { return b.logFunc } -func (b *builder) SetLogFunc(logFunc LogFunc) (reset func()) { +func (b *Builder) SetLogFunc(logFunc LogFunc) (reset func()) { tmp := b.logFunc b.logFunc = logFunc return func() { From 1779a86df189e9dea35aff48699c5ee6644f83e7 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Sat, 5 Jan 2019 00:51:17 +0900 Subject: [PATCH 125/135] Remove dot import --- domain/model/runner/helper.go | 10 +++++----- infrastructure/job/data_source.go | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/domain/model/runner/helper.go b/domain/model/runner/helper.go index ee28eb07..f518fd0b 100644 --- a/domain/model/runner/helper.go +++ b/domain/model/runner/helper.go @@ -2,7 +2,7 @@ package runner import ( "bytes" - . "github.com/duck8823/duci/domain/model/docker" + "github.com/duck8823/duci/domain/model/docker" "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/infrastructure/archive/tar" "github.com/pkg/errors" @@ -30,12 +30,12 @@ func createTarball(workDir job.WorkDir) (*os.File, error) { } // dockerfilePath returns a path to dockerfile for duci using -func dockerfilePath(workDir job.WorkDir) Dockerfile { +func dockerfilePath(workDir job.WorkDir) docker.Dockerfile { dockerfile := "./Dockerfile" if exists(filepath.Join(workDir.String(), ".duci/Dockerfile")) { dockerfile = ".duci/Dockerfile" } - return Dockerfile(dockerfile) + return docker.Dockerfile(dockerfile) } // exists indicates whether the file exists @@ -45,8 +45,8 @@ func exists(name string) bool { } // runtimeOptions parses a config.yml and returns a docker runtime options -func runtimeOptions(workDir job.WorkDir) (RuntimeOptions, error) { - var opts RuntimeOptions +func runtimeOptions(workDir job.WorkDir) (docker.RuntimeOptions, error) { + var opts docker.RuntimeOptions if !exists(filepath.Join(workDir.String(), ".duci/config.yml")) { return opts, nil diff --git a/infrastructure/job/data_source.go b/infrastructure/job/data_source.go index 15cd9209..3a3161c9 100644 --- a/infrastructure/job/data_source.go +++ b/infrastructure/job/data_source.go @@ -3,7 +3,7 @@ package job import ( "bytes" "encoding/json" - . "github.com/duck8823/duci/domain/model/job" + "github.com/duck8823/duci/domain/model/job" "github.com/pkg/errors" "github.com/syndtr/goleveldb/leveldb" ) @@ -22,15 +22,15 @@ func NewDataSource(path string) (*dataSource, error) { } // FindBy returns job found by ID -func (d *dataSource) FindBy(id ID) (*Job, error) { +func (d *dataSource) FindBy(id job.ID) (*job.Job, error) { data, err := d.db.Get(id.ToSlice(), nil) if err == leveldb.ErrNotFound { - return nil, ErrNotFound + return nil, job.ErrNotFound } else if err != nil { return nil, errors.WithStack(err) } - job := &Job{} + job := &job.Job{} if err := json.NewDecoder(bytes.NewReader(data)).Decode(job); err != nil { return nil, errors.WithStack(err) } @@ -39,7 +39,7 @@ func (d *dataSource) FindBy(id ID) (*Job, error) { } // Save store job to data source -func (d *dataSource) Save(job Job) error { +func (d *dataSource) Save(job job.Job) error { data, err := job.ToBytes() if err != nil { return errors.WithStack(err) From c0ef51e146debc51e08da343c6f54ec3f04950f6 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Sat, 5 Jan 2019 00:52:28 +0900 Subject: [PATCH 126/135] Add comment --- internal/logger/logger.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/logger/logger.go b/internal/logger/logger.go index fa9a7fa0..c5e8c4b8 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -5,6 +5,7 @@ import ( "os" ) +// Error print stack to stderr func Error(err error) { _, _ = os.Stderr.WriteString(fmt.Sprintf("%+v", err)) } From 55929e6092c72df2f0cbe8a27607835086588339 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Sat, 5 Jan 2019 00:54:51 +0900 Subject: [PATCH 127/135] Change return type to exported it --- infrastructure/job/data_source.go | 2 +- presentation/controller/health/handler.go | 2 +- presentation/controller/job/handler.go | 2 +- presentation/controller/webhook/handler.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/infrastructure/job/data_source.go b/infrastructure/job/data_source.go index 3a3161c9..254a023b 100644 --- a/infrastructure/job/data_source.go +++ b/infrastructure/job/data_source.go @@ -13,7 +13,7 @@ type dataSource struct { } // NewDataSource returns job data source -func NewDataSource(path string) (*dataSource, error) { +func NewDataSource(path string) (job.Repository, error) { db, err := leveldb.OpenFile(path, nil) if err != nil { return nil, errors.WithStack(err) diff --git a/presentation/controller/health/handler.go b/presentation/controller/health/handler.go index a2e2586e..24963fc4 100644 --- a/presentation/controller/health/handler.go +++ b/presentation/controller/health/handler.go @@ -11,7 +11,7 @@ type handler struct { } // NewHandler returns implement of health check handler -func NewHandler() (*handler, error) { +func NewHandler() (http.Handler, error) { docker, err := docker.New() if err != nil { return nil, errors.WithStack(err) diff --git a/presentation/controller/job/handler.go b/presentation/controller/job/handler.go index 0ae718b9..8ac9c5c7 100644 --- a/presentation/controller/job/handler.go +++ b/presentation/controller/job/handler.go @@ -17,7 +17,7 @@ type handler struct { } // NewHandler returns implement of job -func NewHandler() (*handler, error) { +func NewHandler() (http.Handler, error) { service, err := jobService.GetInstance() if err != nil { return nil, errors.WithStack(err) diff --git a/presentation/controller/webhook/handler.go b/presentation/controller/webhook/handler.go index 3f823805..2843cb28 100644 --- a/presentation/controller/webhook/handler.go +++ b/presentation/controller/webhook/handler.go @@ -24,7 +24,7 @@ type handler struct { } // NewHandler returns a implement of webhook handler -func NewHandler() (*handler, error) { +func NewHandler() (http.Handler, error) { executor, err := duci.New() if err != nil { return nil, errors.WithStack(err) From bcad5bfd3f2df62e1d59cc87b635a54ef9ec4416 Mon Sep 17 00:00:00 2001 From: duck8823 Date: Sat, 5 Jan 2019 00:55:55 +0900 Subject: [PATCH 128/135] Rename error variable --- presentation/controller/webhook/handler.go | 6 +++--- presentation/controller/webhook/phrase.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/presentation/controller/webhook/handler.go b/presentation/controller/webhook/handler.go index 2843cb28..795a1e92 100644 --- a/presentation/controller/webhook/handler.go +++ b/presentation/controller/webhook/handler.go @@ -16,8 +16,8 @@ import ( "net/http" ) -// SkipBuild represents error of skip build -var SkipBuild = errors.New("Skip build") +// ErrSkipBuild represents error of skip build +var ErrSkipBuild = errors.New("Skip build") type handler struct { executor executor.Executor @@ -116,7 +116,7 @@ func (h *handler) IssueCommentEvent(w http.ResponseWriter, r *http.Request) { } phrase, err := extractBuildPhrase(event.GetComment().GetBody()) - if err == SkipBuild { + if err == ErrSkipBuild { w.WriteHeader(http.StatusOK) if _, err := w.Write([]byte("{\"message\":\"skip build\"}")); err != nil { logger.Error(err) diff --git a/presentation/controller/webhook/phrase.go b/presentation/controller/webhook/phrase.go index ed349d3f..db91d246 100644 --- a/presentation/controller/webhook/phrase.go +++ b/presentation/controller/webhook/phrase.go @@ -15,7 +15,7 @@ func (p phrase) Command() docker.Command { func extractBuildPhrase(comment string) (phrase, error) { if !regexp.MustCompile(`^ci\s+[^\\s]+`).Match([]byte(comment)) { - return "", SkipBuild + return "", ErrSkipBuild } phrase := phrase(regexp.MustCompile(`^ci\s+`).ReplaceAllString(comment, "")) return phrase, nil From 8a809ce416a79262825eadadfa69274bc360eb7e Mon Sep 17 00:00:00 2001 From: duck8823 Date: Sat, 5 Jan 2019 01:36:33 +0900 Subject: [PATCH 129/135] Fix git client using ssh --- application/export_test.go | 36 +++++++- application/initialize.go | 19 +++- application/initialize_test.go | 164 ++++++++++++++++++++++++++------- 3 files changed, 182 insertions(+), 37 deletions(-) diff --git a/application/export_test.go b/application/export_test.go index b0e74fb4..eb5ca9f6 100644 --- a/application/export_test.go +++ b/application/export_test.go @@ -1,6 +1,14 @@ package application -import "github.com/tcnksm/go-latest" +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "github.com/tcnksm/go-latest" + "os" + "testing" +) type MaskString = maskString @@ -31,3 +39,29 @@ func TrimSuffix(tag string) string { func GetCtxKey() *string { return &ctxKey } + +func GenerateSSHKey(t *testing.T, path string) { + t.Helper() + + key, err := rsa.GenerateKey(rand.Reader, 256) + if err != nil { + t.Fatalf("error occur: %+v", err) + } + + if err := key.Validate(); err != nil { + t.Fatalf("error occur: %+v", err) + } + + f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0400) + if err != nil { + t.Fatalf("error occur: %+v", err) + } + + if _, err := f.Write(pem.EncodeToMemory(&pem.Block{ + Type: "RSA PRIVATE KEY", + Headers: nil, + Bytes: x509.MarshalPKCS1PrivateKey(key), + })); err != nil { + t.Fatalf("error occur: %+v", err) + } +} diff --git a/application/initialize.go b/application/initialize.go index 91092578..96f94c65 100644 --- a/application/initialize.go +++ b/application/initialize.go @@ -11,12 +11,15 @@ import ( // Initialize singleton instances that are needed by application func Initialize() error { - if err := git.InitializeWithHTTP(func(ctx context.Context, log job.Log) { - for line, err := log.ReadLine(); err == nil; line, err = log.ReadLine() { - println(line.Message) + switch { + case len(Config.GitHub.SSHKeyPath) == 0: + if err := git.InitializeWithHTTP(printLog); err != nil { + return errors.WithStack(err) + } + default: + if err := git.InitializeWithSSH(Config.GitHub.SSHKeyPath, printLog); err != nil { + return errors.WithStack(err) } - }); err != nil { - return errors.WithStack(err) } if err := github.Initialize(Config.GitHub.APIToken.String()); err != nil { @@ -28,3 +31,9 @@ func Initialize() error { } return nil } + +func printLog(_ context.Context, log job.Log) { + for line, err := log.ReadLine(); err == nil; line, err = log.ReadLine() { + println(line.Message) + } +} diff --git a/application/initialize_test.go b/application/initialize_test.go index a537365c..25fa8cfd 100644 --- a/application/initialize_test.go +++ b/application/initialize_test.go @@ -14,42 +14,130 @@ import ( func TestInitialize(t *testing.T) { t.Run("when singleton container is empty", func(t *testing.T) { - // given - application.Config.Server.DatabasePath = path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) - - // and - container.Clear() - - // when - err := application.Initialize() - - // then - if err != nil { - t.Errorf("error must be nil, but got %+v", err) - } - - // and - git := new(git.Git) - if err := container.Get(git); err != nil { - t.Errorf("error must be nil, but got %+v", err) - } - - // and - github := new(github.GitHub) - if err := container.Get(github); err != nil { - t.Errorf("error must be nil, but got %+v", err) - } - - // and - jobService := new(job.Service) - if err := container.Get(jobService); err != nil { - t.Errorf("error must be nil, but got %+v", err) - } + t.Run("without ssh key path", func(t *testing.T) { + // given + sshKeyPath := application.Config.GitHub.SSHKeyPath + databasePath := application.Config.Server.DatabasePath + application.Config.GitHub.SSHKeyPath = "" + application.Config.Server.DatabasePath = path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + defer func() { + application.Config.GitHub.SSHKeyPath = sshKeyPath + application.Config.Server.DatabasePath = databasePath + }() + + // and + container.Clear() + + // when + err := application.Initialize() + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + git := new(git.Git) + if err := container.Get(git); err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + github := new(github.GitHub) + if err := container.Get(github); err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + jobService := new(job.Service) + if err := container.Get(jobService); err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + }) + + t.Run("with correct ssh key path", func(t *testing.T) { + // given + dir := path.Join(os.TempDir(), random.String(16)) + if err := os.MkdirAll(dir, 0700); err != nil { + t.Fatalf("error occur: %+v", err) + } + keyPath := path.Join(dir, "id_rsa") + application.GenerateSSHKey(t, keyPath) + + // and + sshKeyPath := application.Config.GitHub.SSHKeyPath + databasePath := application.Config.Server.DatabasePath + application.Config.GitHub.SSHKeyPath = keyPath + application.Config.Server.DatabasePath = path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + defer func() { + application.Config.GitHub.SSHKeyPath = sshKeyPath + application.Config.Server.DatabasePath = databasePath + }() + + // and + container.Clear() + + // when + err := application.Initialize() + + // then + if err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + git := new(git.Git) + if err := container.Get(git); err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + github := new(github.GitHub) + if err := container.Get(github); err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + + // and + jobService := new(job.Service) + if err := container.Get(jobService); err != nil { + t.Errorf("error must be nil, but got %+v", err) + } + }) + + t.Run("with invalid key path", func(t *testing.T) { + // given + sshKeyPath := application.Config.GitHub.SSHKeyPath + databasePath := application.Config.Server.DatabasePath + application.Config.GitHub.SSHKeyPath = "/path/to/invalid/key/path" + application.Config.Server.DatabasePath = path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + defer func() { + application.Config.GitHub.SSHKeyPath = sshKeyPath + application.Config.Server.DatabasePath = databasePath + }() + + // and + container.Clear() + + // when + err := application.Initialize() + + // then + if err == nil { + t.Error("error must not be nil") + } + }) }) t.Run("when singleton container contains Git instance", func(t *testing.T) { // given + sshKeyPath := application.Config.GitHub.SSHKeyPath + databasePath := application.Config.Server.DatabasePath + application.Config.GitHub.SSHKeyPath = "" application.Config.Server.DatabasePath = path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + defer func() { + application.Config.GitHub.SSHKeyPath = sshKeyPath + application.Config.Server.DatabasePath = databasePath + }() // and container.Override(new(git.Git)) @@ -66,7 +154,14 @@ func TestInitialize(t *testing.T) { t.Run("when singleton container contains GitHub instance", func(t *testing.T) { // given + sshKeyPath := application.Config.GitHub.SSHKeyPath + databasePath := application.Config.Server.DatabasePath + application.Config.GitHub.SSHKeyPath = "" application.Config.Server.DatabasePath = path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + defer func() { + application.Config.GitHub.SSHKeyPath = sshKeyPath + application.Config.Server.DatabasePath = databasePath + }() // and container.Override(new(github.GitHub)) @@ -83,7 +178,14 @@ func TestInitialize(t *testing.T) { t.Run("when singleton container contains JobService instance", func(t *testing.T) { // given + sshKeyPath := application.Config.GitHub.SSHKeyPath + databasePath := application.Config.Server.DatabasePath + application.Config.GitHub.SSHKeyPath = "" application.Config.Server.DatabasePath = path.Join(os.TempDir(), random.String(16, random.Alphanumeric)) + defer func() { + application.Config.GitHub.SSHKeyPath = sshKeyPath + application.Config.Server.DatabasePath = databasePath + }() // and container.Override(new(job.Service)) From 134c05d884440502b1613e1ce67cd21b6a97bc2f Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 5 Jan 2019 14:27:49 +0900 Subject: [PATCH 130/135] Fix target url of commit status --- presentation/controller/webhook/handler.go | 8 ++++++-- presentation/controller/webhook/handler_test.go | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/presentation/controller/webhook/handler.go b/presentation/controller/webhook/handler.go index 795a1e92..4f42801c 100644 --- a/presentation/controller/webhook/handler.go +++ b/presentation/controller/webhook/handler.go @@ -62,6 +62,8 @@ func (h *handler) PushEvent(w http.ResponseWriter, r *http.Request) { return } + targetURL := targetURL(r) + targetURL.Path = fmt.Sprintf("/logs/%s", reqID.ToSlice()) ctx := application.ContextWithJob(context.Background(), &application.BuildJob{ ID: reqID, TargetSource: &github.TargetSource{ @@ -70,7 +72,7 @@ func (h *handler) PushEvent(w http.ResponseWriter, r *http.Request) { SHA: plumbing.NewHash(event.GetHead()), }, TaskName: fmt.Sprintf("%s/push", application.Name), - TargetURL: targetURL(r), + TargetURL: targetURL, }) tgt := &target.GitHub{ @@ -127,6 +129,8 @@ func (h *handler) IssueCommentEvent(w http.ResponseWriter, r *http.Request) { return } + targetURL := targetURL(r) + targetURL.Path = fmt.Sprintf("/logs/%s", reqID.ToSlice()) ctx := application.ContextWithJob(context.Background(), &application.BuildJob{ ID: reqID, TargetSource: &github.TargetSource{ @@ -135,7 +139,7 @@ func (h *handler) IssueCommentEvent(w http.ResponseWriter, r *http.Request) { SHA: plumbing.NewHash(pnt.GetHead()), }, TaskName: fmt.Sprintf("%s/pr/%s", application.Name, phrase.Command().Slice()[0]), - TargetURL: targetURL(r), + TargetURL: targetURL, }) tgt := &target.GitHub{ diff --git a/presentation/controller/webhook/handler_test.go b/presentation/controller/webhook/handler_test.go index a542e6d1..267f04ee 100644 --- a/presentation/controller/webhook/handler_test.go +++ b/presentation/controller/webhook/handler_test.go @@ -245,7 +245,7 @@ func TestHandler_PushEvent(t *testing.T) { SHA: plumbing.ZeroHash, }, TaskName: "duci/push", - TargetURL: webhook.URLMust(url.Parse("http://example.com/")), + TargetURL: webhook.URLMust(url.Parse("http://example.com/logs/72d3162e-cc78-11e3-81ab-4c9367dc0958")), } opt := webhook.CmpOptsAllowFields(go_github.PushEventRepository{}, "ID", "FullName", "SSHURL", "CloneURL") @@ -412,7 +412,7 @@ func TestHandler_IssueCommentEvent_Normal(t *testing.T) { SHA: plumbing.NewHash("aa218f56b14c9653891f9e74264a383fa43fefbd"), }, TaskName: "duci/pr/build", - TargetURL: webhook.URLMust(url.Parse("http://example.com/")), + TargetURL: webhook.URLMust(url.Parse("http://example.com/logs/72d3162e-cc78-11e3-81ab-4c9367dc0958")), } opt := webhook.CmpOptsAllowFields(go_github.Repository{}, "ID", "FullName", "SSHURL", "CloneURL") From 8580b250a3e4841c4654a4315d0a22e75a9788a3 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 5 Jan 2019 15:14:56 +0900 Subject: [PATCH 131/135] Fix json key of log line --- domain/model/job/log.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/domain/model/job/log.go b/domain/model/job/log.go index e49ef58d..22f9ee11 100644 --- a/domain/model/job/log.go +++ b/domain/model/job/log.go @@ -9,6 +9,6 @@ type Log interface { // LogLine stores timestamp and message. type LogLine struct { - Timestamp time.Time - Message string + Timestamp time.Time `json:"time"` + Message string `json:"message"` } From 2b0284b30015408286dd13513637857c785aa1e1 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 5 Jan 2019 16:09:04 +0900 Subject: [PATCH 132/135] Fix ref when push --- domain/model/job/log.go | 2 +- domain/model/job/target/github.go | 3 +-- presentation/controller/webhook/handler_test.go | 4 ++-- presentation/controller/webhook/helper.go | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/domain/model/job/log.go b/domain/model/job/log.go index 22f9ee11..495650af 100644 --- a/domain/model/job/log.go +++ b/domain/model/job/log.go @@ -10,5 +10,5 @@ type Log interface { // LogLine stores timestamp and message. type LogLine struct { Timestamp time.Time `json:"time"` - Message string `json:"message"` + Message string `json:"message"` } diff --git a/domain/model/job/target/github.go b/domain/model/job/target/github.go index ee2c1645..675a4530 100644 --- a/domain/model/job/target/github.go +++ b/domain/model/job/target/github.go @@ -2,7 +2,6 @@ package target import ( "context" - "fmt" "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/job/target/git" "github.com/duck8823/duci/domain/model/job/target/github" @@ -33,7 +32,7 @@ func (g *GitHub) Prepare() (job.WorkDir, job.Cleanup, error) { if err := git.Clone(context.Background(), tmpDir, &github.TargetSource{ Repository: g.Repo, - Ref: fmt.Sprintf("refs/heads/%s", g.Point.GetRef()), + Ref: g.Point.GetRef(), SHA: plumbing.NewHash(g.Point.GetHead()), }); err != nil { return "", cleanupFunc(tmpDir), errors.WithStack(err) diff --git a/presentation/controller/webhook/handler_test.go b/presentation/controller/webhook/handler_test.go index 267f04ee..12b48260 100644 --- a/presentation/controller/webhook/handler_test.go +++ b/presentation/controller/webhook/handler_test.go @@ -382,7 +382,7 @@ func TestHandler_IssueCommentEvent_Normal(t *testing.T) { Times(1). Return(&go_github.PullRequest{ Head: &go_github.PullRequestBranch{ - Ref: go_github.String("refs/test/dummy"), + Ref: go_github.String("dummy"), SHA: go_github.String("aa218f56b14c9653891f9e74264a383fa43fefbd"), }, }, nil) @@ -408,7 +408,7 @@ func TestHandler_IssueCommentEvent_Normal(t *testing.T) { SSHURL: go_github.String("git@github.com:Codertocat/Hello-World.git"), CloneURL: go_github.String("https://github.com/Codertocat/Hello-World.git"), }, - Ref: "refs/test/dummy", + Ref: "refs/heads/dummy", SHA: plumbing.NewHash("aa218f56b14c9653891f9e74264a383fa43fefbd"), }, TaskName: "duci/pr/build", diff --git a/presentation/controller/webhook/helper.go b/presentation/controller/webhook/helper.go index cdc2fd86..027682d1 100644 --- a/presentation/controller/webhook/helper.go +++ b/presentation/controller/webhook/helper.go @@ -46,7 +46,7 @@ func targetPoint(event *go_github.IssueCommentEvent) (github.TargetPoint, error) } return &github.SimpleTargetPoint{ - Ref: pr.GetHead().GetRef(), + Ref: fmt.Sprintf("refs/heads/%s", pr.GetHead().GetRef()), SHA: pr.GetHead().GetSHA(), }, nil } From 172fe638d5388c8b6c67f27f64f8ff11ea062236 Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 5 Jan 2019 17:25:19 +0900 Subject: [PATCH 133/135] Add debug print in error --- application/duci/duci.go | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/application/duci/duci.go b/application/duci/duci.go index bc2eff27..7d5457c9 100644 --- a/application/duci/duci.go +++ b/application/duci/duci.go @@ -9,6 +9,7 @@ import ( "github.com/duck8823/duci/domain/model/job" "github.com/duck8823/duci/domain/model/job/target/github" "github.com/duck8823/duci/domain/model/runner" + "github.com/duck8823/duci/internal/logger" "github.com/pkg/errors" "time" ) @@ -55,16 +56,20 @@ func (d *duci) Start(ctx context.Context) { return } if err := d.jobService.Start(buildJob.ID); err != nil { - _ = d.jobService.Append(buildJob.ID, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) + if err := d.jobService.Append(buildJob.ID, job.LogLine{Timestamp: time.Now(), Message: err.Error()}); err != nil { + logger.Error(err) + } return } - _ = d.github.CreateCommitStatus(ctx, github.CommitStatus{ + if err := d.github.CreateCommitStatus(ctx, github.CommitStatus{ TargetSource: buildJob.TargetSource, State: github.PENDING, Description: "pending", Context: buildJob.TaskName, TargetURL: buildJob.TargetURL, - }) + }); err != nil { + logger.Error(err) + } } // AppendLog is a function that print and store log @@ -76,7 +81,9 @@ func (d *duci) AppendLog(ctx context.Context, log job.Log) { } for line, err := log.ReadLine(); err == nil; line, err = log.ReadLine() { println(line.Message) - _ = d.jobService.Append(buildJob.ID, *line) + if err := d.jobService.Append(buildJob.ID, *line); err != nil { + logger.Error(err) + } } } @@ -88,34 +95,42 @@ func (d *duci) End(ctx context.Context, e error) { return } if err := d.jobService.Finish(buildJob.ID); err != nil { - _ = d.jobService.Append(buildJob.ID, job.LogLine{Timestamp: time.Now(), Message: err.Error()}) + if err := d.jobService.Append(buildJob.ID, job.LogLine{Timestamp: time.Now(), Message: err.Error()}); err != nil { + logger.Error(err) + } return } switch e { case nil: - _ = d.github.CreateCommitStatus(ctx, github.CommitStatus{ + if err := d.github.CreateCommitStatus(ctx, github.CommitStatus{ TargetSource: buildJob.TargetSource, State: github.SUCCESS, Description: "success", Context: buildJob.TaskName, TargetURL: buildJob.TargetURL, - }) + }); err != nil { + logger.Error(err) + } case runner.ErrFailure: - _ = d.github.CreateCommitStatus(ctx, github.CommitStatus{ + if err := d.github.CreateCommitStatus(ctx, github.CommitStatus{ TargetSource: buildJob.TargetSource, State: github.FAILURE, Description: "failure", Context: buildJob.TaskName, TargetURL: buildJob.TargetURL, - }) + }); err != nil { + logger.Error(err) + } default: - _ = d.github.CreateCommitStatus(ctx, github.CommitStatus{ + if err := d.github.CreateCommitStatus(ctx, github.CommitStatus{ TargetSource: buildJob.TargetSource, State: github.ERROR, Description: github.Description(fmt.Sprintf("error: %s", e.Error())), Context: buildJob.TaskName, TargetURL: buildJob.TargetURL, - }) + }); err != nil { + logger.Error(err) + } } } From 6c4af7a89d19f5a2428232f04efd40776e31e6bf Mon Sep 17 00:00:00 2001 From: shunsuke maeda Date: Sat, 5 Jan 2019 17:44:24 +0900 Subject: [PATCH 134/135] Fix sha on push --- .idea/httpRequests/http-requests-log.http | 530 +++++++++++++++++++++ presentation/controller/webhook/handler.go | 2 +- 2 files changed, 531 insertions(+), 1 deletion(-) create mode 100644 .idea/httpRequests/http-requests-log.http diff --git a/.idea/httpRequests/http-requests-log.http b/.idea/httpRequests/http-requests-log.http new file mode 100644 index 00000000..732b887c --- /dev/null +++ b/.idea/httpRequests/http-requests-log.http @@ -0,0 +1,530 @@ +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: push +X-GitHub-Delivery: d9e8d758-10b2-11e9-8f64-85498fa56ba1 + +{ "ref": "refs/heads/rearchitecture", "before": "9fbed8c094a6a07fbe460367b20f5ababe245ba5", "after": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "created": false, "deleted": false, "forced": true, "base_ref": null, "compare": "https://github.com/duck8823/duci/compare/9fbed8c094a6...8580b250a3e4", "commits": [ { "id": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "tree_id": "b93ebeaa9cd8a3dbe826b1b640f0c42609f72b6f", "distinct": true, "message": "Fix json key of log line", "timestamp": "2019-01-05T15:26:04+09:00", "url": "https://github.com/duck8823/duci/commit/8580b250a3e4841c4654a4315d0a22e75a9788a3", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/log.go" ] } ], "head_commit": { "id": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "tree_id": "b93ebeaa9cd8a3dbe826b1b640f0c42609f72b6f", "distinct": true, "message": "Fix json key of log line", "timestamp": "2019-01-05T15:26:04+09:00", "url": "https://github.com/duck8823/duci/commit/8580b250a3e4841c4654a4315d0a22e75a9788a3", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/log.go" ] }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "name": "duck8823", "email": "duck8823@gmail.com", "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://github.com/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": 1522547462, "updated_at": "2018-12-28T21:05:40Z", "pushed_at": 1546669595, "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 657, "stargazers_count": 16, "watchers_count": 16, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 16, "default_branch": "master", "stargazers": 16, "master_branch": "master" }, "pusher": { "name": "duck8823", "email": "duck8823@gmail.com" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: push +X-GitHub-Delivery: d9e8d758-10b2-11e9-8f64-85498fa56ba1 + +{ "ref": "refs/heads/rearchitecture", "before": "9fbed8c094a6a07fbe460367b20f5ababe245ba5", "after": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "created": false, "deleted": false, "forced": true, "base_ref": null, "compare": "https://github.com/duck8823/duci/compare/9fbed8c094a6...8580b250a3e4", "commits": [ { "id": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "tree_id": "b93ebeaa9cd8a3dbe826b1b640f0c42609f72b6f", "distinct": true, "message": "Fix json key of log line", "timestamp": "2019-01-05T15:26:04+09:00", "url": "https://github.com/duck8823/duci/commit/8580b250a3e4841c4654a4315d0a22e75a9788a3", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/log.go" ] } ], "head_commit": { "id": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "tree_id": "b93ebeaa9cd8a3dbe826b1b640f0c42609f72b6f", "distinct": true, "message": "Fix json key of log line", "timestamp": "2019-01-05T15:26:04+09:00", "url": "https://github.com/duck8823/duci/commit/8580b250a3e4841c4654a4315d0a22e75a9788a3", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/log.go" ] }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "name": "duck8823", "email": "duck8823@gmail.com", "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://github.com/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": 1522547462, "updated_at": "2018-12-28T21:05:40Z", "pushed_at": 1546669595, "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 657, "stargazers_count": 16, "watchers_count": 16, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 16, "default_branch": "master", "stargazers": 16, "master_branch": "master" }, "pusher": { "name": "duck8823", "email": "duck8823@gmail.com" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: push +X-GitHub-Delivery: d9e8d758-10b2-11e9-8f64-85498fa56ba1 + +{ "ref": "refs/heads/rearchitecture", "before": "9fbed8c094a6a07fbe460367b20f5ababe245ba5", "after": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "created": false, "deleted": false, "forced": true, "base_ref": null, "compare": "https://github.com/duck8823/duci/compare/9fbed8c094a6...8580b250a3e4", "commits": [ { "id": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "tree_id": "b93ebeaa9cd8a3dbe826b1b640f0c42609f72b6f", "distinct": true, "message": "Fix json key of log line", "timestamp": "2019-01-05T15:26:04+09:00", "url": "https://github.com/duck8823/duci/commit/8580b250a3e4841c4654a4315d0a22e75a9788a3", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/log.go" ] } ], "head_commit": { "id": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "tree_id": "b93ebeaa9cd8a3dbe826b1b640f0c42609f72b6f", "distinct": true, "message": "Fix json key of log line", "timestamp": "2019-01-05T15:26:04+09:00", "url": "https://github.com/duck8823/duci/commit/8580b250a3e4841c4654a4315d0a22e75a9788a3", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/log.go" ] }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "name": "duck8823", "email": "duck8823@gmail.com", "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://github.com/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": 1522547462, "updated_at": "2018-12-28T21:05:40Z", "pushed_at": 1546669595, "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 657, "stargazers_count": 16, "watchers_count": 16, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 16, "default_branch": "master", "stargazers": 16, "master_branch": "master" }, "pusher": { "name": "duck8823", "email": "duck8823@gmail.com" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: push +X-GitHub-Delivery: d9e8d758-10b2-11e9-8f64-85498fa56ba1 + +{ "ref": "refs/heads/rearchitecture", "before": "9fbed8c094a6a07fbe460367b20f5ababe245ba5", "after": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "created": false, "deleted": false, "forced": true, "base_ref": null, "compare": "https://github.com/duck8823/duci/compare/9fbed8c094a6...8580b250a3e4", "commits": [ { "id": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "tree_id": "b93ebeaa9cd8a3dbe826b1b640f0c42609f72b6f", "distinct": true, "message": "Fix json key of log line", "timestamp": "2019-01-05T15:26:04+09:00", "url": "https://github.com/duck8823/duci/commit/8580b250a3e4841c4654a4315d0a22e75a9788a3", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/log.go" ] } ], "head_commit": { "id": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "tree_id": "b93ebeaa9cd8a3dbe826b1b640f0c42609f72b6f", "distinct": true, "message": "Fix json key of log line", "timestamp": "2019-01-05T15:26:04+09:00", "url": "https://github.com/duck8823/duci/commit/8580b250a3e4841c4654a4315d0a22e75a9788a3", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/log.go" ] }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "name": "duck8823", "email": "duck8823@gmail.com", "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://github.com/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": 1522547462, "updated_at": "2018-12-28T21:05:40Z", "pushed_at": 1546669595, "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 657, "stargazers_count": 16, "watchers_count": 16, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 16, "default_branch": "master", "stargazers": 16, "master_branch": "master" }, "pusher": { "name": "duck8823", "email": "duck8823@gmail.com" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9090/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: push +X-GitHub-Delivery: d9e8d758-10b2-11e9-8f64-85498fa56ba1 + +{ "ref": "refs/heads/rearchitecture", "before": "9fbed8c094a6a07fbe460367b20f5ababe245ba5", "after": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "created": false, "deleted": false, "forced": true, "base_ref": null, "compare": "https://github.com/duck8823/duci/compare/9fbed8c094a6...8580b250a3e4", "commits": [ { "id": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "tree_id": "b93ebeaa9cd8a3dbe826b1b640f0c42609f72b6f", "distinct": true, "message": "Fix json key of log line", "timestamp": "2019-01-05T15:26:04+09:00", "url": "https://github.com/duck8823/duci/commit/8580b250a3e4841c4654a4315d0a22e75a9788a3", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/log.go" ] } ], "head_commit": { "id": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "tree_id": "b93ebeaa9cd8a3dbe826b1b640f0c42609f72b6f", "distinct": true, "message": "Fix json key of log line", "timestamp": "2019-01-05T15:26:04+09:00", "url": "https://github.com/duck8823/duci/commit/8580b250a3e4841c4654a4315d0a22e75a9788a3", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/log.go" ] }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "name": "duck8823", "email": "duck8823@gmail.com", "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://github.com/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": 1522547462, "updated_at": "2018-12-28T21:05:40Z", "pushed_at": 1546669595, "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 657, "stargazers_count": 16, "watchers_count": 16, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 16, "default_branch": "master", "stargazers": 16, "master_branch": "master" }, "pusher": { "name": "duck8823", "email": "duck8823@gmail.com" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://duci.io/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://duci.io/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://duci.io/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://duci.io/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +<> 2019-01-05T022328.400.txt + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +<> 2019-01-05T022202.400.txt + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +<> 2019-01-05T022106.400.txt + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +<> 2019-01-05T021946.400.txt + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +<> 2019-01-05T021944.400.txt + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +<> 2019-01-05T021910.400.txt + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +<> 2019-01-05T021551.400.txt + +### + +POST http://localhost:8080/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:8080/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:8080/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +<> 2018-12-09T111752.400.txt + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/v2/webhook +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +<> 2018-12-08T125933.404.txt + +### + +POST http://localhost:9999/v2/webhook +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/v2/webhook +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/v2/webhook +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/v2/webhook +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/v2/webhook +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/v2/webhook +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/ +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +<> 2018-12-07T080719.500.txt + +### + +POST http://localhost:9999/webhook +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/webhook +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci build" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/webhook +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci build" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +<> 2018-12-06T081612.500.txt + +### + +POST http://localhost:9999/webhook +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci build" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/webhook +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci build" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +<> 2018-12-06T081051.500.txt + +### + +POST http://localhost:9999/webhook +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci build" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +<> 2018-12-06T080907.500.txt + +### + +POST http://localhost:9999/webhook +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci build" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +<> 2018-12-06T080755.500.txt + +### + +POST http://localhost:9999/webhook +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: issue_comment +X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 + +{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci build" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +<> 2018-12-06T080724.400.txt + +### + +POST http://localhost:9999/webhook +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: push +X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 + +{ "ref": "refs/heads/rearchitecture", "before": "8f8a0c7ae4f3c235f06ac0c42a4c8337044e3842", "after": "a6f39be6cfaffaa9c960ededc4d40f5aacff15a4", "created": false, "deleted": false, "forced": false, "base_ref": null, "compare": "https://github.com/duck8823/duci/compare/8f8a0c7ae4f3...a6f39be6cfaf", "commits": [ { "id": "a1d4d4bd2b8b21a62bdf3dc10f8a3ce60481c3a2", "tree_id": "81414805071a12c99a8cb8d80a18d1086bbffcf4", "distinct": true, "message": "Move package", "timestamp": "2018-12-01T21:11:44+09:00", "url": "https://github.com/duck8823/duci/commit/a1d4d4bd2b8b21a62bdf3dc10f8a3ce60481c3a2", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ "domain/model/docker/docker.go", "domain/model/docker/third_pirty.go", "domain/model/runner/builder.go", "domain/model/runner/errors.go", "domain/model/runner/function.go", "domain/model/runner/helper.go", "domain/model/runner/runner.go" ], "removed": [ "domain/service/docker/docker.go", "domain/service/docker/third_pirty.go", "domain/service/runner/builder.go", "domain/service/runner/errors.go", "domain/service/runner/function.go", "domain/service/runner/helper.go", "domain/service/runner/runner.go" ], "modified": [ "application/service/executor/executor.go", "main.go" ] }, { "id": "56d994363bacde2bbadc513f40fe84fd4b71b061", "tree_id": "be56c1c727c95f0f849102ed70afa024cc7e78a0", "distinct": true, "message": "Change import", "timestamp": "2018-12-01T21:13:32+09:00", "url": "https://github.com/duck8823/duci/commit/56d994363bacde2bbadc513f40fe84fd4b71b061", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/docker/log.go", "domain/model/runner/function.go" ] }, { "id": "b702f4106b5677c5692e34f56b113720c411e653", "tree_id": "db061148b40257cd44ba8975198f171786fe525d", "distinct": true, "message": "Rename struct", "timestamp": "2018-12-01T21:18:26+09:00", "url": "https://github.com/duck8823/duci/commit/b702f4106b5677c5692e34f56b113720c411e653", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/docker/docker.go" ] }, { "id": "fb910a17b67f13de865ff6866a1be5d77890c89a", "tree_id": "9e69bde648c5f25ef8441e088f4551fe14b6f517", "distinct": true, "message": "Revert: commit b702f4106b5677c5692e34f56b113720c411e653", "timestamp": "2018-12-01T21:51:24+09:00", "url": "https://github.com/duck8823/duci/commit/fb910a17b67f13de865ff6866a1be5d77890c89a", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "main.go" ] }, { "id": "e431df6437b88a56b07d92c3dabec3d6fe535df9", "tree_id": "3fa578e0feb435dc80851a3f323acfaa89ab091d", "distinct": true, "message": "Add github push target", "timestamp": "2018-12-02T14:19:25+09:00", "url": "https://github.com/duck8823/duci/commit/e431df6437b88a56b07d92c3dabec3d6fe535df9", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ "domain/model/job/target/git/git.go", "domain/model/job/target/git/http_client.go", "domain/model/job/target/git/log.go", "domain/model/job/target/git/ssh_client.go", "domain/model/job/target/github/github.go", "domain/model/job/target/github/repository.go", "domain/model/job/target/github/state.go", "domain/model/job/target/github/target_point.go", "domain/model/job/target/github/target_source.go", "domain/model/job/target/github_push.go" ], "removed": [ ], "modified": [ "application/service/git/mock_git/git.go", "application/service/github/mock_github/github.go" ] }, { "id": "a6f39be6cfaffaa9c960ededc4d40f5aacff15a4", "tree_id": "b26ac466dd544d466401f702d73d2e427cf7e9cc", "distinct": true, "message": "Fix to be able to checkout past commit", "timestamp": "2018-12-02T14:25:22+09:00", "url": "https://github.com/duck8823/duci/commit/a6f39be6cfaffaa9c960ededc4d40f5aacff15a4", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/target/git/http_client.go", "domain/model/job/target/git/ssh_client.go" ] } ], "head_commit": { "id": "a6f39be6cfaffaa9c960ededc4d40f5aacff15a4", "tree_id": "b26ac466dd544d466401f702d73d2e427cf7e9cc", "distinct": true, "message": "Fix to be able to checkout past commit", "timestamp": "2018-12-02T14:25:22+09:00", "url": "https://github.com/duck8823/duci/commit/a6f39be6cfaffaa9c960ededc4d40f5aacff15a4", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/target/git/http_client.go", "domain/model/job/target/git/ssh_client.go" ] }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "name": "duck8823", "email": "duck8823@gmail.com", "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://github.com/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": 1522547462, "updated_at": "2018-11-30T13:45:53Z", "pushed_at": 1543728404, "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 490, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master", "stargazers": 14, "master_branch": "master" }, "pusher": { "name": "duck8823", "email": "duck8823@gmail.com" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + +POST http://localhost:9999/webhook +Accept: */* +Cache-Control: no-cache +X-GitHub-Event: push +X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 + +{ "ref": "refs/heads/rearchitecture", "before": "8f8a0c7ae4f3c235f06ac0c42a4c8337044e3842", "after": "a6f39be6cfaffaa9c960ededc4d40f5aacff15a4", "created": false, "deleted": false, "forced": false, "base_ref": null, "compare": "https://github.com/duck8823/duci/compare/8f8a0c7ae4f3...a6f39be6cfaf", "commits": [ { "id": "a1d4d4bd2b8b21a62bdf3dc10f8a3ce60481c3a2", "tree_id": "81414805071a12c99a8cb8d80a18d1086bbffcf4", "distinct": true, "message": "Move package", "timestamp": "2018-12-01T21:11:44+09:00", "url": "https://github.com/duck8823/duci/commit/a1d4d4bd2b8b21a62bdf3dc10f8a3ce60481c3a2", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ "domain/model/docker/docker.go", "domain/model/docker/third_pirty.go", "domain/model/runner/builder.go", "domain/model/runner/errors.go", "domain/model/runner/function.go", "domain/model/runner/helper.go", "domain/model/runner/runner.go" ], "removed": [ "domain/service/docker/docker.go", "domain/service/docker/third_pirty.go", "domain/service/runner/builder.go", "domain/service/runner/errors.go", "domain/service/runner/function.go", "domain/service/runner/helper.go", "domain/service/runner/runner.go" ], "modified": [ "application/service/executor/executor.go", "main.go" ] }, { "id": "56d994363bacde2bbadc513f40fe84fd4b71b061", "tree_id": "be56c1c727c95f0f849102ed70afa024cc7e78a0", "distinct": true, "message": "Change import", "timestamp": "2018-12-01T21:13:32+09:00", "url": "https://github.com/duck8823/duci/commit/56d994363bacde2bbadc513f40fe84fd4b71b061", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/docker/log.go", "domain/model/runner/function.go" ] }, { "id": "b702f4106b5677c5692e34f56b113720c411e653", "tree_id": "db061148b40257cd44ba8975198f171786fe525d", "distinct": true, "message": "Rename struct", "timestamp": "2018-12-01T21:18:26+09:00", "url": "https://github.com/duck8823/duci/commit/b702f4106b5677c5692e34f56b113720c411e653", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/docker/docker.go" ] }, { "id": "fb910a17b67f13de865ff6866a1be5d77890c89a", "tree_id": "9e69bde648c5f25ef8441e088f4551fe14b6f517", "distinct": true, "message": "Revert: commit b702f4106b5677c5692e34f56b113720c411e653", "timestamp": "2018-12-01T21:51:24+09:00", "url": "https://github.com/duck8823/duci/commit/fb910a17b67f13de865ff6866a1be5d77890c89a", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "main.go" ] }, { "id": "e431df6437b88a56b07d92c3dabec3d6fe535df9", "tree_id": "3fa578e0feb435dc80851a3f323acfaa89ab091d", "distinct": true, "message": "Add github push target", "timestamp": "2018-12-02T14:19:25+09:00", "url": "https://github.com/duck8823/duci/commit/e431df6437b88a56b07d92c3dabec3d6fe535df9", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ "domain/model/job/target/git/git.go", "domain/model/job/target/git/http_client.go", "domain/model/job/target/git/log.go", "domain/model/job/target/git/ssh_client.go", "domain/model/job/target/github/github.go", "domain/model/job/target/github/repository.go", "domain/model/job/target/github/state.go", "domain/model/job/target/github/target_point.go", "domain/model/job/target/github/target_source.go", "domain/model/job/target/github_push.go" ], "removed": [ ], "modified": [ "application/service/git/mock_git/git.go", "application/service/github/mock_github/github.go" ] }, { "id": "a6f39be6cfaffaa9c960ededc4d40f5aacff15a4", "tree_id": "b26ac466dd544d466401f702d73d2e427cf7e9cc", "distinct": true, "message": "Fix to be able to checkout past commit", "timestamp": "2018-12-02T14:25:22+09:00", "url": "https://github.com/duck8823/duci/commit/a6f39be6cfaffaa9c960ededc4d40f5aacff15a4", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/target/git/http_client.go", "domain/model/job/target/git/ssh_client.go" ] } ], "head_commit": { "id": "a6f39be6cfaffaa9c960ededc4d40f5aacff15a4", "tree_id": "b26ac466dd544d466401f702d73d2e427cf7e9cc", "distinct": true, "message": "Fix to be able to checkout past commit", "timestamp": "2018-12-02T14:25:22+09:00", "url": "https://github.com/duck8823/duci/commit/a6f39be6cfaffaa9c960ededc4d40f5aacff15a4", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/target/git/http_client.go", "domain/model/job/target/git/ssh_client.go" ] }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "name": "duck8823", "email": "duck8823@gmail.com", "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://github.com/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": 1522547462, "updated_at": "2018-11-30T13:45:53Z", "pushed_at": 1543728404, "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 490, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master", "stargazers": 14, "master_branch": "master" }, "pusher": { "name": "duck8823", "email": "duck8823@gmail.com" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } + +### + diff --git a/presentation/controller/webhook/handler.go b/presentation/controller/webhook/handler.go index 4f42801c..99e63d62 100644 --- a/presentation/controller/webhook/handler.go +++ b/presentation/controller/webhook/handler.go @@ -69,7 +69,7 @@ func (h *handler) PushEvent(w http.ResponseWriter, r *http.Request) { TargetSource: &github.TargetSource{ Repository: event.GetRepo(), Ref: event.GetRef(), - SHA: plumbing.NewHash(event.GetHead()), + SHA: plumbing.NewHash(event.GetHeadCommit().GetID()), }, TaskName: fmt.Sprintf("%s/push", application.Name), TargetURL: targetURL, From c116414e845d7093dc84489e10dd674027fd7eb5 Mon Sep 17 00:00:00 2001 From: Shunsuke Maeda Date: Sat, 5 Jan 2019 18:26:47 +0900 Subject: [PATCH 135/135] Delete http-requests-log.http --- .idea/httpRequests/http-requests-log.http | 530 ---------------------- 1 file changed, 530 deletions(-) delete mode 100644 .idea/httpRequests/http-requests-log.http diff --git a/.idea/httpRequests/http-requests-log.http b/.idea/httpRequests/http-requests-log.http deleted file mode 100644 index 732b887c..00000000 --- a/.idea/httpRequests/http-requests-log.http +++ /dev/null @@ -1,530 +0,0 @@ -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: push -X-GitHub-Delivery: d9e8d758-10b2-11e9-8f64-85498fa56ba1 - -{ "ref": "refs/heads/rearchitecture", "before": "9fbed8c094a6a07fbe460367b20f5ababe245ba5", "after": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "created": false, "deleted": false, "forced": true, "base_ref": null, "compare": "https://github.com/duck8823/duci/compare/9fbed8c094a6...8580b250a3e4", "commits": [ { "id": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "tree_id": "b93ebeaa9cd8a3dbe826b1b640f0c42609f72b6f", "distinct": true, "message": "Fix json key of log line", "timestamp": "2019-01-05T15:26:04+09:00", "url": "https://github.com/duck8823/duci/commit/8580b250a3e4841c4654a4315d0a22e75a9788a3", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/log.go" ] } ], "head_commit": { "id": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "tree_id": "b93ebeaa9cd8a3dbe826b1b640f0c42609f72b6f", "distinct": true, "message": "Fix json key of log line", "timestamp": "2019-01-05T15:26:04+09:00", "url": "https://github.com/duck8823/duci/commit/8580b250a3e4841c4654a4315d0a22e75a9788a3", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/log.go" ] }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "name": "duck8823", "email": "duck8823@gmail.com", "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://github.com/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": 1522547462, "updated_at": "2018-12-28T21:05:40Z", "pushed_at": 1546669595, "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 657, "stargazers_count": 16, "watchers_count": 16, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 16, "default_branch": "master", "stargazers": 16, "master_branch": "master" }, "pusher": { "name": "duck8823", "email": "duck8823@gmail.com" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: push -X-GitHub-Delivery: d9e8d758-10b2-11e9-8f64-85498fa56ba1 - -{ "ref": "refs/heads/rearchitecture", "before": "9fbed8c094a6a07fbe460367b20f5ababe245ba5", "after": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "created": false, "deleted": false, "forced": true, "base_ref": null, "compare": "https://github.com/duck8823/duci/compare/9fbed8c094a6...8580b250a3e4", "commits": [ { "id": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "tree_id": "b93ebeaa9cd8a3dbe826b1b640f0c42609f72b6f", "distinct": true, "message": "Fix json key of log line", "timestamp": "2019-01-05T15:26:04+09:00", "url": "https://github.com/duck8823/duci/commit/8580b250a3e4841c4654a4315d0a22e75a9788a3", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/log.go" ] } ], "head_commit": { "id": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "tree_id": "b93ebeaa9cd8a3dbe826b1b640f0c42609f72b6f", "distinct": true, "message": "Fix json key of log line", "timestamp": "2019-01-05T15:26:04+09:00", "url": "https://github.com/duck8823/duci/commit/8580b250a3e4841c4654a4315d0a22e75a9788a3", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/log.go" ] }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "name": "duck8823", "email": "duck8823@gmail.com", "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://github.com/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": 1522547462, "updated_at": "2018-12-28T21:05:40Z", "pushed_at": 1546669595, "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 657, "stargazers_count": 16, "watchers_count": 16, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 16, "default_branch": "master", "stargazers": 16, "master_branch": "master" }, "pusher": { "name": "duck8823", "email": "duck8823@gmail.com" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: push -X-GitHub-Delivery: d9e8d758-10b2-11e9-8f64-85498fa56ba1 - -{ "ref": "refs/heads/rearchitecture", "before": "9fbed8c094a6a07fbe460367b20f5ababe245ba5", "after": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "created": false, "deleted": false, "forced": true, "base_ref": null, "compare": "https://github.com/duck8823/duci/compare/9fbed8c094a6...8580b250a3e4", "commits": [ { "id": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "tree_id": "b93ebeaa9cd8a3dbe826b1b640f0c42609f72b6f", "distinct": true, "message": "Fix json key of log line", "timestamp": "2019-01-05T15:26:04+09:00", "url": "https://github.com/duck8823/duci/commit/8580b250a3e4841c4654a4315d0a22e75a9788a3", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/log.go" ] } ], "head_commit": { "id": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "tree_id": "b93ebeaa9cd8a3dbe826b1b640f0c42609f72b6f", "distinct": true, "message": "Fix json key of log line", "timestamp": "2019-01-05T15:26:04+09:00", "url": "https://github.com/duck8823/duci/commit/8580b250a3e4841c4654a4315d0a22e75a9788a3", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/log.go" ] }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "name": "duck8823", "email": "duck8823@gmail.com", "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://github.com/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": 1522547462, "updated_at": "2018-12-28T21:05:40Z", "pushed_at": 1546669595, "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 657, "stargazers_count": 16, "watchers_count": 16, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 16, "default_branch": "master", "stargazers": 16, "master_branch": "master" }, "pusher": { "name": "duck8823", "email": "duck8823@gmail.com" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: push -X-GitHub-Delivery: d9e8d758-10b2-11e9-8f64-85498fa56ba1 - -{ "ref": "refs/heads/rearchitecture", "before": "9fbed8c094a6a07fbe460367b20f5ababe245ba5", "after": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "created": false, "deleted": false, "forced": true, "base_ref": null, "compare": "https://github.com/duck8823/duci/compare/9fbed8c094a6...8580b250a3e4", "commits": [ { "id": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "tree_id": "b93ebeaa9cd8a3dbe826b1b640f0c42609f72b6f", "distinct": true, "message": "Fix json key of log line", "timestamp": "2019-01-05T15:26:04+09:00", "url": "https://github.com/duck8823/duci/commit/8580b250a3e4841c4654a4315d0a22e75a9788a3", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/log.go" ] } ], "head_commit": { "id": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "tree_id": "b93ebeaa9cd8a3dbe826b1b640f0c42609f72b6f", "distinct": true, "message": "Fix json key of log line", "timestamp": "2019-01-05T15:26:04+09:00", "url": "https://github.com/duck8823/duci/commit/8580b250a3e4841c4654a4315d0a22e75a9788a3", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/log.go" ] }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "name": "duck8823", "email": "duck8823@gmail.com", "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://github.com/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": 1522547462, "updated_at": "2018-12-28T21:05:40Z", "pushed_at": 1546669595, "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 657, "stargazers_count": 16, "watchers_count": 16, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 16, "default_branch": "master", "stargazers": 16, "master_branch": "master" }, "pusher": { "name": "duck8823", "email": "duck8823@gmail.com" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9090/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: push -X-GitHub-Delivery: d9e8d758-10b2-11e9-8f64-85498fa56ba1 - -{ "ref": "refs/heads/rearchitecture", "before": "9fbed8c094a6a07fbe460367b20f5ababe245ba5", "after": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "created": false, "deleted": false, "forced": true, "base_ref": null, "compare": "https://github.com/duck8823/duci/compare/9fbed8c094a6...8580b250a3e4", "commits": [ { "id": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "tree_id": "b93ebeaa9cd8a3dbe826b1b640f0c42609f72b6f", "distinct": true, "message": "Fix json key of log line", "timestamp": "2019-01-05T15:26:04+09:00", "url": "https://github.com/duck8823/duci/commit/8580b250a3e4841c4654a4315d0a22e75a9788a3", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/log.go" ] } ], "head_commit": { "id": "8580b250a3e4841c4654a4315d0a22e75a9788a3", "tree_id": "b93ebeaa9cd8a3dbe826b1b640f0c42609f72b6f", "distinct": true, "message": "Fix json key of log line", "timestamp": "2019-01-05T15:26:04+09:00", "url": "https://github.com/duck8823/duci/commit/8580b250a3e4841c4654a4315d0a22e75a9788a3", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/log.go" ] }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "name": "duck8823", "email": "duck8823@gmail.com", "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://github.com/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": 1522547462, "updated_at": "2018-12-28T21:05:40Z", "pushed_at": 1546669595, "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 657, "stargazers_count": 16, "watchers_count": 16, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 16, "default_branch": "master", "stargazers": 16, "master_branch": "master" }, "pusher": { "name": "duck8823", "email": "duck8823@gmail.com" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://duci.io/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://duci.io/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://duci.io/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://duci.io/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -<> 2019-01-05T022328.400.txt - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -<> 2019-01-05T022202.400.txt - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -<> 2019-01-05T022106.400.txt - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -<> 2019-01-05T021946.400.txt - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -<> 2019-01-05T021944.400.txt - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -<> 2019-01-05T021910.400.txt - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -<> 2019-01-05T021551.400.txt - -### - -POST http://localhost:8080/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:8080/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:8080/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -<> 2018-12-09T111752.400.txt - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/v2/webhook -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -<> 2018-12-08T125933.404.txt - -### - -POST http://localhost:9999/v2/webhook -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/v2/webhook -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/v2/webhook -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: 416c5678-c3ba-4d45-85f3-a967db4e3dcf - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/v2/webhook -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/v2/webhook -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/v2/webhook -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/ -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -<> 2018-12-07T080719.500.txt - -### - -POST http://localhost:9999/webhook -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci test" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/webhook -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci build" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/webhook -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci build" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -<> 2018-12-06T081612.500.txt - -### - -POST http://localhost:9999/webhook -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci build" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/webhook -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci build" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -<> 2018-12-06T081051.500.txt - -### - -POST http://localhost:9999/webhook -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci build" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -<> 2018-12-06T080907.500.txt - -### - -POST http://localhost:9999/webhook -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci build" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -<> 2018-12-06T080755.500.txt - -### - -POST http://localhost:9999/webhook -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: issue_comment -X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 - -{ "action": "created", "issue": { "url": "https://api.github.com/repos/duck8823/duci/issues/148", "repository_url": "https://api.github.com/repos/duck8823/duci", "labels_url": "https://api.github.com/repos/duck8823/duci/issues/148/labels{/name}", "comments_url": "https://api.github.com/repos/duck8823/duci/issues/148/comments", "events_url": "https://api.github.com/repos/duck8823/duci/issues/148/events", "html_url": "https://github.com/duck8823/duci/pull/148", "id": 385284428, "node_id": "MDExOlB1bGxSZXF1ZXN0MjM0Mjg5Mzcx", "number": 148, "title": "[WIP] RE: ARCHITECTURE", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "labels": [ { "id": 886097753, "node_id": "MDU6TGFiZWw4ODYwOTc3NTM=", "url": "https://api.github.com/repos/duck8823/duci/labels/enhancement", "name": "enhancement", "color": "a2eeef", "default": true }, { "id": 986350154, "node_id": "MDU6TGFiZWw5ODYzNTAxNTQ=", "url": "https://api.github.com/repos/duck8823/duci/labels/maintenance", "name": "maintenance", "color": "74d850", "default": false } ], "state": "open", "locked": false, "assignee": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "assignees": [ { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } ], "milestone": null, "comments": 1, "created_at": "2018-11-28T14:08:16Z", "updated_at": "2018-12-05T23:06:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": { "url": "https://api.github.com/repos/duck8823/duci/pulls/148", "html_url": "https://github.com/duck8823/duci/pull/148", "diff_url": "https://github.com/duck8823/duci/pull/148.diff", "patch_url": "https://github.com/duck8823/duci/pull/148.patch" }, "body": "fix #145 " }, "comment": { "url": "https://api.github.com/repos/duck8823/duci/issues/comments/444685937", "html_url": "https://github.com/duck8823/duci/pull/148#issuecomment-444685937", "issue_url": "https://api.github.com/repos/duck8823/duci/issues/148", "id": 444685937, "node_id": "MDEyOklzc3VlQ29tbWVudDQ0NDY4NTkzNw==", "user": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "created_at": "2018-12-05T23:06:33Z", "updated_at": "2018-12-05T23:06:33Z", "author_association": "OWNER", "body": "ci build" }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://api.github.com/repos/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": "2018-04-01T01:51:02Z", "updated_at": "2018-11-30T13:45:53Z", "pushed_at": "2018-12-03T23:47:21Z", "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 512, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -<> 2018-12-06T080724.400.txt - -### - -POST http://localhost:9999/webhook -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: push -X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 - -{ "ref": "refs/heads/rearchitecture", "before": "8f8a0c7ae4f3c235f06ac0c42a4c8337044e3842", "after": "a6f39be6cfaffaa9c960ededc4d40f5aacff15a4", "created": false, "deleted": false, "forced": false, "base_ref": null, "compare": "https://github.com/duck8823/duci/compare/8f8a0c7ae4f3...a6f39be6cfaf", "commits": [ { "id": "a1d4d4bd2b8b21a62bdf3dc10f8a3ce60481c3a2", "tree_id": "81414805071a12c99a8cb8d80a18d1086bbffcf4", "distinct": true, "message": "Move package", "timestamp": "2018-12-01T21:11:44+09:00", "url": "https://github.com/duck8823/duci/commit/a1d4d4bd2b8b21a62bdf3dc10f8a3ce60481c3a2", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ "domain/model/docker/docker.go", "domain/model/docker/third_pirty.go", "domain/model/runner/builder.go", "domain/model/runner/errors.go", "domain/model/runner/function.go", "domain/model/runner/helper.go", "domain/model/runner/runner.go" ], "removed": [ "domain/service/docker/docker.go", "domain/service/docker/third_pirty.go", "domain/service/runner/builder.go", "domain/service/runner/errors.go", "domain/service/runner/function.go", "domain/service/runner/helper.go", "domain/service/runner/runner.go" ], "modified": [ "application/service/executor/executor.go", "main.go" ] }, { "id": "56d994363bacde2bbadc513f40fe84fd4b71b061", "tree_id": "be56c1c727c95f0f849102ed70afa024cc7e78a0", "distinct": true, "message": "Change import", "timestamp": "2018-12-01T21:13:32+09:00", "url": "https://github.com/duck8823/duci/commit/56d994363bacde2bbadc513f40fe84fd4b71b061", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/docker/log.go", "domain/model/runner/function.go" ] }, { "id": "b702f4106b5677c5692e34f56b113720c411e653", "tree_id": "db061148b40257cd44ba8975198f171786fe525d", "distinct": true, "message": "Rename struct", "timestamp": "2018-12-01T21:18:26+09:00", "url": "https://github.com/duck8823/duci/commit/b702f4106b5677c5692e34f56b113720c411e653", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/docker/docker.go" ] }, { "id": "fb910a17b67f13de865ff6866a1be5d77890c89a", "tree_id": "9e69bde648c5f25ef8441e088f4551fe14b6f517", "distinct": true, "message": "Revert: commit b702f4106b5677c5692e34f56b113720c411e653", "timestamp": "2018-12-01T21:51:24+09:00", "url": "https://github.com/duck8823/duci/commit/fb910a17b67f13de865ff6866a1be5d77890c89a", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "main.go" ] }, { "id": "e431df6437b88a56b07d92c3dabec3d6fe535df9", "tree_id": "3fa578e0feb435dc80851a3f323acfaa89ab091d", "distinct": true, "message": "Add github push target", "timestamp": "2018-12-02T14:19:25+09:00", "url": "https://github.com/duck8823/duci/commit/e431df6437b88a56b07d92c3dabec3d6fe535df9", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ "domain/model/job/target/git/git.go", "domain/model/job/target/git/http_client.go", "domain/model/job/target/git/log.go", "domain/model/job/target/git/ssh_client.go", "domain/model/job/target/github/github.go", "domain/model/job/target/github/repository.go", "domain/model/job/target/github/state.go", "domain/model/job/target/github/target_point.go", "domain/model/job/target/github/target_source.go", "domain/model/job/target/github_push.go" ], "removed": [ ], "modified": [ "application/service/git/mock_git/git.go", "application/service/github/mock_github/github.go" ] }, { "id": "a6f39be6cfaffaa9c960ededc4d40f5aacff15a4", "tree_id": "b26ac466dd544d466401f702d73d2e427cf7e9cc", "distinct": true, "message": "Fix to be able to checkout past commit", "timestamp": "2018-12-02T14:25:22+09:00", "url": "https://github.com/duck8823/duci/commit/a6f39be6cfaffaa9c960ededc4d40f5aacff15a4", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/target/git/http_client.go", "domain/model/job/target/git/ssh_client.go" ] } ], "head_commit": { "id": "a6f39be6cfaffaa9c960ededc4d40f5aacff15a4", "tree_id": "b26ac466dd544d466401f702d73d2e427cf7e9cc", "distinct": true, "message": "Fix to be able to checkout past commit", "timestamp": "2018-12-02T14:25:22+09:00", "url": "https://github.com/duck8823/duci/commit/a6f39be6cfaffaa9c960ededc4d40f5aacff15a4", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/target/git/http_client.go", "domain/model/job/target/git/ssh_client.go" ] }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "name": "duck8823", "email": "duck8823@gmail.com", "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://github.com/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": 1522547462, "updated_at": "2018-11-30T13:45:53Z", "pushed_at": 1543728404, "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 490, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master", "stargazers": 14, "master_branch": "master" }, "pusher": { "name": "duck8823", "email": "duck8823@gmail.com" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### - -POST http://localhost:9999/webhook -Accept: */* -Cache-Control: no-cache -X-GitHub-Event: push -X-GitHub-Delivery: eb6a738e-e5a0-11e8-9bf7-9b4b63059ea8 - -{ "ref": "refs/heads/rearchitecture", "before": "8f8a0c7ae4f3c235f06ac0c42a4c8337044e3842", "after": "a6f39be6cfaffaa9c960ededc4d40f5aacff15a4", "created": false, "deleted": false, "forced": false, "base_ref": null, "compare": "https://github.com/duck8823/duci/compare/8f8a0c7ae4f3...a6f39be6cfaf", "commits": [ { "id": "a1d4d4bd2b8b21a62bdf3dc10f8a3ce60481c3a2", "tree_id": "81414805071a12c99a8cb8d80a18d1086bbffcf4", "distinct": true, "message": "Move package", "timestamp": "2018-12-01T21:11:44+09:00", "url": "https://github.com/duck8823/duci/commit/a1d4d4bd2b8b21a62bdf3dc10f8a3ce60481c3a2", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ "domain/model/docker/docker.go", "domain/model/docker/third_pirty.go", "domain/model/runner/builder.go", "domain/model/runner/errors.go", "domain/model/runner/function.go", "domain/model/runner/helper.go", "domain/model/runner/runner.go" ], "removed": [ "domain/service/docker/docker.go", "domain/service/docker/third_pirty.go", "domain/service/runner/builder.go", "domain/service/runner/errors.go", "domain/service/runner/function.go", "domain/service/runner/helper.go", "domain/service/runner/runner.go" ], "modified": [ "application/service/executor/executor.go", "main.go" ] }, { "id": "56d994363bacde2bbadc513f40fe84fd4b71b061", "tree_id": "be56c1c727c95f0f849102ed70afa024cc7e78a0", "distinct": true, "message": "Change import", "timestamp": "2018-12-01T21:13:32+09:00", "url": "https://github.com/duck8823/duci/commit/56d994363bacde2bbadc513f40fe84fd4b71b061", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/docker/log.go", "domain/model/runner/function.go" ] }, { "id": "b702f4106b5677c5692e34f56b113720c411e653", "tree_id": "db061148b40257cd44ba8975198f171786fe525d", "distinct": true, "message": "Rename struct", "timestamp": "2018-12-01T21:18:26+09:00", "url": "https://github.com/duck8823/duci/commit/b702f4106b5677c5692e34f56b113720c411e653", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/docker/docker.go" ] }, { "id": "fb910a17b67f13de865ff6866a1be5d77890c89a", "tree_id": "9e69bde648c5f25ef8441e088f4551fe14b6f517", "distinct": true, "message": "Revert: commit b702f4106b5677c5692e34f56b113720c411e653", "timestamp": "2018-12-01T21:51:24+09:00", "url": "https://github.com/duck8823/duci/commit/fb910a17b67f13de865ff6866a1be5d77890c89a", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "main.go" ] }, { "id": "e431df6437b88a56b07d92c3dabec3d6fe535df9", "tree_id": "3fa578e0feb435dc80851a3f323acfaa89ab091d", "distinct": true, "message": "Add github push target", "timestamp": "2018-12-02T14:19:25+09:00", "url": "https://github.com/duck8823/duci/commit/e431df6437b88a56b07d92c3dabec3d6fe535df9", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ "domain/model/job/target/git/git.go", "domain/model/job/target/git/http_client.go", "domain/model/job/target/git/log.go", "domain/model/job/target/git/ssh_client.go", "domain/model/job/target/github/github.go", "domain/model/job/target/github/repository.go", "domain/model/job/target/github/state.go", "domain/model/job/target/github/target_point.go", "domain/model/job/target/github/target_source.go", "domain/model/job/target/github_push.go" ], "removed": [ ], "modified": [ "application/service/git/mock_git/git.go", "application/service/github/mock_github/github.go" ] }, { "id": "a6f39be6cfaffaa9c960ededc4d40f5aacff15a4", "tree_id": "b26ac466dd544d466401f702d73d2e427cf7e9cc", "distinct": true, "message": "Fix to be able to checkout past commit", "timestamp": "2018-12-02T14:25:22+09:00", "url": "https://github.com/duck8823/duci/commit/a6f39be6cfaffaa9c960ededc4d40f5aacff15a4", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/target/git/http_client.go", "domain/model/job/target/git/ssh_client.go" ] } ], "head_commit": { "id": "a6f39be6cfaffaa9c960ededc4d40f5aacff15a4", "tree_id": "b26ac466dd544d466401f702d73d2e427cf7e9cc", "distinct": true, "message": "Fix to be able to checkout past commit", "timestamp": "2018-12-02T14:25:22+09:00", "url": "https://github.com/duck8823/duci/commit/a6f39be6cfaffaa9c960ededc4d40f5aacff15a4", "author": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "committer": { "name": "shunsuke maeda", "email": "duck8823@gmail.com", "username": "duck8823" }, "added": [ ], "removed": [ ], "modified": [ "domain/model/job/target/git/http_client.go", "domain/model/job/target/git/ssh_client.go" ] }, "repository": { "id": 127587125, "node_id": "MDEwOlJlcG9zaXRvcnkxMjc1ODcxMjU=", "name": "duci", "full_name": "duck8823/duci", "private": false, "owner": { "name": "duck8823", "email": "duck8823@gmail.com", "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false }, "html_url": "https://github.com/duck8823/duci", "description": "The small ci server ", "fork": false, "url": "https://github.com/duck8823/duci", "forks_url": "https://api.github.com/repos/duck8823/duci/forks", "keys_url": "https://api.github.com/repos/duck8823/duci/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/duck8823/duci/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/duck8823/duci/teams", "hooks_url": "https://api.github.com/repos/duck8823/duci/hooks", "issue_events_url": "https://api.github.com/repos/duck8823/duci/issues/events{/number}", "events_url": "https://api.github.com/repos/duck8823/duci/events", "assignees_url": "https://api.github.com/repos/duck8823/duci/assignees{/user}", "branches_url": "https://api.github.com/repos/duck8823/duci/branches{/branch}", "tags_url": "https://api.github.com/repos/duck8823/duci/tags", "blobs_url": "https://api.github.com/repos/duck8823/duci/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/duck8823/duci/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/duck8823/duci/git/refs{/sha}", "trees_url": "https://api.github.com/repos/duck8823/duci/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/duck8823/duci/statuses/{sha}", "languages_url": "https://api.github.com/repos/duck8823/duci/languages", "stargazers_url": "https://api.github.com/repos/duck8823/duci/stargazers", "contributors_url": "https://api.github.com/repos/duck8823/duci/contributors", "subscribers_url": "https://api.github.com/repos/duck8823/duci/subscribers", "subscription_url": "https://api.github.com/repos/duck8823/duci/subscription", "commits_url": "https://api.github.com/repos/duck8823/duci/commits{/sha}", "git_commits_url": "https://api.github.com/repos/duck8823/duci/git/commits{/sha}", "comments_url": "https://api.github.com/repos/duck8823/duci/comments{/number}", "issue_comment_url": "https://api.github.com/repos/duck8823/duci/issues/comments{/number}", "contents_url": "https://api.github.com/repos/duck8823/duci/contents/{+path}", "compare_url": "https://api.github.com/repos/duck8823/duci/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/duck8823/duci/merges", "archive_url": "https://api.github.com/repos/duck8823/duci/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/duck8823/duci/downloads", "issues_url": "https://api.github.com/repos/duck8823/duci/issues{/number}", "pulls_url": "https://api.github.com/repos/duck8823/duci/pulls{/number}", "milestones_url": "https://api.github.com/repos/duck8823/duci/milestones{/number}", "notifications_url": "https://api.github.com/repos/duck8823/duci/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/duck8823/duci/labels{/name}", "releases_url": "https://api.github.com/repos/duck8823/duci/releases{/id}", "deployments_url": "https://api.github.com/repos/duck8823/duci/deployments", "created_at": 1522547462, "updated_at": "2018-11-30T13:45:53Z", "pushed_at": 1543728404, "git_url": "git://github.com/duck8823/duci.git", "ssh_url": "git@github.com:duck8823/duci.git", "clone_url": "https://github.com/duck8823/duci.git", "svn_url": "https://github.com/duck8823/duci", "homepage": "", "size": 490, "stargazers_count": 14, "watchers_count": 14, "language": "Go", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": true, "has_pages": false, "forks_count": 1, "mirror_url": null, "archived": false, "open_issues_count": 4, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 1, "open_issues": 4, "watchers": 14, "default_branch": "master", "stargazers": 14, "master_branch": "master" }, "pusher": { "name": "duck8823", "email": "duck8823@gmail.com" }, "sender": { "login": "duck8823", "id": 15160519, "node_id": "MDQ6VXNlcjE1MTYwNTE5", "avatar_url": "https://avatars2.githubusercontent.com/u/15160519?v=4", "gravatar_id": "", "url": "https://api.github.com/users/duck8823", "html_url": "https://github.com/duck8823", "followers_url": "https://api.github.com/users/duck8823/followers", "following_url": "https://api.github.com/users/duck8823/following{/other_user}", "gists_url": "https://api.github.com/users/duck8823/gists{/gist_id}", "starred_url": "https://api.github.com/users/duck8823/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/duck8823/subscriptions", "organizations_url": "https://api.github.com/users/duck8823/orgs", "repos_url": "https://api.github.com/users/duck8823/repos", "events_url": "https://api.github.com/users/duck8823/events{/privacy}", "received_events_url": "https://api.github.com/users/duck8823/received_events", "type": "User", "site_admin": false } } - -### -