From 418b7d5329d8d259f57bab0bf75589dd524dd2a5 Mon Sep 17 00:00:00 2001 From: Jake Coffman Date: Tue, 21 May 2024 14:12:07 -0500 Subject: [PATCH 01/11] hack: dependabot ls command --- cmd/dependabot/internal/cmd/ls.go | 91 +++++++++++++++++++++++++++++++ internal/infra/run.go | 15 +++++ internal/server/api.go | 16 ++++-- 3 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 cmd/dependabot/internal/cmd/ls.go diff --git a/cmd/dependabot/internal/cmd/ls.go b/cmd/dependabot/internal/cmd/ls.go new file mode 100644 index 00000000..e5ba43ac --- /dev/null +++ b/cmd/dependabot/internal/cmd/ls.go @@ -0,0 +1,91 @@ +package cmd + +import ( + "context" + "errors" + "github.com/MakeNowJust/heredoc" + "github.com/dependabot/cli/internal/infra" + "github.com/spf13/cobra" + "log" +) + +var listCmd = NewListCommand() + +func init() { + rootCmd.AddCommand(listCmd) +} + +func NewListCommand() *cobra.Command { + var flags UpdateFlags + + cmd := &cobra.Command{ + Use: "ls [ ] [flags]", + Short: "List the dependencies of a manifest/lockfile", + Example: heredoc.Doc(` + $ dependabot ls go_modules rsc/quote + $ dependabot ls go_modules --local . + `), + RunE: func(cmd *cobra.Command, args []string) error { + input, err := readArguments(cmd, &flags) + if err != nil { + return err + } + + processInput(input, &flags) + + input.Job.Source.Provider = "github" // TODO why isn't this being set? + + if err := infra.Run(infra.RunParams{ + CacheDir: flags.cache, + CollectorConfigPath: flags.collectorConfigPath, + CollectorImage: collectorImage, + Creds: input.Credentials, + Debug: flags.debugging, + Flamegraph: flags.flamegraph, + Expected: nil, // update subcommand doesn't use expectations + ExtraHosts: flags.extraHosts, + InputName: flags.file, + Job: &input.Job, + ListDependencies: true, // list dependencies, then exit + LocalDir: flags.local, + Output: flags.output, + ProxyCertPath: flags.proxyCertPath, + ProxyImage: proxyImage, + PullImages: flags.pullImages, + Timeout: flags.timeout, + UpdaterImage: updaterImage, + Volumes: flags.volumes, + Writer: nil, // prevent outputting all API responses to stdout, we only want dependencies + }); err != nil { + if errors.Is(err, context.DeadlineExceeded) { + log.Fatalf("update timed out after %s", flags.timeout) + } + // HACK: we cancel context to stop the containers, so we don't know if there was a failure. + // A correct solution would involve changes with dependabot-core, which is good, but + // I am just hacking this together right now. + // log.Fatalf("updater failure: %v", err) + return nil + } + + return nil + }, + } + + cmd.Flags().StringVarP(&flags.branch, "branch", "b", "", "target branch to update") + cmd.Flags().StringVarP(&flags.directory, "directory", "d", "/", "directory to update") + cmd.Flags().StringVarP(&flags.commit, "commit", "", "", "commit to update") + + cmd.Flags().StringVarP(&flags.output, "output", "o", "", "write scenario to file") + cmd.Flags().StringVar(&flags.cache, "cache", "", "cache import/export directory") + cmd.Flags().StringVar(&flags.local, "local", "", "local directory to use as fetched source") + cmd.Flags().StringVar(&flags.proxyCertPath, "proxy-cert", "", "path to a certificate the proxy will trust") + cmd.Flags().StringVar(&flags.collectorConfigPath, "collector-config", "", "path to an OpenTelemetry collector config file") + cmd.Flags().BoolVar(&flags.pullImages, "pull", true, "pull the image if it isn't present") + cmd.Flags().BoolVar(&flags.debugging, "debug", false, "run an interactive shell inside the updater") + cmd.Flags().BoolVar(&flags.flamegraph, "flamegraph", false, "generate a flamegraph and other metrics") + cmd.Flags().StringArrayVarP(&flags.volumes, "volume", "v", nil, "mount volumes in Docker") + cmd.Flags().StringArrayVar(&flags.extraHosts, "extra-hosts", nil, "Docker extra hosts setting on the proxy") + cmd.Flags().DurationVarP(&flags.timeout, "timeout", "t", 0, "max time to run an update") + + return cmd +} diff --git a/internal/infra/run.go b/internal/infra/run.go index be54b6d9..38967648 100644 --- a/internal/infra/run.go +++ b/internal/infra/run.go @@ -37,6 +37,8 @@ type RunParams struct { Job *model.Job // expectations asserted at the end of a test Expected []model.Output + // if true, the containers will be stopped once the dependencies are listed + ListDependencies bool // directory to copy into the updater container as the repo LocalDir string // credentials passed to the proxy @@ -113,6 +115,19 @@ func Run(params RunParams) error { api := server.NewAPI(params.Expected, params.Writer) defer api.Stop() + if params.ListDependencies { + go func() { + dependencyList := <-api.UpdateDependencyList + encoder := json.NewEncoder(os.Stdout) + encoder.SetIndent("", " ") + err := encoder.Encode(dependencyList.Dependencies) + if err != nil { + log.Printf("failed to write dependency list: %v\n", err) + } + cancel() + }() + } + var outFile *os.File if params.Output != "" { var err error diff --git a/internal/server/api.go b/internal/server/api.go index c2bb5bac..9a9bf97f 100644 --- a/internal/server/api.go +++ b/internal/server/api.go @@ -36,6 +36,9 @@ type API struct { hasExpectations bool port int writer io.Writer + + // UpdateDependencyList is a channel you can listen on to get the dependencies as soon as they're published + UpdateDependencyList chan model.UpdateDependencyList } // NewAPI creates a new API instance and starts the server @@ -67,12 +70,13 @@ func NewAPI(expected []model.Output, writer io.Writer) *API { IdleTimeout: 60 * time.Second, } api := &API{ - server: server, - Expectations: expected, - writer: writer, - cursor: 0, - hasExpectations: len(expected) > 0, - port: l.Addr().(*net.TCPAddr).Port, + server: server, + Expectations: expected, + writer: writer, + cursor: 0, + hasExpectations: len(expected) > 0, + port: l.Addr().(*net.TCPAddr).Port, + UpdateDependencyList: make(chan model.UpdateDependencyList, 1), // buffer of 1 to prevent blocking } server.Handler = api From f829eae58ad6fe9c0b1da302f37c9eb193562e49 Mon Sep 17 00:00:00 2001 From: Barry Gordon Date: Thu, 7 Aug 2025 18:03:44 +0100 Subject: [PATCH 02/11] Introduce Command to run params --- internal/infra/run.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/internal/infra/run.go b/internal/infra/run.go index 38967648..fe57bcdf 100644 --- a/internal/infra/run.go +++ b/internal/infra/run.go @@ -30,9 +30,23 @@ import ( "gopkg.in/yaml.v3" ) +type RunCommand int + +const ( + UpdateCommand RunCommand = iota + AnalyseCommand +) + +var runCmds = map[RunCommand]string{ + UpdateCommand: "bin/run fetch_files && bin/run update_files", + AnalyseCommand: "bin/run fetch_files && bin/run analyse_files", +} + type RunParams struct { // Input file Input string + // Which command to use, this will default to UpdateCommand + Command RunCommand // job definition passed to the updater Job *model.Job // expectations asserted at the end of a test @@ -467,8 +481,7 @@ func runContainers(ctx context.Context, params RunParams) (err error) { if params.Flamegraph { env = append(env, "FLAMEGRAPH=1") } - const cmd = "bin/run fetch_files && bin/run update_files" - if err := updater.RunCmd(ctx, cmd, dependabot, env...); err != nil { + if err := updater.RunCmd(ctx, runCmds[params.Command], dependabot, env...); err != nil { return err } if params.Flamegraph { From 70434821d419de14353b5e2ff7e8c2ca2949fd49 Mon Sep 17 00:00:00 2001 From: Barry Gordon Date: Thu, 7 Aug 2025 18:05:49 +0100 Subject: [PATCH 03/11] Use AnalyseCommand in ls --- cmd/dependabot/internal/cmd/ls.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmd/dependabot/internal/cmd/ls.go b/cmd/dependabot/internal/cmd/ls.go index e5ba43ac..6ef14967 100644 --- a/cmd/dependabot/internal/cmd/ls.go +++ b/cmd/dependabot/internal/cmd/ls.go @@ -3,10 +3,11 @@ package cmd import ( "context" "errors" + "log" + "github.com/MakeNowJust/heredoc" "github.com/dependabot/cli/internal/infra" "github.com/spf13/cobra" - "log" ) var listCmd = NewListCommand() @@ -36,6 +37,7 @@ func NewListCommand() *cobra.Command { input.Job.Source.Provider = "github" // TODO why isn't this being set? if err := infra.Run(infra.RunParams{ + Command: infra.AnalyseCommand, CacheDir: flags.cache, CollectorConfigPath: flags.collectorConfigPath, CollectorImage: collectorImage, From 8dcd35499386f8b4c665cd2b94b3f76a9d77fce5 Mon Sep 17 00:00:00 2001 From: Barry Gordon Date: Thu, 7 Aug 2025 18:10:52 +0100 Subject: [PATCH 04/11] Prefer graph to ls --- cmd/dependabot/internal/cmd/{ls.go => graph.go} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename cmd/dependabot/internal/cmd/{ls.go => graph.go} (96%) diff --git a/cmd/dependabot/internal/cmd/ls.go b/cmd/dependabot/internal/cmd/graph.go similarity index 96% rename from cmd/dependabot/internal/cmd/ls.go rename to cmd/dependabot/internal/cmd/graph.go index 6ef14967..83897b5d 100644 --- a/cmd/dependabot/internal/cmd/ls.go +++ b/cmd/dependabot/internal/cmd/graph.go @@ -20,11 +20,11 @@ func NewListCommand() *cobra.Command { var flags UpdateFlags cmd := &cobra.Command{ - Use: "ls [ ] [flags]", + Use: "graph [ ] [flags]", Short: "List the dependencies of a manifest/lockfile", Example: heredoc.Doc(` - $ dependabot ls go_modules rsc/quote - $ dependabot ls go_modules --local . + $ dependabot graph go_modules rsc/quote + $ dependabot graph go_modules --local . `), RunE: func(cmd *cobra.Command, args []string) error { input, err := readArguments(cmd, &flags) From ba7aaaf7e7059360ecc73035815fb44bc940d973 Mon Sep 17 00:00:00 2001 From: Barry Gordon Date: Fri, 8 Aug 2025 12:16:11 +0100 Subject: [PATCH 05/11] AnalyseCommand is now UpdateGraphCommand everywhere --- cmd/dependabot/internal/cmd/graph.go | 2 +- internal/infra/run.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/dependabot/internal/cmd/graph.go b/cmd/dependabot/internal/cmd/graph.go index 83897b5d..47d4368f 100644 --- a/cmd/dependabot/internal/cmd/graph.go +++ b/cmd/dependabot/internal/cmd/graph.go @@ -37,7 +37,7 @@ func NewListCommand() *cobra.Command { input.Job.Source.Provider = "github" // TODO why isn't this being set? if err := infra.Run(infra.RunParams{ - Command: infra.AnalyseCommand, + Command: infra.UpdateGraphCommand, CacheDir: flags.cache, CollectorConfigPath: flags.collectorConfigPath, CollectorImage: collectorImage, diff --git a/internal/infra/run.go b/internal/infra/run.go index fe57bcdf..3fddf35c 100644 --- a/internal/infra/run.go +++ b/internal/infra/run.go @@ -33,13 +33,13 @@ import ( type RunCommand int const ( - UpdateCommand RunCommand = iota - AnalyseCommand + UpdateFilesCommand RunCommand = iota + UpdateGraphCommand ) var runCmds = map[RunCommand]string{ - UpdateCommand: "bin/run fetch_files && bin/run update_files", - AnalyseCommand: "bin/run fetch_files && bin/run analyse_files", + UpdateFilesCommand: "bin/run fetch_files && bin/run update_files", + UpdateGraphCommand: "bin/run fetch_files && bin/run update_graph", } type RunParams struct { From 66f88b07004aeec004e7d211a7682cfc99a3c853 Mon Sep 17 00:00:00 2001 From: Barry Gordon Date: Fri, 8 Aug 2025 12:28:49 +0100 Subject: [PATCH 06/11] Remove a few last pieces of the initial ls cmd --- cmd/dependabot/internal/cmd/graph.go | 7 +++---- internal/infra/run.go | 15 --------------- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/cmd/dependabot/internal/cmd/graph.go b/cmd/dependabot/internal/cmd/graph.go index 47d4368f..725ad9f5 100644 --- a/cmd/dependabot/internal/cmd/graph.go +++ b/cmd/dependabot/internal/cmd/graph.go @@ -10,13 +10,13 @@ import ( "github.com/spf13/cobra" ) -var listCmd = NewListCommand() +var graphCmd = NewGraphCommand() func init() { - rootCmd.AddCommand(listCmd) + rootCmd.AddCommand(graphCmd) } -func NewListCommand() *cobra.Command { +func NewGraphCommand() *cobra.Command { var flags UpdateFlags cmd := &cobra.Command{ @@ -48,7 +48,6 @@ func NewListCommand() *cobra.Command { ExtraHosts: flags.extraHosts, InputName: flags.file, Job: &input.Job, - ListDependencies: true, // list dependencies, then exit LocalDir: flags.local, Output: flags.output, ProxyCertPath: flags.proxyCertPath, diff --git a/internal/infra/run.go b/internal/infra/run.go index 3fddf35c..1dd5796e 100644 --- a/internal/infra/run.go +++ b/internal/infra/run.go @@ -51,8 +51,6 @@ type RunParams struct { Job *model.Job // expectations asserted at the end of a test Expected []model.Output - // if true, the containers will be stopped once the dependencies are listed - ListDependencies bool // directory to copy into the updater container as the repo LocalDir string // credentials passed to the proxy @@ -129,19 +127,6 @@ func Run(params RunParams) error { api := server.NewAPI(params.Expected, params.Writer) defer api.Stop() - if params.ListDependencies { - go func() { - dependencyList := <-api.UpdateDependencyList - encoder := json.NewEncoder(os.Stdout) - encoder.SetIndent("", " ") - err := encoder.Encode(dependencyList.Dependencies) - if err != nil { - log.Printf("failed to write dependency list: %v\n", err) - } - cancel() - }() - } - var outFile *os.File if params.Output != "" { var err error From 49dca376c2c3481c1723356791f994cb156458c1 Mon Sep 17 00:00:00 2001 From: Barry Gordon Date: Fri, 8 Aug 2025 12:42:57 +0100 Subject: [PATCH 07/11] Align graph inputs with update subcmd --- cmd/dependabot/internal/cmd/graph.go | 43 ++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/cmd/dependabot/internal/cmd/graph.go b/cmd/dependabot/internal/cmd/graph.go index 725ad9f5..727d189f 100644 --- a/cmd/dependabot/internal/cmd/graph.go +++ b/cmd/dependabot/internal/cmd/graph.go @@ -3,7 +3,10 @@ package cmd import ( "context" "errors" + "fmt" + "io" "log" + "os" "github.com/MakeNowJust/heredoc" "github.com/dependabot/cli/internal/infra" @@ -20,21 +23,35 @@ func NewGraphCommand() *cobra.Command { var flags UpdateFlags cmd := &cobra.Command{ - Use: "graph [ ] [flags]", + Use: "graph [ | -f ] [flags]", Short: "List the dependencies of a manifest/lockfile", Example: heredoc.Doc(` - $ dependabot graph go_modules rsc/quote - $ dependabot graph go_modules --local . + $ dependabot graph bundler dependabot/dependabot-core + $ dependabot graph bundler --local . + $ dependabot graph -f input.yml `), RunE: func(cmd *cobra.Command, args []string) error { - input, err := readArguments(cmd, &flags) + var outFile *os.File + if flags.output != "" { + var err error + outFile, err = os.Create(flags.output) + if err != nil { + return fmt.Errorf("failed to create output file: %w", err) + } + defer outFile.Close() + } + + input, err := extractInput(cmd, &flags) if err != nil { return err } processInput(input, &flags) - input.Job.Source.Provider = "github" // TODO why isn't this being set? + var writer io.Writer + if !flags.debugging { + writer = os.Stdout + } if err := infra.Run(infra.RunParams{ Command: infra.UpdateGraphCommand, @@ -44,7 +61,7 @@ func NewGraphCommand() *cobra.Command { Creds: input.Credentials, Debug: flags.debugging, Flamegraph: flags.flamegraph, - Expected: nil, // update subcommand doesn't use expectations + Expected: nil, // graph subcommand doesn't use expectations ExtraHosts: flags.extraHosts, InputName: flags.file, Job: &input.Job, @@ -56,22 +73,22 @@ func NewGraphCommand() *cobra.Command { Timeout: flags.timeout, UpdaterImage: updaterImage, Volumes: flags.volumes, - Writer: nil, // prevent outputting all API responses to stdout, we only want dependencies + Writer: writer, + ApiUrl: flags.apiUrl, }); err != nil { if errors.Is(err, context.DeadlineExceeded) { log.Fatalf("update timed out after %s", flags.timeout) } - // HACK: we cancel context to stop the containers, so we don't know if there was a failure. - // A correct solution would involve changes with dependabot-core, which is good, but - // I am just hacking this together right now. - // log.Fatalf("updater failure: %v", err) - return nil + log.Fatalf("updater failure: %v", err) } return nil }, } + cmd.Flags().StringVarP(&flags.file, "file", "f", "", "path to input file") + + cmd.Flags().StringVarP(&flags.provider, "provider", "p", "github", "provider of the repository") cmd.Flags().StringVarP(&flags.branch, "branch", "b", "", "target branch to update") cmd.Flags().StringVarP(&flags.directory, "directory", "d", "/", "directory to update") cmd.Flags().StringVarP(&flags.commit, "commit", "", "", "commit to update") @@ -87,6 +104,8 @@ func NewGraphCommand() *cobra.Command { cmd.Flags().StringArrayVarP(&flags.volumes, "volume", "v", nil, "mount volumes in Docker") cmd.Flags().StringArrayVar(&flags.extraHosts, "extra-hosts", nil, "Docker extra hosts setting on the proxy") cmd.Flags().DurationVarP(&flags.timeout, "timeout", "t", 0, "max time to run an update") + cmd.Flags().IntVar(&flags.inputServerPort, "input-port", 0, "port to use for securely passing input to the updater") + cmd.Flags().StringVarP(&flags.apiUrl, "api-url", "a", "", "the api dependabot should connect to.") return cmd } From 1f975bca8ee43b4217c58bb8de6bb22d815d3348 Mon Sep 17 00:00:00 2001 From: Barry Gordon Date: Fri, 8 Aug 2025 13:10:54 +0100 Subject: [PATCH 08/11] Call graph subcmd out as experimental --- cmd/dependabot/internal/cmd/graph.go | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/cmd/dependabot/internal/cmd/graph.go b/cmd/dependabot/internal/cmd/graph.go index 727d189f..0c1198eb 100644 --- a/cmd/dependabot/internal/cmd/graph.go +++ b/cmd/dependabot/internal/cmd/graph.go @@ -7,12 +7,18 @@ import ( "io" "log" "os" + "slices" "github.com/MakeNowJust/heredoc" "github.com/dependabot/cli/internal/infra" "github.com/spf13/cobra" ) +var graphSupportedEcosystems = []string{ + "bundler", + "go_modules", +} + var graphCmd = NewGraphCommand() func init() { @@ -24,8 +30,13 @@ func NewGraphCommand() *cobra.Command { cmd := &cobra.Command{ Use: "graph [ | -f ] [flags]", - Short: "List the dependencies of a manifest/lockfile", + Short: "[Experimental] List the dependencies of a manifest/lockfile", Example: heredoc.Doc(` + NOTE: This command is a work in progress. + + It will only work with some package managers and the dependency list + may be incomplete. + $ dependabot graph bundler dependabot/dependabot-core $ dependabot graph bundler --local . $ dependabot graph -f input.yml @@ -48,6 +59,14 @@ func NewGraphCommand() *cobra.Command { processInput(input, &flags) + if !slices.Contains(graphSupportedEcosystems, input.Job.PackageManager) { + return fmt.Errorf( + "package manager '%s' is not supported for graphing. Supported ecosystems: %v", + input.Job.PackageManager, + graphSupportedEcosystems, + ) + } + var writer io.Writer if !flags.debugging { writer = os.Stdout From a72cb21c1657c06754083e2fc9c7367d23bae44f Mon Sep 17 00:00:00 2001 From: Barry Gordon Date: Fri, 8 Aug 2025 13:49:44 +0100 Subject: [PATCH 09/11] Properly handle calls to create_dependency_submission --- internal/model/update.go | 10 ++++++++++ internal/server/api.go | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/internal/model/update.go b/internal/model/update.go index 00286503..63d72093 100644 --- a/internal/model/update.go +++ b/internal/model/update.go @@ -29,6 +29,16 @@ type UpdatePullRequest struct { DependencyGroup map[string]any `json:"dependency-group" yaml:"dependency-group,omitempty"` } +type DependencySubmissionRequest struct { + Version int8 `json:"version" yaml:"version"` + Sha string `json:"sha" yaml:"sha"` + Ref string `json:"ref" yaml:"ref"` + Job map[string]any `json:"job" yaml:"job"` + Detector map[string]any `json:"detector" yaml:"detector"` + Scanned string `json:"scanned" yaml:"scanned"` + Manifests map[string]any `json:"manifests" yaml:"manifests"` +} + type DependencyFile struct { Content string `json:"content" yaml:"content"` ContentEncoding string `json:"content_encoding" yaml:"content_encoding"` diff --git a/internal/server/api.go b/internal/server/api.go index 9a9bf97f..2edbc42e 100644 --- a/internal/server/api.go +++ b/internal/server/api.go @@ -234,6 +234,8 @@ func decodeWrapper(kind string, data []byte) (actual *model.UpdateWrapper, err e actual.Data, err = decode[model.UpdateDependencyList](data) case "create_pull_request": actual.Data, err = decode[model.CreatePullRequest](data) + case "create_dependency_submission": + actual.Data, err = decode[model.DependencySubmissionRequest](data) case "update_pull_request": actual.Data, err = decode[model.UpdatePullRequest](data) case "close_pull_request": @@ -284,6 +286,11 @@ func decode[T any](data []byte) (T, error) { return wrapper.Data, nil } +// TODO(brrygrdn): Add model.DependencySubmissionRequest to support smoke tests +// +// The test command only expects to run with `update` operations right now so +// we will need to incorporate which run command is expected as well, but we +// don't need regression coverage yet. func compare(expect, actual *model.UpdateWrapper) error { switch v := expect.Data.(type) { case model.UpdateDependencyList: From 1840e6d2432cdf020191cb8673ae0cab256742fd Mon Sep 17 00:00:00 2001 From: Barry Gordon Date: Fri, 8 Aug 2025 13:50:11 +0100 Subject: [PATCH 10/11] Remove the dependency list channel as YAGNI --- internal/server/api.go | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/internal/server/api.go b/internal/server/api.go index 2edbc42e..20a05eb3 100644 --- a/internal/server/api.go +++ b/internal/server/api.go @@ -36,9 +36,6 @@ type API struct { hasExpectations bool port int writer io.Writer - - // UpdateDependencyList is a channel you can listen on to get the dependencies as soon as they're published - UpdateDependencyList chan model.UpdateDependencyList } // NewAPI creates a new API instance and starts the server @@ -70,13 +67,12 @@ func NewAPI(expected []model.Output, writer io.Writer) *API { IdleTimeout: 60 * time.Second, } api := &API{ - server: server, - Expectations: expected, - writer: writer, - cursor: 0, - hasExpectations: len(expected) > 0, - port: l.Addr().(*net.TCPAddr).Port, - UpdateDependencyList: make(chan model.UpdateDependencyList, 1), // buffer of 1 to prevent blocking + server: server, + Expectations: expected, + writer: writer, + cursor: 0, + hasExpectations: len(expected) > 0, + port: l.Addr().(*net.TCPAddr).Port, } server.Handler = api From 150ac1c800db2ea79d79d4a83b207ca658940f46 Mon Sep 17 00:00:00 2001 From: Barry Gordon <896971+brrygrdn@users.noreply.github.com> Date: Fri, 8 Aug 2025 14:12:43 +0100 Subject: [PATCH 11/11] Update RunCommand description --- internal/infra/run.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/infra/run.go b/internal/infra/run.go index 1dd5796e..933a82b8 100644 --- a/internal/infra/run.go +++ b/internal/infra/run.go @@ -45,7 +45,7 @@ var runCmds = map[RunCommand]string{ type RunParams struct { // Input file Input string - // Which command to use, this will default to UpdateCommand + // Which command to use, this will default to UpdateFilesCommand Command RunCommand // job definition passed to the updater Job *model.Job