cmd

package
v0.0.0-...-f4f425e Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 1, 2025 License: Apache-2.0 Imports: 33 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	Diff = &cli.Command{
		Name:  "diff",
		Usage: "Generates a diff between a nominal and orch8rion-instrumented build. Use --build to execute a build first, or provide a work directory path obtained from `orch8rion go build -work -a`. This is incompatible with coverage related flags.",
		Args:  true,
		Flags: []cli.Flag{
			&filenameFlag,
			&filterFlag,
			&packageFlag,
			&debugFlag,
			&buildFlag,
			&noCacheFlag,
		},
		Action: func(clictx *cli.Context) error {
			workFolder, err := workFolder(clictx)
			if err != nil {
				return err
			}

			report, err := report.FromWorkDir(clictx.Context, workFolder)
			if err != nil {
				return cli.Exit(fmt.Sprintf("failed to read work dir: %s (did you forgot the -work flag during build ?)", err), 1)
			}

			if report.IsEmpty() {
				return cli.Exit("no files to diff (did you forgot the -a flag during build?)", 1)
			}

			if !clictx.Bool(debugFlag.Name) {
				report = report.WithSpecialCasesFilter()
			}

			if filter := clictx.String(filterFlag.Name); filter != "" {
				report, err = report.WithRegexFilter(filter)
				if err != nil {
					return cli.Exit(fmt.Sprintf("failed to filter files: %s", err), 1)
				}
			}

			return outputReport(clictx, report)
		},
	}
)
View Source
var (
	Go = &cli.Command{
		Name:            "go",
		Usage:           "Executes standard go commands with automatic instrumentation enabled",
		UsageText:       "orch8rion go [go command arguments...]",
		Args:            true,
		SkipFlagParsing: true,
		Action: func(clictx *cli.Context) (err error) {
			span, ctx := tracer.StartSpanFromContext(clictx.Context, "go",
				tracer.ResourceName(strings.Join(clictx.Args().Slice(), " ")),
			)
			defer func() { span.Finish(tracer.WithError(err)) }()

			if err := pin.AutoPinOrch8rion(ctx, clictx.App.Writer, clictx.App.ErrWriter); err != nil {
				return cli.Exit(err, -1)
			}

			if err := goproxy.Run(ctx, clictx.Args().Slice(), goproxy.WithToolexec(binpath.Orch8rion, "toolexec")); err != nil {
				var exitErr *exec.ExitError
				if errors.As(err, &exitErr) {
					return cli.Exit(err, exitErr.ExitCode())
				}
				return cli.Exit(err, -1)
			}
			return nil
		},
	}
)
View Source
var Lint = &cli.Command{
	Name:            "lint",
	Usage:           "Run selected static analysis checks on Go code for Orch8rion to work better for certain features.",
	UsageText:       "orch8rion lint [lint arguments...]",
	Args:            true,
	SkipFlagParsing: true,
	Action: func(clictx *cli.Context) (err error) {
		span, _ := tracer.StartSpanFromContext(clictx.Context, "lint",
			tracer.ResourceName(strings.Join(clictx.Args().Slice(), " ")),
		)
		defer func() { span.Finish(tracer.WithError(err)) }()

		args := clictx.Args().Slice()
		if slices.Contains(args, "-help") || slices.Contains(args, "--help") || slices.Contains(args, "-h") {
			tmpl := template.Must(template.New("help").Parse(cli.CommandHelpTemplate))
			if err := tmpl.Execute(os.Stdout, clictx.Command); err != nil {

				fmt.Fprintf(clictx.App.Writer, "NAME:\n   orch8rion lint - %s\n\n", clictx.Command.Usage)
				fmt.Fprintf(clictx.App.Writer, "USAGE:\n   %s\n\n", clictx.Command.UsageText)
				fmt.Fprintln(clictx.App.Writer)
			}
		}

		args = append([]string{"orch8rion-lint"}, args...)
		os.Args = args

		analyzers := []*analysis.Analyzer{
			errorlint.NewAnalyzer(
				errorlint.WithComparison(true),
				errorlint.WithAsserts(true),
			),
		}
		multichecker.Main(analyzers...)

		return nil
	},
}
View Source
var Pin = &cli.Command{
	Name:  "pin",
	Usage: "Registers orch8rion in your project's `go.mod` file",
	Flags: []cli.Flag{
		&cli.BoolFlag{
			Name:  "generate",
			Usage: "Add a //go:generate directive to " + config.FilenameOrch8rionToolGo + " to facilitate automated upkeep of its contents.",
			Value: true,
		},
		&cli.BoolFlag{
			Name:  "prune",
			Usage: "Remove imports from " + config.FilenameOrch8rionToolGo + " that do not contain any orch8rion integrations.",
			Value: true,
		},
		&cli.BoolFlag{
			Name:  "validate",
			Usage: "Validate all " + config.FilenameOrch8rionYML + " files in the project.",
			Value: false,
		},
	},
	Action: func(clictx *cli.Context) (err error) {
		span, ctx := tracer.StartSpanFromContext(clictx.Context, "pin",
			tracer.ResourceName(strings.Join(clictx.Args().Slice(), " ")),
		)
		defer func() { span.Finish(tracer.WithError(err)) }()

		return pin.PinOrch8rion(ctx, pin.Options{
			Writer:     clictx.App.Writer,
			ErrWriter:  clictx.App.ErrWriter,
			Validate:   clictx.Bool("validate"),
			NoGenerate: !clictx.Bool("generate"),
			NoPrune:    !clictx.Bool("prune"),
		})
	},
}
View Source
var Server = &cli.Command{
	Name:        "server",
	Usage:       "Start an Objectsrion job server.",
	Description: "The job server is used to remove duplicated processing that can occur when instrumenting large applications, due to how Orch8rion injects new dependencies that the go toolchain was initially not aware of.\n\nUsers do not normally need to use this command directly, as Orch8rion automatically manages servers during runtime.",
	Flags: []cli.Flag{
		&cli.StringFlag{
			Name:  "url-file",
			Usage: "Write a file containing the ClientURL for this server once it is ready to accept connections. The server automatically shuts down when the URL file is deleted.",
		},
		&cli.IntFlag{
			Name:        "port",
			Usage:       "Choose a port to listen on.",
			Value:       -1,
			DefaultText: "random",
		},
		&cli.DurationFlag{
			Name:  "inactivity-timeout",
			Usage: "Automatically shut down after a period without any connected client.",
			Value: time.Minute,
		},
		&cli.BoolFlag{
			Name:  "nats-logging",
			Usage: "Enable NATS server logging.",
		},
		&cli.StringFlag{
			Name:        "build-flags",
			Usage:       "Specify the 'go build' flags to use when resolving packages. This is specified as a YAML array and must start with a valid go subcommand (e.g, 'build').",
			DefaultText: "Looked up the process hierarchy",
			Action: func(ctx *cli.Context, val string) error {
				var args []string
				if err := yaml.Unmarshal([]byte(val), &args); err != nil {
					return cli.Exit(fmt.Errorf("invalid -build-flags value: %w", err), 2)
				}
				goflags.SetFlags(ctx.Context, ".", args)
				return nil
			},
		},
		&cli.IntFlag{
			Name:        "parent-pid",
			Usage:       "Specify which process created this server. This is useful when the server is started as a daemon, as it needs to be able to resolve the top-level go command line.",
			DefaultText: "This process' parent (may be inaccurate if the process is daemonized)",
			Action: func(ctx *cli.Context, val int) error {
				return goflags.SetFlagsFromPid(ctx.Context, val)
			},
		},
	},
	Hidden: true,
	Action: func(ctx *cli.Context) error {
		log := zerolog.Ctx(ctx.Context)

		opts := jobserver.Options{
			Port:              ctx.Int("port"),
			InactivityTimeout: ctx.Duration("inactivity-timeout"),
			EnableLogging:     ctx.Bool("nats-logging"),
		}

		if urlFile := ctx.String("url-file"); urlFile != "" {
			if err := startWithURLFile(ctx.Context, &opts, urlFile); err != nil {
				log.Error().Err(err).Str("url-file", urlFile).Msg("Failed to start job server")
			}
			return nil
		}
		_, err := start(ctx.Context, &opts, true)
		if err != nil {
			log.Error().Err(err).Msg("Failed to start job server")
		}
		return err
	},
}
View Source
var Toolexec = &cli.Command{
	Name:            "toolexec",
	Usage:           "Standard `-toolexec` plugin for the Go toolchain",
	UsageText:       "orch8rion toolexec [tool] [tool args...]",
	Args:            true,
	SkipFlagParsing: true,
	Action: func(clictx *cli.Context) (resErr error) {
		log := zerolog.Ctx(clictx.Context)
		importPath := os.Getenv("TOOLEXEC_IMPORTPATH")

		span, ctx := tracer.StartSpanFromContext(clictx.Context, "toolexec",
			tracer.ResourceName(strings.Join(clictx.Args().Slice(), " ")),
		)
		defer func() { span.Finish(tracer.WithError(resErr)) }()

		proxyCmd, err := proxy.ParseCommand(ctx, importPath, clictx.Args().Slice())
		if err != nil || proxyCmd == nil {

			return err
		}
		defer func() { proxyCmd.Close(ctx, resErr) }()

		if proxyCmd.Type() == proxy.CommandTypeOther {

			err := proxy.RunCommand(ctx, proxyCmd)
			var event *zerolog.Event
			if err != nil {
				event = log.Error().Err(err)
			} else {
				event = log.Trace()
			}
			event.Strs("command", proxyCmd.Args()).Msg("Toolexec fast-forward command")
			return err
		}

		if err := pin.AutoPinOrch8rion(ctx, clictx.App.Writer, clictx.App.ErrWriter); err != nil {
			return cli.Exit(err, -1)
		}

		if proxyCmd.ShowVersion() {
			log.Trace().Strs("command", proxyCmd.Args()).Msg("Toolexec version command")
			fullVersion, err := toolexec.ComputeVersion(ctx, proxyCmd)
			if err != nil {
				return err
			}
			log.Trace().Str("version", fullVersion).Msg("Complete version output")
			_, err = fmt.Println(fullVersion)
			return err
		}

		log.Debug().Strs("command", proxyCmd.Args()).Msg("Toolexec original command")
		weaver := aspect.Weaver{ImportPath: importPath}

		if err := proxy.ProcessCommand(ctx, proxyCmd, weaver.OnCompile); errors.Is(err, proxy.ErrSkipCommand) {
			log.Trace().Msg("OnCompile processor requested command skipping...")
			return nil
		} else if err != nil {
			return err
		}
		if err := proxy.ProcessCommand(ctx, proxyCmd, weaver.OnCompileMain); errors.Is(err, proxy.ErrSkipCommand) {
			log.Trace().Msg("OnCompileMain processor requested command skipping...")
			return nil
		} else if err != nil {
			return err
		}
		if err := proxy.ProcessCommand(ctx, proxyCmd, weaver.OnLink); errors.Is(err, proxy.ErrSkipCommand) {
			log.Trace().Msg("OnLink processor requested command skipping...")
			return nil
		} else if err != nil {
			return err
		}

		log.Debug().Strs("command", proxyCmd.Args()).Msg("Toolexec final command")
		if err := proxy.RunCommand(ctx, proxyCmd); err != nil {

			log.Error().Strs("command", proxyCmd.Args()).Err(err).Msg("Proxied command failed")
			return err
		}
		return nil
	},
}
View Source
var Version = &cli.Command{
	Name:  "version",
	Usage: "Displays this command's version information",
	Flags: []cli.Flag{
		&cli.BoolFlag{
			Name:   "static",
			Usage:  "only display the static version tag, ignoring build information baked into the binary",
			Hidden: true,
		},
		&cli.BoolFlag{
			Name:    "verbose",
			Aliases: []string{"v"},
			Usage:   "display the version of the orch8rion binary that started this command (if different from the current)",
			Hidden:  true,
		},
	},
	Action: func(c *cli.Context) error {
		tag := version.Tag()
		if c.Bool("static") {
			tag, _ = version.TagInfo()
		}
		if _, err := fmt.Fprintf(c.App.Writer, "orch8rion %s", tag); err != nil {
			return err
		}

		if c.Bool("verbose") {
			if _, err := fmt.Fprintf(c.App.Writer, " built with %s (%s/%s)", runtime.Version(), runtime.GOOS, runtime.GOARCH); err != nil {
				return err
			}
		}

		_, err := fmt.Fprintln(c.App.Writer)
		return err
	},
}

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL