@@ -173,6 +173,7 @@ func SetupCommands(version string) {
173
173
174
174
// Generate Command
175
175
RootCmd .AddCommand (generateCmd )
176
+ RootCmd .AddCommand (newCmd )
176
177
177
178
// Get Services Command
178
179
getServicesCmd .Flags ().BoolP ("long" , "l" , false , "show more details" )
@@ -214,9 +215,17 @@ func SetupCommands(version string) {
214
215
composeCmd .AddCommand (composeDownCmd )
215
216
composeStartCmd .Flags ().Bool ("force" , false , "force a build of the image even if nothing has changed" )
216
217
composeCmd .AddCommand (composeStartCmd )
217
- RootCmd .AddCommand (composeCmd )
218
218
composeCmd .AddCommand (composeRestartCmd )
219
219
composeCmd .AddCommand (composeStopCmd )
220
+ composeCmd .AddCommand (getServicesCmd ) // like docker compose ls
221
+ RootCmd .AddCommand (composeCmd )
222
+
223
+ // Add up/down commands to the root as well
224
+ RootCmd .AddCommand (composeDownCmd )
225
+ RootCmd .AddCommand (composeUpCmd )
226
+ // RootCmd.AddCommand(composeStartCmd)
227
+ // RootCmd.AddCommand(composeRestartCmd)
228
+ // RootCmd.AddCommand(composeStopCmd)
220
229
221
230
// Debug Command
222
231
debugCmd .Flags ().String ("etag" , "" , "deployment ID (ETag) of the service" )
@@ -270,7 +279,7 @@ var RootCmd = &cobra.Command{
270
279
SilenceErrors : true ,
271
280
Use : "defang" ,
272
281
Args : cobra .NoArgs ,
273
- Short : "Defang CLI manages services on the Defang cluster " ,
282
+ Short : "Defang CLI is used to develop, deploy, and debug your cloud services " ,
274
283
PersistentPreRunE : func (cmd * cobra.Command , args []string ) (err error ) {
275
284
276
285
term .SetDebug (doDebug )
@@ -430,10 +439,10 @@ var certGenerateCmd = &cobra.Command{
430
439
}
431
440
432
441
var generateCmd = & cobra.Command {
433
- Use : "generate [SAMPLE] " ,
442
+ Use : "generate" ,
434
443
Args : cobra .MaximumNArgs (1 ),
435
- Aliases : []string {"gen" , "new" , "init" },
436
- Short : "Generate a sample Defang project in the current folder " ,
444
+ Aliases : []string {"gen" },
445
+ Short : "Generate a sample Defang project" ,
437
446
RunE : func (cmd * cobra.Command , args []string ) error {
438
447
var sample , language , defaultFolder string
439
448
if len (args ) > 0 {
@@ -446,12 +455,12 @@ var generateCmd = &cobra.Command{
446
455
}
447
456
return cli .InitFromSamples (cmd .Context (), "" , []string {sample })
448
457
}
458
+
449
459
sampleList , fetchSamplesErr := cli .FetchSamples (cmd .Context ())
450
460
if sample == "" {
451
461
if err := survey .AskOne (& survey.Select {
452
462
Message : "Choose the language you'd like to use:" ,
453
- Options : []string {"Nodejs" , "Golang" , "Python" },
454
- Default : "Nodejs" ,
463
+ Options : cli .SupportedLanguages ,
455
464
Help : "The project code will be in the language you choose here." ,
456
465
}, & language ); err != nil {
457
466
return err
@@ -604,6 +613,14 @@ var generateCmd = &cobra.Command{
604
613
},
605
614
}
606
615
616
+ var newCmd = & cobra.Command {
617
+ Use : "new [SAMPLE]" ,
618
+ Args : cobra .MaximumNArgs (1 ),
619
+ Aliases : []string {"init" },
620
+ Short : "Create a new Defang project from a sample" ,
621
+ RunE : generateCmd .RunE ,
622
+ }
623
+
607
624
func collectUnsetEnvVars (project * proj.Project ) []string {
608
625
var envVars []string
609
626
if project != nil {
@@ -669,6 +686,7 @@ var getVersionCmd = &cobra.Command{
669
686
var tailCmd = & cobra.Command {
670
687
Use : "tail" ,
671
688
Annotations : authNeededAnnotation ,
689
+ Aliases : []string {"logs" },
672
690
Args : cobra .NoArgs ,
673
691
Short : "Tail logs from one or more services" ,
674
692
RunE : func (cmd * cobra.Command , args []string ) error {
@@ -775,7 +793,7 @@ var configSetCmd = &cobra.Command{
775
793
}
776
794
term .Info ("Updated value for" , name )
777
795
778
- printDefangHint ("To update the deployed values, do:" , "compose start " )
796
+ printDefangHint ("To update the deployed values, do:" , "compose restart " )
779
797
return nil
780
798
},
781
799
}
@@ -818,20 +836,33 @@ var composeCmd = &cobra.Command{
818
836
Aliases : []string {"stack" },
819
837
Args : cobra .NoArgs ,
820
838
Short : "Work with local Compose files" ,
839
+ Long : `Define and deploy multi-container applications with Defang. Most compose commands require
840
+ a "compose.yaml" file. The simplest "compose.yaml" file with a single service is:
841
+
842
+ services:
843
+ app: # the name of the service
844
+ build: . # the folder with the Dockerfile and app sources (. means current folder)
845
+ ports:
846
+ - 80 # the port the service listens on for HTTP requests
847
+ ` ,
821
848
}
822
849
823
850
var composeUpCmd = & cobra.Command {
824
851
Use : "up" ,
825
852
Annotations : authNeededAnnotation ,
826
853
Args : cobra .NoArgs , // TODO: takes optional list of service names
827
- Short : "Like 'start' but immediately tracks the progress of the deployment " ,
854
+ Short : "Reads a Compose file and deploy a new project or update an existing project " ,
828
855
RunE : func (cmd * cobra.Command , args []string ) error {
829
856
var force , _ = cmd .Flags ().GetBool ("force" )
830
857
var detach , _ = cmd .Flags ().GetBool ("detach" )
831
858
832
859
since := time .Now ()
833
860
deploy , project , err := cli .ComposeUp (cmd .Context (), client , force )
834
861
if err != nil {
862
+ if ! errors .Is (err , types .ErrComposeFileNotFound ) {
863
+ return err
864
+ }
865
+ printDefangHint ("To start a new project, do:" , "new" )
835
866
return err
836
867
}
837
868
@@ -1019,7 +1050,7 @@ var composeDownCmd = &cobra.Command{
1019
1050
Aliases : []string {"rm" },
1020
1051
Annotations : authNeededAnnotation ,
1021
1052
Args : cobra .NoArgs , // TODO: takes optional list of service names
1022
- Short : "Like 'stop' but also deprovisions the services from the cluster " ,
1053
+ Short : "Reads a Compose file and deprovisions its services" ,
1023
1054
RunE : func (cmd * cobra.Command , args []string ) error {
1024
1055
var detach , _ = cmd .Flags ().GetBool ("detach" )
1025
1056
0 commit comments