diff --git a/distbuild/pkg/build/cmd.go b/distbuild/pkg/build/cmd.go new file mode 100644 index 0000000..866a5c4 --- /dev/null +++ b/distbuild/pkg/build/cmd.go @@ -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 +} diff --git a/distbuild/pkg/build/cmd_test.go b/distbuild/pkg/build/cmd_test.go new file mode 100644 index 0000000..a45ba70 --- /dev/null +++ b/distbuild/pkg/build/cmd_test.go @@ -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) +} diff --git a/distbuild/pkg/build/graph.go b/distbuild/pkg/build/graph.go index af2d1fc..860d973 100644 --- a/distbuild/pkg/build/graph.go +++ b/distbuild/pkg/build/graph.go @@ -83,9 +83,9 @@ type Job struct { // Все строки в описании команды могут содержать в себе на переменные. Перед выполнением // реальной команды, переменные заменяются на их реальные значения. // -// {{OUTPUT_DIR}} - абсолютный путь до выходной директории джоба. -// {{SOURCE_DIR}} - абсолютный путь до директории с исходными файлами. -// {{DEP:f374b81d81f641c8c3d5d5468081ef83b2c7dae9}} - абсолютный путь до директории, +// {{.OutputDir}} - абсолютный путь до выходной директории джоба. +// {{.SourceDir}} - абсолютный путь до директории с исходными файлами. +// {{index .Deps "f374b81d81f641c8c3d5d5468081ef83b2c7dae9"}} - абсолютный путь до директории, // содержащей выход джоба с id f374b81d81f641c8c3d5d5468081ef83b2c7dae9. type Cmd struct { // Exec описывает команду, которую нужно выполнить. @@ -104,10 +104,6 @@ type Cmd struct { CatOutput string } -func (cmd Cmd) Render(outputDir, sourceDir string, deps map[ID]string) Cmd { - panic("implement me") -} - type Graph struct { SourceFiles map[ID]string diff --git a/distbuild/pkg/dist/schedule.go b/distbuild/pkg/dist/schedule.go index efaee15..0fccf30 100644 --- a/distbuild/pkg/dist/schedule.go +++ b/distbuild/pkg/dist/schedule.go @@ -9,7 +9,7 @@ import ( type scheduledJob struct { job *build.Job - finished *proto.FinishedJob + finished *proto.JobResult mu sync.Mutex 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() defer s.mu.Unlock() diff --git a/distbuild/pkg/proto/build.go b/distbuild/pkg/proto/build.go index 163ddd5..2b5bb7e 100644 --- a/distbuild/pkg/proto/build.go +++ b/distbuild/pkg/proto/build.go @@ -9,7 +9,7 @@ type MissingSources struct { } type StatusUpdate struct { - JobFinished *FinishedJob + JobFinished *JobResult BuildFailed *BuildFailed BuildFinished *BuildFinished } diff --git a/distbuild/pkg/proto/heartbeat.go b/distbuild/pkg/proto/heartbeat.go index c15f21d..adf5228 100644 --- a/distbuild/pkg/proto/heartbeat.go +++ b/distbuild/pkg/proto/heartbeat.go @@ -4,8 +4,8 @@ import ( "gitlab.com/slon/shad-go/distbuild/pkg/build" ) -// CompleteJob описывает результат работы джоба. -type FinishedJob struct { +// JobResult описывает результат работы джоба. +type JobResult struct { ID build.ID Stdout, Stderr []byte @@ -44,9 +44,9 @@ type HeartbeatRequest struct { // FreeSlots сообщаяет, сколько еще процессов можно запустить на этом воркере. FreeSlots int - // FinishedJob сообщает координатору, какие джобы завершили исполнение на этом воркере + // JobResult сообщает координатору, какие джобы завершили исполнение на этом воркере // на этой итерации цикла. - FinishedJob []FinishedJob + FinishedJob []JobResult // AddedArtifacts говорит, какие артефакты появились в кеше на этой итерации цикла. AddedArtifacts []build.ID diff --git a/distbuild/pkg/worker/state.go b/distbuild/pkg/worker/state.go index 1ac0042..528c4ec 100644 --- a/distbuild/pkg/worker/state.go +++ b/distbuild/pkg/worker/state.go @@ -18,7 +18,7 @@ func (w *Worker) buildHeartbeat() *proto.HeartbeatRequest { 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.mu.Lock() diff --git a/distbuild/pkg/worker/worker.go b/distbuild/pkg/worker/worker.go index c27c17d..df42e20 100644 --- a/distbuild/pkg/worker/worker.go +++ b/distbuild/pkg/worker/worker.go @@ -31,7 +31,7 @@ type Worker struct { mu sync.Mutex newArtifacts []build.ID newSources []build.ID - finishedJobs []proto.FinishedJob + finishedJobs []proto.JobResult } func New( @@ -118,7 +118,7 @@ func (w *Worker) Run(ctx context.Context) error { zap.Int("num_jobs", len(rsp.JobsToRun))) for _, job := range rsp.JobsToRun { - var finished proto.FinishedJob + var finished proto.JobResult finished.ID = job.Job.ID var stdout bytes.Buffer