Skip to content
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
2 changes: 1 addition & 1 deletion cmd/agent/container/deferred_hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func (cmd *DeferredHooksCmd) Run(ctx context.Context) error {
Repository: cmd.DotfilesRepo,
InstallScript: cmd.DotfilesScript,
RemoteUser: config.GetRemoteUser(setupInfo),
}, cmd.SecretsEnv)
}, cmd.SecretsEnv, setup.SkipPhases{})
if err != nil {
return fmt.Errorf("deferred hooks setup: %w", err)
}
Expand Down
3 changes: 3 additions & 0 deletions cmd/agent/container/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ func (cmd *SetupContainerCmd) finalizeSetup(sctx *setupContext) error {
PlatformOptions: &sctx.workspaceInfo.CLIOptions.Platform,
TunnelClient: sctx.tunnelClient,
Prebuild: cmd.Prebuild,
SkipPostCreate: sctx.workspaceInfo.CLIOptions.SkipPostCreate,
SkipPostStart: sctx.workspaceInfo.CLIOptions.SkipPostStart,
SkipPostAttach: sctx.workspaceInfo.CLIOptions.SkipPostAttach,
Dotfiles: setup.DotfilesConfig{
Repository: cmd.DotfilesRepo,
InstallScript: cmd.DotfilesScript,
Expand Down
10 changes: 6 additions & 4 deletions cmd/agent/workspace/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,12 @@ func (cmd *BuildCmd) Run(ctx context.Context) error {
for _, platform := range platforms {
// build the image
imageName, err := runner.Build(ctx, provider2.BuildOptions{
CLIOptions: workspaceInfo.CLIOptions,
RegistryCache: workspaceInfo.RegistryCache,
Platform: platform,
ExportCache: true,
CLIOptions: workspaceInfo.CLIOptions,
RegistryCache: workspaceInfo.RegistryCache,
Platform: platform,
ExportCache: true,
NoBuild: workspaceInfo.CLIOptions.NoBuild,
PushDuringBuild: workspaceInfo.CLIOptions.PushDuringBuild,
})
if err != nil {
log.Errorf("Error building image: %v", err)
Expand Down
11 changes: 8 additions & 3 deletions cmd/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,9 @@ func NewBuildCmd(flags *flags.GlobalFlags) *cobra.Command {
StringSliceVar(&cmd.Platforms, "platform", []string{}, "Set target platform for build")
buildCmd.Flags().
BoolVar(&cmd.SkipPush, "skip-push", false, "If true will not push the image to the repository, useful for testing")
buildCmd.Flags().BoolVar(&cmd.PushDuringBuild, "push", false,
"Push image directly to registry during build, skipping load to local daemon.",
)
buildCmd.Flags().
BoolVar(&cmd.PushDuringBuild, "push", false,
"Push image directly to registry during build, skipping load to local daemon")
buildCmd.Flags().
StringArrayVar(&cmd.CacheFrom, "cache-from", []string{},
"Cache sources for the build (e.g., myregistry.io/cache:latest or type=registry,ref=...). "+
Expand All @@ -187,6 +187,11 @@ func NewBuildCmd(flags *flags.GlobalFlags) *cobra.Command {
BoolVar(&cmd.GitCloneRecursiveSubmodules, "git-clone-recursive-submodules", false,
"If true will clone git submodule repositories recursively")

buildCmd.Flags().
StringVar(&cmd.ImageName, "image-name", "", "Alternative name for the built image")
buildCmd.Flags().
BoolVar(&cmd.NoBuild, "no-build", false, "Fail if the image must be built (enforce pre-built images only)")

// TESTING
buildCmd.Flags().BoolVar(&cmd.ForceBuild, "force-build", false, "TESTING ONLY")
buildCmd.Flags().
Expand Down
69 changes: 69 additions & 0 deletions cmd/build_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package cmd

import (
"testing"

"github.com/devsy-org/devsy/cmd/flags"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestBuildCmd_NoCacheFlag(t *testing.T) {
buildCmd := NewBuildCmd(&flags.GlobalFlags{})
flag := buildCmd.Flags().Lookup("no-cache")
require.NotNil(t, flag)
assert.Equal(t, "false", flag.DefValue)
}

func TestBuildCmd_NoCacheFlagParsesValue(t *testing.T) {
buildCmd := NewBuildCmd(&flags.GlobalFlags{})
err := buildCmd.ParseFlags([]string{"--no-cache"})
require.NoError(t, err)

val, err := buildCmd.Flags().GetBool("no-cache")
require.NoError(t, err)
assert.True(t, val)
}

func TestBuildCmd_ImageNameFlag(t *testing.T) {
buildCmd := NewBuildCmd(&flags.GlobalFlags{})
flag := buildCmd.Flags().Lookup("image-name")
require.NotNil(t, flag)
assert.Equal(t, "", flag.DefValue)
}

func TestBuildCmd_ImageNameFlagParsesValue(t *testing.T) {
buildCmd := NewBuildCmd(&flags.GlobalFlags{})
err := buildCmd.ParseFlags([]string{"--image-name", "my-custom-image:latest"})
require.NoError(t, err)

flag := buildCmd.Flags().Lookup("image-name")
assert.Equal(t, "my-custom-image:latest", flag.Value.String())
}

func TestBuildCmd_NoBuildFlag(t *testing.T) {
buildCmd := NewBuildCmd(&flags.GlobalFlags{})
flag := buildCmd.Flags().Lookup("no-build")
require.NotNil(t, flag)
assert.Equal(t, "false", flag.DefValue)
}

func TestBuildCmd_NoBuildFlagParsesValue(t *testing.T) {
buildCmd := NewBuildCmd(&flags.GlobalFlags{})
err := buildCmd.ParseFlags([]string{"--no-build"})
require.NoError(t, err)

val, err := buildCmd.Flags().GetBool("no-build")
require.NoError(t, err)
assert.True(t, val)
}

func TestBuildCmd_NoCacheDefaultFalse(t *testing.T) {
buildCmd := NewBuildCmd(&flags.GlobalFlags{})
err := buildCmd.ParseFlags([]string{})
require.NoError(t, err)

val, err := buildCmd.Flags().GetBool("no-cache")
require.NoError(t, err)
assert.False(t, val)
}
23 changes: 23 additions & 0 deletions cmd/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ type ExecCmd struct {
RemoteEnv []string
DefaultUserEnvProbe string
IDLabels []string
ContainerDataFolder string
SkipPostCreate bool
}

func NewExecCmd(f *flags.GlobalFlags) *cobra.Command {
Expand Down Expand Up @@ -89,11 +91,32 @@ func NewExecCmd(f *flags.GlobalFlags) *cobra.Command {
[]string{},
"Override the default container identification labels (format: key=value, can be specified multiple times)",
)
execCmd.Flags().
StringVar(
&cmd.ContainerDataFolder,
"container-data-folder",
"",
"Override the default container data folder path",
)
execCmd.Flags().
BoolVar(
&cmd.SkipPostCreate,
"skip-post-create",
false,
"Skip running postCreateCommand",
)

return execCmd
}

func (cmd *ExecCmd) Run(ctx context.Context, args []string) error {
if cmd.ContainerDataFolder != "" {
log.Warnf("--container-data-folder is accepted but not yet implemented for exec")
}
if cmd.SkipPostCreate {
log.Warnf("--skip-post-create is accepted but not yet implemented for exec")
}

if cmd.WorkspaceFolder == "" && cmd.ContainerID == "" {
return fmt.Errorf("either --workspace-folder or --container-id must be provided")
}
Expand Down
47 changes: 46 additions & 1 deletion cmd/exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ import (
"github.com/stretchr/testify/require"
)

const (
flagSkipPostCreate = "--skip-post-create"
flagWorkspaceFolder = "--workspace-folder"
testTmpDir = "/tmp"
)

func TestValidateRemoteEnv_Valid(t *testing.T) {
cmd := &ExecCmd{
GlobalFlags: &flags.GlobalFlags{},
Expand Down Expand Up @@ -54,7 +60,7 @@ func TestNewExecCmd_RequiresWorkspaceFolderOrContainerID(t *testing.T) {

func TestNewExecCmd_RequiresArgs(t *testing.T) {
execCmd := NewExecCmd(&flags.GlobalFlags{})
execCmd.SetArgs([]string{"--workspace-folder", "/tmp/test"})
execCmd.SetArgs([]string{flagWorkspaceFolder, testTmpDir + "/test"})
err := execCmd.Execute()
require.Error(t, err)
assert.Contains(t, err.Error(), "requires at least 1 arg")
Expand Down Expand Up @@ -95,3 +101,42 @@ func TestExecCmd_NonExistentContainerID(t *testing.T) {
require.Error(t, err)
assert.Contains(t, err.Error(), "nonexistent-container-id-12345")
}

func TestExecCmd_ContainerDataFolderFlag(t *testing.T) {
execCmd := NewExecCmd(&flags.GlobalFlags{})
flag := execCmd.Flags().Lookup("container-data-folder")
require.NotNil(t, flag)
assert.Equal(t, "", flag.DefValue)
}

func TestExecCmd_ContainerDataFolderFlagParsesValue(t *testing.T) {
execCmd := NewExecCmd(&flags.GlobalFlags{})
err := execCmd.ParseFlags([]string{
flagWorkspaceFolder, testTmpDir,
"--container-data-folder", "/custom/data",
})
require.NoError(t, err)

flag := execCmd.Flags().Lookup("container-data-folder")
assert.Equal(t, "/custom/data", flag.Value.String())
}

func TestExecCmd_SkipPostCreateFlag(t *testing.T) {
execCmd := NewExecCmd(&flags.GlobalFlags{})
flag := execCmd.Flags().Lookup("skip-post-create")
require.NotNil(t, flag)
assert.Equal(t, "false", flag.DefValue)
}

func TestExecCmd_SkipPostCreateFlagParsesValue(t *testing.T) {
execCmd := NewExecCmd(&flags.GlobalFlags{})
err := execCmd.ParseFlags([]string{
flagWorkspaceFolder, testTmpDir,
flagSkipPostCreate,
})
require.NoError(t, err)

val, err := execCmd.Flags().GetBool("skip-post-create")
require.NoError(t, err)
assert.True(t, val)
}
25 changes: 1 addition & 24 deletions cmd/minor_flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,9 @@ func TestUpCmd_TerminalRowsFlagParsesValue(t *testing.T) {
assert.Equal(t, 40, val)
}

func TestUpCmd_SkipPostCreateFlag(t *testing.T) {
upCmd := NewUpCmd(&flags.GlobalFlags{})
flag := upCmd.Flags().Lookup("skip-post-create")
require.NotNil(t, flag)
assert.Equal(t, "false", flag.DefValue)
}

func TestUpCmd_SkipPostCreateFlagParsesValue(t *testing.T) {
upCmd := NewUpCmd(&flags.GlobalFlags{})
err := upCmd.ParseFlags([]string{"--skip-post-create"})
err := upCmd.ParseFlags([]string{flagSkipPostCreate})
require.NoError(t, err)
val, err := upCmd.Flags().GetBool("skip-post-create")
require.NoError(t, err)
Expand Down Expand Up @@ -120,22 +113,6 @@ func TestUpCmd_DotfilesTargetPathFlagParsesValue(t *testing.T) {
assert.Equal(t, "~/dotfiles", val)
}

func TestBuildCmd_NoCacheFlag(t *testing.T) {
buildCmd := NewBuildCmd(&flags.GlobalFlags{})
flag := buildCmd.Flags().Lookup("no-cache")
require.NotNil(t, flag)
assert.Equal(t, "false", flag.DefValue)
}

func TestBuildCmd_NoCacheFlagParsesValue(t *testing.T) {
buildCmd := NewBuildCmd(&flags.GlobalFlags{})
err := buildCmd.ParseFlags([]string{"--no-cache"})
require.NoError(t, err)
val, err := buildCmd.Flags().GetBool("no-cache")
require.NoError(t, err)
assert.True(t, val)
}

func TestBuildCmd_LabelFlag(t *testing.T) {
buildCmd := NewBuildCmd(&flags.GlobalFlags{})
flag := buildCmd.Flags().Lookup("label")
Expand Down
32 changes: 27 additions & 5 deletions cmd/runusercommands.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@ import (
type RunUserCommandsCmd struct {
*flags.GlobalFlags

WorkspaceFolder string
IDLabels []string
WorkspaceFolder string
IDLabels []string
SkipPostCreate bool
SkipPostStart bool
SkipPostAttach bool
SkipOnCreate bool
SkipUpdateContent bool
}

// NewRunUserCommandsCmd creates a new run-user-commands command.
Expand Down Expand Up @@ -53,6 +58,16 @@ func NewRunUserCommandsCmd(f *flags.GlobalFlags) *cobra.Command {
[]string{},
"Override the default container identification labels (format: key=value, can be specified multiple times)",
)
runCmd.Flags().
BoolVar(&cmd.SkipPostCreate, "skip-post-create", false, "Skip running postCreateCommand")
runCmd.Flags().
BoolVar(&cmd.SkipPostStart, "skip-post-start", false, "Skip running postStartCommand")
runCmd.Flags().
BoolVar(&cmd.SkipPostAttach, "skip-post-attach", false, "Skip running postAttachCommand")
runCmd.Flags().
BoolVar(&cmd.SkipOnCreate, "skip-on-create", false, "Skip running onCreateCommand")
runCmd.Flags().
BoolVar(&cmd.SkipUpdateContent, "skip-update-content", false, "Skip running updateContentCommand")

return runCmd
}
Expand Down Expand Up @@ -149,13 +164,20 @@ func (cmd *RunUserCommandsCmd) runLifecycleHooks(
hooks := []struct {
name string
cmds []types.LifecycleHook
skip bool
}{
{"postCreateCommand", result.MergedConfig.PostCreateCommands},
{"postStartCommand", result.MergedConfig.PostStartCommands},
{"postAttachCommand", result.MergedConfig.PostAttachCommands},
{"onCreateCommand", result.MergedConfig.OnCreateCommands, cmd.SkipOnCreate},
{"updateContentCommand", result.MergedConfig.UpdateContentCommands, cmd.SkipUpdateContent},
{"postCreateCommand", result.MergedConfig.PostCreateCommands, cmd.SkipPostCreate},
{"postStartCommand", result.MergedConfig.PostStartCommands, cmd.SkipPostStart},
{"postAttachCommand", result.MergedConfig.PostAttachCommands, cmd.SkipPostAttach},
}

for _, hook := range hooks {
if hook.skip {
log.Infof("skipping %s (--skip flag set)", hook.name)
continue
}
for _, h := range hook.cmds {
if err := execLifecycleHook(params, hook.name, h); err != nil {
_ = devcconfig.WriteErrorJSON(os.Stderr, err.Error())
Expand Down
Loading
Loading