Skip to content

Commit 882f2f5

Browse files
committed
feat(build,deploy): build service images using compose (bake/buildkit), push to cluster, and deploy
1 parent dde23b5 commit 882f2f5

File tree

6 files changed

+270
-441
lines changed

6 files changed

+270
-441
lines changed

cmd/uncloud/build.go

Lines changed: 68 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,71 +10,103 @@ import (
1010
"github.com/spf13/cobra"
1111
)
1212

13-
// NewBuildCommand creates a new command to build services from a Compose file.
13+
type buildOptions struct {
14+
cli.BuildServicesOptions
15+
files []string
16+
profiles []string
17+
}
18+
19+
// NewBuildCommand creates a new command to build images for services from a Compose file.
1420
func NewBuildCommand() *cobra.Command {
15-
opts := cli.BuildOptions{}
21+
opts := buildOptions{}
1622
cmd := &cobra.Command{
1723
Use: "build [FLAGS] [SERVICE...]",
1824
Short: "Build services from a Compose file.",
25+
Long: `Build images for services from a Compose file using local Docker.
26+
27+
By default, built images remain on the local Docker host. Use --push to upload them
28+
to cluster machines or --push-registry to upload them to external registries.`,
29+
Example: ` # Build all services that have a build section in compose.yaml.
30+
uc build
31+
32+
# Build specific services that have a build section.
33+
uc build web api
34+
35+
# Build services and push images to all cluster machines or service x-machines if specified.
36+
uc build --push
37+
38+
# Build services and push images to specific machines.
39+
uc build --push -m machine1,machine2
40+
41+
# Build services and push images to external registries (e.g., Docker Hub).
42+
uc build --push-registry
43+
44+
# Build services with build arguments, pull newer base images before building, and don't use cache.
45+
uc build --build-arg NODE_VERSION=24 --build-arg ENV=production --no-cache --pull`,
1946
RunE: func(cmd *cobra.Command, args []string) error {
2047
uncli := cmd.Context().Value("cli").(*cli.CLI)
21-
22-
if len(args) > 0 {
23-
opts.Services = args
24-
}
48+
opts.Services = args
2549

2650
return runBuild(cmd.Context(), uncli, opts)
2751
},
2852
}
2953

30-
cmd.Flags().StringSliceVarP(&opts.Files, "file", "f", nil,
31-
"One or more Compose files to build (default compose.yaml)")
32-
cmd.Flags().StringSliceVarP(&opts.Profiles, "profile", "p", nil,
33-
"One or more Compose profiles to enable.")
34-
cmd.Flags().BoolVarP(&opts.Push, "push", "P", false,
35-
"Push built images to the registry after building. (default false)")
54+
cmd.Flags().StringArrayVar(&opts.BuildArgs, "build-arg", nil,
55+
"Set a build-time variable for services. Used in Dockerfiles that declare the variable with ARG.\n"+
56+
"Can be specified multiple times. Format: --build-arg VAR=VALUE")
57+
cmd.Flags().BoolVar(&opts.Check, "check", false,
58+
"Check the build configuration for services without building them.")
59+
cmd.Flags().BoolVar(&opts.Deps, "deps", false,
60+
"Also build services declared as dependencies of the selected services.")
61+
cmd.Flags().StringSliceVarP(&opts.files, "file", "f", nil,
62+
"One or more Compose files to build. (default compose.yaml)")
63+
cmd.Flags().StringSliceVarP(&opts.Machines, "machine", "m", nil,
64+
"Machine names or IDs to push the built images to (requires --push).\n"+
65+
"Can be specified multiple times or as a comma-separated list. (default is all machines or x-machines)")
3666
cmd.Flags().BoolVar(&opts.NoCache, "no-cache", false,
37-
"Do not use cache when building images. (default false)")
67+
"Do not use cache when building images.")
68+
cmd.Flags().StringSliceVarP(&opts.profiles, "profile", "p", nil,
69+
"One or more Compose profiles to enable.")
70+
cmd.Flags().BoolVar(&opts.Pull, "pull", false,
71+
"Always attempt to pull newer versions of base images before building.")
72+
cmd.Flags().BoolVar(&opts.PushCluster, "push", false,
73+
"Upload the built images to cluster machines after building.\n"+
74+
"Use --machine to specify which machines. (default is all machines)")
75+
cmd.Flags().BoolVar(&opts.PushRegistry, "push-registry", false,
76+
"Upload the built images to external registries (e.g., Docker Hub) after building.")
77+
cmd.Flags().StringVarP(&opts.Context, "context", "c", "",
78+
"Name of the cluster context. (default is the current context)")
3879

3980
return cmd
4081
}
4182

42-
// TODO: deduplicate with a similar functino for deploy options
43-
// projectOpts returns the project options for the Compose file(s).
44-
func projectOptsFromBuildOpts(opts cli.BuildOptions) []composecli.ProjectOptionsFn {
45-
projectOpts := []composecli.ProjectOptionsFn{}
46-
47-
if len(opts.Profiles) > 0 {
48-
projectOpts = append(projectOpts, composecli.WithDefaultProfiles(opts.Profiles...))
83+
// runBuild parses the Compose file(s) and builds the images for selected services.
84+
func runBuild(ctx context.Context, uncli *cli.CLI, opts buildOptions) error {
85+
// Validate push flags.
86+
if opts.PushCluster && opts.PushRegistry {
87+
return fmt.Errorf("cannot specify both --push and --push-registry: choose one push target")
4988
}
5089

51-
return projectOpts
52-
}
90+
machines := cli.ExpandCommaSeparatedValues(opts.Machines)
91+
// Special handling for an explicit "all" keyword to push to all machines.
92+
if len(machines) == 1 && machines[0] == "all" {
93+
machines = nil
94+
}
95+
opts.Machines = machines
5396

54-
// runBuild parses the Compose file(s), builds the services, and pushes them if requested.
55-
func runBuild(ctx context.Context, uncli *cli.CLI, opts cli.BuildOptions) error {
56-
projectOpts := projectOptsFromBuildOpts(opts)
57-
project, err := compose.LoadProject(ctx, opts.Files, projectOpts...)
97+
project, err := compose.LoadProject(ctx, opts.files, composecli.WithDefaultProfiles(opts.profiles...))
5898
if err != nil {
5999
return fmt.Errorf("load compose file(s): %w", err)
60100
}
61101

62-
if len(opts.Services) > 0 {
63-
project, err = project.WithSelectedServices(opts.Services)
64-
if err != nil {
65-
return fmt.Errorf("select services: %w", err)
66-
}
67-
}
68-
69-
servicesToBuild, err := cli.ServicesThatNeedBuild(project, opts.Services, false)
102+
servicesToBuild, err := cli.ServicesThatNeedBuild(project, opts.Services, opts.Deps)
70103
if err != nil {
71104
return fmt.Errorf("determine services to build: %w", err)
72105
}
73-
74106
if len(servicesToBuild) == 0 {
75107
fmt.Println("No services to build.")
76108
return nil
77109
}
78110

79-
return cli.BuildServices(ctx, servicesToBuild, opts)
111+
return uncli.BuildServices(ctx, project, opts.BuildServicesOptions)
80112
}

cmd/uncloud/cbuild.go

Lines changed: 0 additions & 203 deletions
This file was deleted.

0 commit comments

Comments
 (0)