Skip to content

Commit 6c3e28d

Browse files
committed
Merge branch 'main' into lio-compose-file
2 parents 054db05 + be30ddf commit 6c3e28d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+3414
-1076
lines changed

.github/workflows/install.yml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on:
55
types: [published]
66
push:
77
branches:
8-
- main
8+
- "**"
99
paths:
1010
- '.github/workflows/install.yml'
1111
- 'src/bin/install'
@@ -15,8 +15,19 @@ jobs:
1515
runs-on: ubuntu-latest
1616

1717
steps:
18-
- name: Install defang
18+
- name: Install defang (latest)
1919
run: . <(curl -Ls https://s.defang.io/install)
20+
env:
21+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # avoid rate limiting
22+
23+
- name: Sanity check
24+
run: defang --version
25+
26+
- name: Install defang (specific version)
27+
run: . <(curl -Ls https://s.defang.io/install)
28+
env:
29+
DEFANG_INSTALL_VERSION: v0.5.36
30+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # alt name
2031

2132
- name: Sanity check
2233
run: defang --version

pkgs/defang/default.nix

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,22 @@ system ? builtins.currentSystem
1010
}:
1111
let
1212
shaMap = {
13-
x86_64-linux = "0crcm1sr1zpi1cz6mbyhj6iivsz9akpln1zrk0flcy9dnkn4av9a";
14-
aarch64-linux = "1nmmf7nw7s2d9q9y780nzgd3i0pz8dvyryjxccrfdp01sfzlks61";
15-
x86_64-darwin = "1sncfvh315sp0n6chpvzdx5hp7hsrkx6m03aix8hfkb1hxjlg0hc";
16-
aarch64-darwin = "1sncfvh315sp0n6chpvzdx5hp7hsrkx6m03aix8hfkb1hxjlg0hc";
13+
x86_64-linux = "1qqbbmww2cd9pfignak4hyc1syvchg8lyqyjx5h6ir4zf6fsivs7";
14+
aarch64-linux = "16yjplqhcd8qasyr85v6siw9nhriv4h46k19nyaqjw6v98lswnkv";
15+
x86_64-darwin = "1z7663383q0cgv2yghk615szy4zjiby2vxr2dg79nzbzb024f55x";
16+
aarch64-darwin = "1z7663383q0cgv2yghk615szy4zjiby2vxr2dg79nzbzb024f55x";
1717
};
1818

1919
urlMap = {
20-
x86_64-linux = "https://github.com/DefangLabs/defang/releases/download/v0.5.38/defang_0.5.38_linux_amd64.tar.gz";
21-
aarch64-linux = "https://github.com/DefangLabs/defang/releases/download/v0.5.38/defang_0.5.38_linux_arm64.tar.gz";
22-
x86_64-darwin = "https://github.com/DefangLabs/defang/releases/download/v0.5.38/defang_0.5.38_macOS.zip";
23-
aarch64-darwin = "https://github.com/DefangLabs/defang/releases/download/v0.5.38/defang_0.5.38_macOS.zip";
20+
x86_64-linux = "https://github.com/DefangLabs/defang/releases/download/v0.5.41/defang_0.5.41_linux_amd64.tar.gz";
21+
aarch64-linux = "https://github.com/DefangLabs/defang/releases/download/v0.5.41/defang_0.5.41_linux_arm64.tar.gz";
22+
x86_64-darwin = "https://github.com/DefangLabs/defang/releases/download/v0.5.41/defang_0.5.41_macOS.zip";
23+
aarch64-darwin = "https://github.com/DefangLabs/defang/releases/download/v0.5.41/defang_0.5.41_macOS.zip";
2424
};
2525
in
2626
stdenvNoCC.mkDerivation {
2727
pname = "defang";
28-
version = "0.5.38";
28+
version = "0.5.41";
2929
src = fetchurl {
3030
url = urlMap.${system};
3131
sha256 = shaMap.${system};

pkgs/npm/package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/bin/install

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,24 @@ fi
2828
if [[ -z "$DEFANG_INSTALL_VERSION" ]]; then
2929
RELEASE_PATH="latest"
3030
else
31-
RELEASE_PATH="tags/$DEFANG_INSTALL_VERSION"
31+
RELEASE_PATH="tags/v${DEFANG_INSTALL_VERSION#v}"
3232
fi
3333

34-
# Echo fetching the release path either latest or strip the tags/ from the version
35-
echo "Fetching the ${DEFANG_INSTALL_VERSION:-latest} release of defang..."
36-
RELEASE_JSON=$(curl -s -f -L https://api.github.com/repos/DefangLabs/defang/releases/$RELEASE_PATH)
34+
# Anonymous API request to GitHub are rate limited to 60 requests per hour.
35+
# Check whether the user has set a GitHub token to increase the rate limit.
36+
AUTH_HEADER=""
37+
if [[ -n "$GITHUB_TOKEN" ]]; then
38+
AUTH_HEADER="Authorization: Bearer $GITHUB_TOKEN"
39+
elif [[ -n "$GH_TOKEN" ]]; then
40+
AUTH_HEADER="Authorization: Bearer $GH_TOKEN"
41+
fi
42+
43+
# Echo fetching the release path either latest or the version
44+
echo "Fetching the ${RELEASE_PATH#tags/} release of defang..."
45+
# Download the release information from GitHub, using the token if available, but falling back to anonymous access
46+
RELEASE_JSON=$([[ -n "$AUTH_HEADER" ]] &&
47+
curl -sfL -H "$AUTH_HEADER" https://api.github.com/repos/DefangLabs/defang/releases/$RELEASE_PATH ||
48+
curl -sfL https://api.github.com/repos/DefangLabs/defang/releases/$RELEASE_PATH)
3749

3850
# Check for curl failure
3951
if [ -z "$RELEASE_JSON" ]; then
@@ -80,7 +92,7 @@ elif [ "$OS" = "Linux" ]; then
8092
fi
8193

8294
# Download the file
83-
if ! curl -s -f -L "$DOWNLOAD_URL" -o "$FILENAME"; then
95+
if ! curl -sfL "$DOWNLOAD_URL" -o "$FILENAME"; then
8496
echo "Download failed. Please check your internet connection and try again."
8597
return 4
8698
fi
@@ -239,5 +251,5 @@ rm "$FILENAME"
239251
echo "Installation completed. You can now use defang by typing '$BINARY_NAME' in the terminal."
240252

241253
# Unset the variables and functions to avoid polluting the user's environment
242-
unset EXTRACT_DIR DOWNLOAD_URL RELEASE_JSON RELEASE_PATH ARCH_SUFFIX ARCH OS FILENAME INSTALL_DIR BINARY_NAME REPLY EXPORT_PATH CURRENT_SHELL FOUND_PROFILE_FILE
254+
unset EXTRACT_DIR DOWNLOAD_URL RELEASE_JSON RELEASE_PATH ARCH_SUFFIX ARCH OS FILENAME INSTALL_DIR BINARY_NAME REPLY EXPORT_PATH CURRENT_SHELL FOUND_PROFILE_FILE AUTH_HEADER
243255
unset -f _prompt_and_append_to_file _generate_completion_script _install_completion_script

src/cmd/cli/command/commands.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ func Execute(ctx context.Context) error {
6464
term.Error("Error:", prettyError(err))
6565
}
6666

67+
if err == cli.ErrDryRun {
68+
return nil
69+
}
70+
6771
var derr *cli.ComposeError
6872
if errors.As(err, &derr) {
6973
compose := "compose"
@@ -151,6 +155,9 @@ func SetupCommands(version string) {
151155
tosCmd.Flags().Bool("agree-tos", false, "agree to the Defang terms of service")
152156
RootCmd.AddCommand(tosCmd)
153157

158+
// Upgrade command
159+
RootCmd.AddCommand(upgradeCmd)
160+
154161
// Token command
155162
tokenCmd.Flags().Duration("expires", 24*time.Hour, "validity duration of the token")
156163
tokenCmd.Flags().String("scope", "", fmt.Sprintf("scope of the token; one of %v (required)", scope.All())) // TODO: make it an Option
@@ -177,7 +184,7 @@ func SetupCommands(version string) {
177184
// TODO: when we add multi-project support to the playground, differentiate
178185
// between ls and ps
179186
lsCommand.Aliases = []string{"getServices", "ps", "ls", "list"}
180-
RootCmd.AddCommand(makeComposeLsCmd())
187+
RootCmd.AddCommand(lsCommand)
181188

182189
// Get Status Command
183190
RootCmd.AddCommand(getVersionCmd)
@@ -314,8 +321,8 @@ var RootCmd = &cobra.Command{
314321
version := cmd.Root().Version // HACK to avoid circular dependency with RootCmd
315322
term.Debug("Fabric:", v.Fabric, "CLI:", version, "CLI-Min:", v.CliMin)
316323
if hasTty && isNewer(version, v.CliMin) {
317-
term.Warn("Your CLI version is outdated. Please update to the latest version.")
318-
os.Setenv("DEFANG_HIDE_UPDATE", "1") // hide the update hint at the end
324+
term.Warn("Your CLI version is outdated. Please upgrade to the latest version by running:\n\ndefang upgrade")
325+
os.Setenv("DEFANG_HIDE_UPDATE", "1") // hide the upgrade hint at the end
319326
}
320327
}
321328

@@ -956,6 +963,16 @@ var tosCmd = &cobra.Command{
956963
},
957964
}
958965

966+
var upgradeCmd = &cobra.Command{
967+
Use: "upgrade",
968+
Args: cobra.NoArgs,
969+
Aliases: []string{"update"},
970+
Short: "Upgrade the Defang CLI to the latest version",
971+
RunE: func(cmd *cobra.Command, args []string) error {
972+
return cli.Upgrade(cmd.Context())
973+
},
974+
}
975+
959976
func configureLoader(cmd *cobra.Command) compose.Loader {
960977
f := cmd.Flags()
961978
o := compose.LoaderOptions{}

src/cmd/cli/command/compose.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,19 @@ import (
1818
"github.com/spf13/cobra"
1919
)
2020

21+
func getManagedResources(serviceInfos []*defangv1.ServiceInfo) []string {
22+
var managedResources []string
23+
for _, service := range serviceInfos {
24+
if service.Type == defangv1.ServiceType_MANAGED {
25+
managedResources = append(managedResources, service.Service.Name)
26+
}
27+
}
28+
return managedResources
29+
}
30+
2131
func makeComposeUpCmd() *cobra.Command {
32+
mode := Mode(defangv1.DeploymentMode_DEVELOPMENT)
33+
2234
composeUpCmd := &cobra.Command{
2335
Use: "up",
2436
Annotations: authNeededAnnotation,
@@ -29,7 +41,7 @@ func makeComposeUpCmd() *cobra.Command {
2941
var detach, _ = cmd.Flags().GetBool("detach")
3042

3143
since := time.Now()
32-
deploy, project, err := cli.ComposeUp(cmd.Context(), client, force)
44+
deploy, project, err := cli.ComposeUp(cmd.Context(), client, force, mode.Value())
3345
if err != nil {
3446
if !errors.Is(err, types.ErrComposeFileNotFound) {
3547
return err
@@ -44,6 +56,11 @@ func makeComposeUpCmd() *cobra.Command {
4456

4557
printPlaygroundPortalServiceURLs(deploy.Services)
4658

59+
managedResources := getManagedResources(deploy.Services)
60+
if len(managedResources) > 0 {
61+
term.Warnf("Defang cannot monitor status of the following managed service(s): %v.\n To check if the managed service is up, check the status of the service which depends on it.", managedResources)
62+
}
63+
4764
if detach {
4865
term.Info("Detached.")
4966
return nil
@@ -106,6 +123,8 @@ func makeComposeUpCmd() *cobra.Command {
106123
if errors.As(context.Cause(tailCtx), &errDeploymentFailed) {
107124
term.Warn(errDeploymentFailed)
108125
failedServices = []string{errDeploymentFailed.Service}
126+
} else if len(managedResources) > 0 {
127+
term.Warn("Managed services have been deployed but not all services may be available yet.")
109128
} else {
110129
term.Warn("Deployment is not finished. Service(s) might not be running.")
111130
// TODO: some services might be OK and we should only debug the ones that are not
@@ -151,6 +170,7 @@ func makeComposeUpCmd() *cobra.Command {
151170
composeUpCmd.Flags().BoolP("detach", "d", false, "run in detached mode")
152171
composeUpCmd.Flags().Bool("force", false, "force a build of the image even if nothing has changed")
153172
composeUpCmd.Flags().Bool("tail", false, "tail the service logs after updating") // obsolete, but keep for backwards compatibility
173+
composeUpCmd.Flags().VarP(&mode, "mode", "m", "deployment mode, possible values: "+strings.Join(allModes(), ", "))
154174
_ = composeUpCmd.Flags().MarkHidden("tail")
155175
return composeUpCmd
156176
}
@@ -165,7 +185,7 @@ func makeComposeStartCmd() *cobra.Command {
165185
RunE: func(cmd *cobra.Command, args []string) error {
166186
var force, _ = cmd.Flags().GetBool("force")
167187

168-
deploy, _, err := cli.ComposeUp(cmd.Context(), client, force)
188+
deploy, _, err := cli.ComposeUp(cmd.Context(), client, force, defangv1.DeploymentMode_UNSPECIFIED_MODE)
169189
if err != nil {
170190
return err
171191
}
@@ -283,7 +303,7 @@ func makeComposeConfigCmd() *cobra.Command {
283303
RunE: func(cmd *cobra.Command, args []string) error {
284304
cli.DoDryRun = true // config is like start in a dry run
285305
// force=false to calculate the digest
286-
if _, _, err := cli.ComposeUp(cmd.Context(), client, false); !errors.Is(err, cli.ErrDryRun) {
306+
if _, _, err := cli.ComposeUp(cmd.Context(), client, false, defangv1.DeploymentMode_UNSPECIFIED_MODE); !errors.Is(err, cli.ErrDryRun) {
287307
return err
288308
}
289309
return nil

src/cmd/cli/command/compose_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package command
2+
3+
import (
4+
"slices"
5+
"testing"
6+
7+
defangv1 "github.com/DefangLabs/defang/src/protos/io/defang/v1"
8+
)
9+
10+
func TestGetManagedResources(t *testing.T) {
11+
tests := []struct {
12+
name string
13+
project []*defangv1.ServiceInfo
14+
expected []string
15+
}{
16+
{
17+
name: "no services",
18+
project: []*defangv1.ServiceInfo{},
19+
expected: []string{},
20+
},
21+
{
22+
name: "one service all managed",
23+
project: []*defangv1.ServiceInfo{{Service: &defangv1.ServiceID{Name: "redis"}, Type: defangv1.ServiceType_MANAGED}},
24+
expected: []string{"redis"},
25+
},
26+
{
27+
name: "one service unmanaged",
28+
project: []*defangv1.ServiceInfo{{Service: &defangv1.ServiceID{Name: "web"}, Type: defangv1.ServiceType_SERVICE}},
29+
expected: []string{},
30+
},
31+
{
32+
name: "one service unmanaged, one service managed",
33+
project: []*defangv1.ServiceInfo{{Service: &defangv1.ServiceID{Name: "web"}, Type: defangv1.ServiceType_SERVICE}, {Service: &defangv1.ServiceID{Name: "redis"}, Type: defangv1.ServiceType_MANAGED}},
34+
expected: []string{"redis"},
35+
},
36+
{
37+
name: "two unmanaged",
38+
project: []*defangv1.ServiceInfo{{Service: &defangv1.ServiceID{Name: "web"}, Type: defangv1.ServiceType_SERVICE}, {Service: &defangv1.ServiceID{Name: "app"}, Type: defangv1.ServiceType_WORKER}},
39+
expected: []string{},
40+
},
41+
{
42+
name: "two managed",
43+
project: []*defangv1.ServiceInfo{{Service: &defangv1.ServiceID{Name: "redis"}, Type: defangv1.ServiceType_MANAGED}, {Service: &defangv1.ServiceID{Name: "postgres"}, Type: defangv1.ServiceType_MANAGED}},
44+
expected: []string{"redis", "postgres"},
45+
},
46+
}
47+
48+
for _, tt := range tests {
49+
t.Run(tt.name, func(t *testing.T) {
50+
actual := getManagedResources(tt.project)
51+
if !slices.Equal(actual, tt.expected) {
52+
t.Errorf("expected %v, got %v", tt.expected, actual)
53+
}
54+
})
55+
}
56+
}

src/cmd/cli/command/mode.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package command
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
defangv1 "github.com/DefangLabs/defang/src/protos/io/defang/v1"
8+
)
9+
10+
type Mode defangv1.DeploymentMode
11+
12+
func (b Mode) String() string {
13+
return strings.ToLower(defangv1.DeploymentMode_name[int32(b)])
14+
}
15+
func (b *Mode) Set(s string) error {
16+
mode, ok := defangv1.DeploymentMode_value[strings.ToUpper(s)]
17+
if !ok {
18+
return fmt.Errorf("invalid mode: %s, valid values are: %v", s, strings.Join(allModes(), ", "))
19+
}
20+
*b = Mode(mode)
21+
return nil
22+
}
23+
func (b Mode) Type() string {
24+
return "mode"
25+
}
26+
27+
func (b Mode) Value() defangv1.DeploymentMode {
28+
return defangv1.DeploymentMode(b)
29+
}
30+
31+
func allModes() []string {
32+
modes := make([]string, 0, len(defangv1.DeploymentMode_name)-1)
33+
for i, mode := range defangv1.DeploymentMode_name {
34+
if i == 0 {
35+
continue
36+
}
37+
modes = append(modes, strings.ToLower(mode))
38+
}
39+
return modes
40+
}

0 commit comments

Comments
 (0)