Add artifact workdir layout and locking
This commit is contained in:
@@ -13,7 +13,8 @@ import (
|
||||
)
|
||||
|
||||
func TestExecuteValidCommands(t *testing.T) {
|
||||
pipelinePath, sessionPath := writeValidConfigFiles(t)
|
||||
workspaceRoot := t.TempDir()
|
||||
pipelinePath, sessionPath := writeValidConfigFiles(t, workspaceRoot)
|
||||
manifestPath := writeManifestPathForExecute(t)
|
||||
|
||||
cases := []struct {
|
||||
@@ -22,7 +23,7 @@ func TestExecuteValidCommands(t *testing.T) {
|
||||
wantOut string
|
||||
}{
|
||||
{name: "run", args: []string{"run", "--config", pipelinePath, "--session", sessionPath}, wantOut: "narratio run: configuration loaded and valid"},
|
||||
{name: "plan", args: []string{"plan", "--config", pipelinePath, "--session", sessionPath}, wantOut: "narratio plan: configuration loaded and valid"},
|
||||
{name: "plan", args: []string{"plan", "--config", pipelinePath, "--session", sessionPath}, wantOut: "narratio plan: configuration loaded and valid; workdir prepared at"},
|
||||
{name: "status", args: []string{"status", "--manifest", manifestPath}, wantOut: "session_id: 2026-05-03"},
|
||||
{name: "resume", args: []string{"resume"}, wantOut: "narratio resume: not yet implemented"},
|
||||
{name: "run-stage", args: []string{"run-stage", "polish"}, wantOut: "narratio run-stage: not yet implemented"},
|
||||
@@ -113,7 +114,7 @@ func TestExecuteMissingCommand(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func writeValidConfigFiles(t *testing.T) (string, string) {
|
||||
func writeValidConfigFiles(t *testing.T, workspaceRoot string) (string, string) {
|
||||
t.Helper()
|
||||
|
||||
dir := t.TempDir()
|
||||
@@ -121,7 +122,7 @@ func writeValidConfigFiles(t *testing.T) (string, string) {
|
||||
sessionPath := filepath.Join(dir, "session.yml")
|
||||
|
||||
pipelineYAML := `workspace:
|
||||
root: /tmp/narratio
|
||||
root: ` + workspaceRoot + `
|
||||
storage:
|
||||
backend: s3
|
||||
whisperx:
|
||||
|
||||
@@ -6,10 +6,11 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"gitea.maximumdirect.net/eric/narratio/internal/artifacts"
|
||||
"gitea.maximumdirect.net/eric/narratio/internal/config"
|
||||
)
|
||||
|
||||
// Plan validates configuration inputs and reports readiness for future planning.
|
||||
// Plan validates configuration inputs and prepares the local session workdir.
|
||||
func Plan(_ context.Context, args []string, out io.Writer) error {
|
||||
fs := flag.NewFlagSet("plan", flag.ContinueOnError)
|
||||
fs.SetOutput(io.Discard)
|
||||
@@ -37,6 +38,12 @@ func Plan(_ context.Context, args []string, out io.Writer) error {
|
||||
return fmt.Errorf("plan: %w", err)
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintln(out, "narratio plan: configuration loaded and valid")
|
||||
store := artifacts.NewLocalStore(cfg.Pipeline.Workspace.Root)
|
||||
paths, err := store.EnsureLayout(cfg.Session.SessionID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("plan: prepare workdir: %w", err)
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintf(out, "narratio plan: configuration loaded and valid; workdir prepared at %s\n", paths.Root)
|
||||
return err
|
||||
}
|
||||
|
||||
61
internal/app/plan_test.go
Normal file
61
internal/app/plan_test.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gitea.maximumdirect.net/eric/narratio/internal/artifacts"
|
||||
)
|
||||
|
||||
func TestPlanCreatesAndReusesWorkdir(t *testing.T) {
|
||||
workspaceRoot := t.TempDir()
|
||||
pipelinePath, sessionPath := writeValidConfigFiles(t, workspaceRoot)
|
||||
|
||||
var out bytes.Buffer
|
||||
args := []string{"--config", pipelinePath, "--session", sessionPath}
|
||||
|
||||
if err := Plan(context.Background(), args, &out); err != nil {
|
||||
t.Fatalf("first Plan() error = %v", err)
|
||||
}
|
||||
if !strings.Contains(out.String(), "workdir prepared") {
|
||||
t.Fatalf("first output = %q, want workdir prepared", out.String())
|
||||
}
|
||||
|
||||
sessionWorkdir := artifacts.SessionWorkDir(workspaceRoot, "2026-05-03")
|
||||
expectedDirs := []string{
|
||||
sessionWorkdir,
|
||||
filepath.Join(sessionWorkdir, "inputs"),
|
||||
filepath.Join(sessionWorkdir, "audio"),
|
||||
filepath.Join(sessionWorkdir, "transcripts", "raw"),
|
||||
filepath.Join(sessionWorkdir, "transcripts", "normalized"),
|
||||
filepath.Join(sessionWorkdir, "artifacts"),
|
||||
filepath.Join(sessionWorkdir, "config"),
|
||||
filepath.Join(sessionWorkdir, "logs"),
|
||||
}
|
||||
for _, dir := range expectedDirs {
|
||||
assertDir(t, dir)
|
||||
}
|
||||
|
||||
out.Reset()
|
||||
if err := Plan(context.Background(), args, &out); err != nil {
|
||||
t.Fatalf("second Plan() error = %v", err)
|
||||
}
|
||||
if !strings.Contains(out.String(), "workdir prepared") {
|
||||
t.Fatalf("second output = %q, want workdir prepared", out.String())
|
||||
}
|
||||
}
|
||||
|
||||
func assertDir(t *testing.T, path string) {
|
||||
t.Helper()
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
t.Fatalf("Stat(%q) error = %v", path, err)
|
||||
}
|
||||
if !info.IsDir() {
|
||||
t.Fatalf("%q is not a directory", path)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user