Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core: add XCADDY_GO_MOD_FLAGS env var to allow passing custom go mod flags #113

Merged
merged 1 commit into from
Aug 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,9 @@ Because the subcommands and flags are constrained to benefit rapid plugin protot
- `XCADDY_SKIP_BUILD=1` causes xcaddy to not compile the program, it is used in conjunction with build tools such as [GoReleaser](https://goreleaser.com). Implies `XCADDY_SKIP_CLEANUP=1`.
- `XCADDY_SKIP_CLEANUP=1` causes xcaddy to leave build artifacts on disk after exiting.
- `XCADDY_WHICH_GO` sets the go command to use when for example more then 1 version of go is installed.
- `XCADDY_GO_BUILD_FLAGS` overrides default build arguments. Supports Unix-style shell quoting, for example: XCADDY_GO_BUILD_FLAGS="-ldflags '-w s'".
- `XCADDY_GO_BUILD_FLAGS` overrides default build arguments. Supports Unix-style shell quoting, for example: XCADDY_GO_BUILD_FLAGS="-ldflags '-w s'". The provided flags are applied to `go` commands: build, clean, get, install, list, run, and test
- `XCADDY_GO_MOD_FLAGS` overrides default `go mod` arguments. Supports Unix-style shell quoting.

---

© 2020 Matthew Holt
5 changes: 3 additions & 2 deletions builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type Builder struct {
SkipBuild bool `json:"skip_build,omitempty"`
Debug bool `json:"debug,omitempty"`
BuildFlags string `json:"build_flags,omitempty"`
ModFlags string `json:"mod_flags,omitempty"`
}

// Build builds Caddy at the configured version with the
Expand Down Expand Up @@ -102,13 +103,13 @@ func (b Builder) Build(ctx context.Context, outputFile string) error {
log.Println("[INFO] Building Caddy")

// tidy the module to ensure go.mod and go.sum are consistent with the module prereq
tidyCmd := buildEnv.newGoCommand("mod", "tidy")
tidyCmd := buildEnv.newGoModCommand("tidy")
if err := buildEnv.runCommand(ctx, tidyCmd, b.TimeoutGet); err != nil {
return err
}

// compile
cmd := buildEnv.newGoCommand("build",
cmd := buildEnv.newGoBuildCommand("build",
"-o", absOutputFile,
)
if b.Debug {
Expand Down
2 changes: 2 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ var (
skipCleanup = os.Getenv("XCADDY_SKIP_CLEANUP") == "1" || skipBuild
buildDebugOutput = os.Getenv("XCADDY_DEBUG") == "1"
buildFlags = os.Getenv("XCADDY_GO_BUILD_FLAGS")
modFlags = os.Getenv("XCADDY_GO_MOD_FLAGS")
)

func Main() {
Expand Down Expand Up @@ -136,6 +137,7 @@ func runBuild(ctx context.Context, args []string) error {
SkipCleanup: skipCleanup,
Debug: buildDebugOutput,
BuildFlags: buildFlags,
ModFlags: modFlags,
}
err := builder.Build(ctx, output)
if err != nil {
Expand Down
38 changes: 29 additions & 9 deletions environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,12 @@ func (b Builder) newEnvironment(ctx context.Context) (*environment, error) {
timeoutGoGet: b.TimeoutGet,
skipCleanup: b.SkipCleanup,
buildFlags: b.BuildFlags,
modFlags: b.ModFlags,
}

// initialize the go module
log.Println("[INFO] Initializing Go module")
cmd := env.newGoCommand("mod", "init")
cmd := env.newGoModCommand("init")
cmd.Args = append(cmd.Args, "caddy")
err = env.runCommand(ctx, cmd, 10*time.Second)
if err != nil {
Expand All @@ -115,7 +116,7 @@ func (b Builder) newEnvironment(ctx context.Context) (*environment, error) {
replaced := make(map[string]string)
for _, r := range b.Replacements {
log.Printf("[INFO] Replace %s => %s", r.Old.String(), r.New.String())
cmd := env.newGoCommand("mod", "edit",
cmd := env.newGoModCommand("edit",
"-replace", fmt.Sprintf("%s=%s", r.Old.Param(), r.New.Param()))
err := env.runCommand(ctx, cmd, 10*time.Second)
if err != nil {
Expand Down Expand Up @@ -181,6 +182,7 @@ type environment struct {
timeoutGoGet time.Duration
skipCleanup bool
buildFlags string
modFlags string
}

// Close cleans up the build environment, including deleting
Expand All @@ -194,22 +196,40 @@ func (env environment) Close() error {
return os.RemoveAll(env.tempFolder)
}

func (env environment) newGoCommand(args ...string) *exec.Cmd {
cmd := exec.Command(utils.GetGo(), args...)
func (env environment) newCommand(command string, args ...string) *exec.Cmd {
cmd := exec.Command(command, args...)
cmd.Dir = env.tempFolder
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd
}

// newGoBuildCommand creates a new *exec.Cmd which assumes the first element in `args` is one of: build, clean, get, install, list, run, or test. The
// created command will also have the value of `XCADDY_GO_BUILD_FLAGS` appended to its arguments, if set.
func (env environment) newGoBuildCommand(args ...string) *exec.Cmd {
cmd := env.newCommand(utils.GetGo(), args...)
return parseAndAppendFlags(cmd, env.buildFlags)
}

// newGoModCommand creates a new *exec.Cmd which assumes `args` are the args for `go mod` command. The
// created command will also have the value of `XCADDY_GO_MOD_FLAGS` appended to its arguments, if set.
func (env environment) newGoModCommand(args ...string) *exec.Cmd {
args = append([]string{"mod"}, args...)
cmd := env.newCommand(utils.GetGo(), args...)
return parseAndAppendFlags(cmd, env.modFlags)
}

if env.buildFlags == "" {
func parseAndAppendFlags(cmd *exec.Cmd, flags string) *exec.Cmd {
if strings.TrimSpace(flags) == "" {
return cmd
}

flags, err := shlex.Split(env.buildFlags)
fs, err := shlex.Split(flags)
if err != nil {
log.Printf("[ERROR] Splitting arguments failed: %s", env.buildFlags)
log.Printf("[ERROR] Splitting arguments failed: %s", flags)
return cmd
}
cmd.Args = append(cmd.Args, flags...)
cmd.Args = append(cmd.Args, fs...)

return cmd
}
Expand Down Expand Up @@ -276,7 +296,7 @@ func (env environment) execGoGet(ctx context.Context, modulePath, moduleVersion,
caddy += "@" + caddyVersion
}

cmd := env.newGoCommand("get", "-d", "-v")
cmd := env.newGoBuildCommand("get", "-d", "-v")
// using an empty string as an additional argument to "go get"
// breaks the command since it treats the empty string as a
// distinct argument, so we're using an if statement to avoid it.
Expand Down