provide ability to read and upload cards to drone server.

pull/16/head
Eoin McAfee 3 years ago
parent 0a95ecec98
commit fe9f999fb0

@ -6,29 +6,15 @@ package livelog
import (
"bufio"
"encoding/base64"
"io"
"io/ioutil"
"regexp"
)
var re = regexp.MustCompile("#((.*?)#)")
// Copy copies from src to dst and removes until either EOF
// is reached on src or an error occurs.
func Copy(dst io.Writer, src io.ReadCloser) error {
r := bufio.NewReader(src)
for {
bytes, err := r.ReadBytes('\n')
// check logs for card data
card := re.FindStringSubmatch(string(bytes))
if card != nil {
data, err := base64.StdEncoding.DecodeString(card[len(card)-1:][0])
if err == nil {
_ = ioutil.WriteFile("/tmp/card.json", data, 0644)
}
continue
}
if _, err := dst.Write(bytes); err != nil {
return err
}

@ -0,0 +1,40 @@
package extractor
import (
"encoding/base64"
"io"
"regexp"
)
var re = regexp.MustCompile("#((.*?)#)")
type Writer struct {
base io.Writer
file []byte
}
func New(w io.Writer) *Writer {
return &Writer{w, nil}
}
func (e *Writer) Write(p []byte) (n int, err error) {
card := re.FindStringSubmatch(string(p))
if card == nil {
return e.base.Write(p)
}
data, err := base64.StdEncoding.DecodeString(card[len(card)-1:][0])
if err == nil {
e.file = data
}
// remove encoded string for logs
return e.base.Write([]byte(""))
}
func (e *Writer) File() ([]byte, bool) {
if len(e.file) > 0 {
return e.file, true
} else {
return nil, false
}
}

@ -8,6 +8,8 @@ import (
"context"
"sync"
"github.com/drone/runner-go/livelog/extractor"
"github.com/drone/drone-go/drone"
"github.com/drone/runner-go/environ"
"github.com/drone/runner-go/logger"
@ -235,17 +237,20 @@ func (e *Execer) exec(ctx context.Context, state *pipeline.State, spec Spec, ste
wc := e.streamer.Stream(noContext, state, step.GetName())
wc = newReplacer(wc, secretSlice(step))
// wrap writer in extrator
ext := extractor.New(wc)
// if the step is configured as a daemon, it is detached
// from the main process and executed separately.
if step.IsDetached() {
go func() {
e.engine.Run(ctx, spec, copy, wc)
e.engine.Run(ctx, spec, copy, ext)
wc.Close()
}()
return nil
}
exited, err := e.engine.Run(ctx, spec, copy, wc)
exited, err := e.engine.Run(ctx, spec, copy, ext)
// close the stream. If the session is a remote session, the
// full log buffer is uploaded to the remote server.
@ -253,14 +258,15 @@ func (e *Execer) exec(ctx context.Context, state *pipeline.State, spec Spec, ste
result = multierror.Append(result, err)
}
// stream card data to server if exists
file, _ := e.engine.StreamFile(ctx, spec, copy, "/tmp/card.json")
if file != nil {
err = e.uploader.UploadCard(ctx, file, state, step.GetName())
// upload card if exists
card, ok := ext.File()
if ok {
err = e.uploader.UploadCard(ctx, card, state, step.GetName())
if err != nil {
return nil
}
}
// if the context was cancelled and returns a Canceled or
// DeadlineExceeded error this indicates the pipeline was
// cancelled.

@ -84,9 +84,6 @@ type (
// Run runs the pipeline step.
Run(context.Context, Spec, Step, io.Writer) (*State, error)
// StreamFile copies a file to the server
StreamFile(context.Context, Spec, Step, string) (io.ReadCloser, error)
}
// Spec is an interface that must be implemented by all

@ -2,11 +2,10 @@ package pipeline
import (
"context"
"io"
)
type Uploader interface {
UploadCard(context.Context, io.ReadCloser, *State, string) error
UploadCard(context.Context, []byte, *State, string) error
}
func NopUploader() Uploader {
@ -15,4 +14,4 @@ func NopUploader() Uploader {
type nopUploader struct{}
func (*nopUploader) UploadCard(context.Context, io.ReadCloser, *State, string) error { return nil }
func (*nopUploader) UploadCard(context.Context, []byte, *State, string) error { return nil }

@ -3,7 +3,6 @@ package uploader
import (
"context"
"encoding/json"
"io"
"github.com/drone/drone-go/drone"
"github.com/drone/runner-go/client"
@ -23,14 +22,10 @@ func New(client client.Client) *Upload {
}
}
func (s *Upload) UploadCard(ctx context.Context, r io.ReadCloser, state *pipeline.State, stepName string) error {
func (s *Upload) UploadCard(ctx context.Context, bytes []byte, state *pipeline.State, stepName string) error {
src := state.Find(stepName)
bytes, err := io.ReadAll(r)
if err != nil {
return err
}
card := drone.CardInput{}
err = json.Unmarshal(bytes, &card)
err := json.Unmarshal(bytes, &card)
if err != nil {
return err
}

Loading…
Cancel
Save