This commit is contained in:
Fedor Korotkiy 2020-03-23 23:58:08 +03:00
parent 5f0bb90e2c
commit 6295c3f1a4
8 changed files with 113 additions and 17 deletions

View file

@ -0,0 +1,69 @@
package build
import (
"fmt"
"strings"
"text/template"
)
type JobContext struct {
SourceDir string
OutputDir string
Deps map[ID]string
}
// Render replaces variable references with their real value.
func (c *Cmd) Render(ctx JobContext) (*Cmd, error) {
var errs []error
var fixedCtx struct {
SourceDir string
OutputDir string
Deps map[string]string
}
fixedCtx.SourceDir = ctx.SourceDir
fixedCtx.OutputDir = ctx.OutputDir
fixedCtx.Deps = map[string]string{}
for k, v := range ctx.Deps {
fixedCtx.Deps[k.String()] = v
}
render := func(str string) string {
t, err := template.New("").Parse(str)
if err != nil {
errs = append(errs, err)
return ""
}
var b strings.Builder
if err := t.Execute(&b, fixedCtx); err != nil {
errs = append(errs, err)
return ""
}
return b.String()
}
renderList := func(l []string) []string {
var result []string
for _, in := range l {
result = append(result, render(in))
}
return result
}
var rendered Cmd
rendered.CatOutput = render(c.CatOutput)
rendered.CatTemplate = render(c.CatTemplate)
rendered.WorkingDirectory = render(c.WorkingDirectory)
rendered.Exec = renderList(c.Exec)
rendered.Environ = renderList(c.Environ)
if len(errs) != 0 {
return nil, fmt.Errorf("error rendering cmd: %w", errs[0])
}
return &rendered, nil
}

View file

@ -0,0 +1,31 @@
package build
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestCmdRender(t *testing.T) {
tmpl := Cmd{
CatOutput: "{{.OutputDir}}/import.map",
CatTemplate: `bytes={{index .Deps "6100000000000000000000000000000000000000"}}/lib.a`,
}
ctx := JobContext{
OutputDir: "/distbuild/jobs/b",
Deps: map[ID]string{
{'a'}: "/distbuild/jobs/a",
},
}
result, err := tmpl.Render(ctx)
require.NoError(t, err)
expected := &Cmd{
CatOutput: "/distbuild/jobs/b/import.map",
CatTemplate: "bytes=/distbuild/jobs/a/lib.a",
}
require.Equal(t, expected, result)
}

View file

@ -83,9 +83,9 @@ type Job struct {
// Все строки в описании команды могут содержать в себе на переменные. Перед выполнением // Все строки в описании команды могут содержать в себе на переменные. Перед выполнением
// реальной команды, переменные заменяются на их реальные значения. // реальной команды, переменные заменяются на их реальные значения.
// //
// {{OUTPUT_DIR}} - абсолютный путь до выходной директории джоба. // {{.OutputDir}} - абсолютный путь до выходной директории джоба.
// {{SOURCE_DIR}} - абсолютный путь до директории с исходными файлами. // {{.SourceDir}} - абсолютный путь до директории с исходными файлами.
// {{DEP:f374b81d81f641c8c3d5d5468081ef83b2c7dae9}} - абсолютный путь до директории, // {{index .Deps "f374b81d81f641c8c3d5d5468081ef83b2c7dae9"}} - абсолютный путь до директории,
// содержащей выход джоба с id f374b81d81f641c8c3d5d5468081ef83b2c7dae9. // содержащей выход джоба с id f374b81d81f641c8c3d5d5468081ef83b2c7dae9.
type Cmd struct { type Cmd struct {
// Exec описывает команду, которую нужно выполнить. // Exec описывает команду, которую нужно выполнить.
@ -104,10 +104,6 @@ type Cmd struct {
CatOutput string CatOutput string
} }
func (cmd Cmd) Render(outputDir, sourceDir string, deps map[ID]string) Cmd {
panic("implement me")
}
type Graph struct { type Graph struct {
SourceFiles map[ID]string SourceFiles map[ID]string

View file

@ -9,7 +9,7 @@ import (
type scheduledJob struct { type scheduledJob struct {
job *build.Job job *build.Job
finished *proto.FinishedJob finished *proto.JobResult
mu sync.Mutex mu sync.Mutex
done chan struct{} done chan struct{}
@ -22,7 +22,7 @@ func newScheduledJob(job *build.Job) *scheduledJob {
} }
} }
func (s *scheduledJob) finish(f *proto.FinishedJob) { func (s *scheduledJob) finish(f *proto.JobResult) {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()

View file

@ -9,7 +9,7 @@ type MissingSources struct {
} }
type StatusUpdate struct { type StatusUpdate struct {
JobFinished *FinishedJob JobFinished *JobResult
BuildFailed *BuildFailed BuildFailed *BuildFailed
BuildFinished *BuildFinished BuildFinished *BuildFinished
} }

View file

@ -4,8 +4,8 @@ import (
"gitlab.com/slon/shad-go/distbuild/pkg/build" "gitlab.com/slon/shad-go/distbuild/pkg/build"
) )
// CompleteJob описывает результат работы джоба. // JobResult описывает результат работы джоба.
type FinishedJob struct { type JobResult struct {
ID build.ID ID build.ID
Stdout, Stderr []byte Stdout, Stderr []byte
@ -44,9 +44,9 @@ type HeartbeatRequest struct {
// FreeSlots сообщаяет, сколько еще процессов можно запустить на этом воркере. // FreeSlots сообщаяет, сколько еще процессов можно запустить на этом воркере.
FreeSlots int FreeSlots int
// FinishedJob сообщает координатору, какие джобы завершили исполнение на этом воркере // JobResult сообщает координатору, какие джобы завершили исполнение на этом воркере
// на этой итерации цикла. // на этой итерации цикла.
FinishedJob []FinishedJob FinishedJob []JobResult
// AddedArtifacts говорит, какие артефакты появились в кеше на этой итерации цикла. // AddedArtifacts говорит, какие артефакты появились в кеше на этой итерации цикла.
AddedArtifacts []build.ID AddedArtifacts []build.ID

View file

@ -18,7 +18,7 @@ func (w *Worker) buildHeartbeat() *proto.HeartbeatRequest {
return req return req
} }
func (w *Worker) jobFinished(job *proto.FinishedJob) { func (w *Worker) jobFinished(job *proto.JobResult) {
w.log.Debug("job finished", zap.String("job_id", job.ID.String())) w.log.Debug("job finished", zap.String("job_id", job.ID.String()))
w.mu.Lock() w.mu.Lock()

View file

@ -31,7 +31,7 @@ type Worker struct {
mu sync.Mutex mu sync.Mutex
newArtifacts []build.ID newArtifacts []build.ID
newSources []build.ID newSources []build.ID
finishedJobs []proto.FinishedJob finishedJobs []proto.JobResult
} }
func New( func New(
@ -118,7 +118,7 @@ func (w *Worker) Run(ctx context.Context) error {
zap.Int("num_jobs", len(rsp.JobsToRun))) zap.Int("num_jobs", len(rsp.JobsToRun)))
for _, job := range rsp.JobsToRun { for _, job := range rsp.JobsToRun {
var finished proto.FinishedJob var finished proto.JobResult
finished.ID = job.Job.ID finished.ID = job.Job.ID
var stdout bytes.Buffer var stdout bytes.Buffer