Skip to content

Commit cf4b9a3

Browse files
committed
Merge remote-tracking branch 'origin/main' into app-specification
2 parents 5a37e66 + 03379d0 commit cf4b9a3

Some content is hidden

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

51 files changed

+1629
-157
lines changed

.github/workflows/test-update.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: test the system update flow
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
build-and-update:
14+
runs-on: ubuntu-22.04
15+
16+
steps:
17+
- name: Checkout
18+
uses: actions/checkout@v4
19+
20+
- name: Set up Go
21+
uses: actions/setup-go@v5
22+
with:
23+
go-version-file: go.mod
24+
25+
- name: Run dep package update test
26+
env:
27+
GH_TOKEN: ${{ secrets.ARDUINOBOT_TOKEN }}
28+
run: |
29+
go tool task test:update

Taskfile.yml

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,13 @@ tasks:
5050

5151
test:internal:
5252
cmds:
53-
- go build ./cmd/arduino-app-cli # needed for e2e tests
53+
- go build ./cmd/arduino-app-cli
5454
- task: generate
55-
- go test ./internal/... ./cmd/... -v -race {{ .CLI_ARGS }}
55+
- go test $(go list ./internal/... ./cmd/... | grep -v internal/e2e/updatetest) -v -race {{ .CLI_ARGS }}
56+
57+
test:update:
58+
cmds:
59+
- go test --timeout 30m -v ./internal/e2e/updatetest
5660

5761
test:pkg:
5862
desc: Run only tests in the pkg directory
@@ -102,9 +106,10 @@ tasks:
102106
deps:
103107
- build-deb:clone-examples
104108
cmds:
105-
- docker build --build-arg BINARY_NAME=arduino-app-cli --build-arg DEB_NAME=arduino-app-cli --build-arg VERSION={{ .VERSION }} --build-arg ARCH={{ .ARCH }} --build-arg RELEASE={{ .RELEASE }} --output=./build -f debian/Dockerfile .
109+
- docker build --build-arg BINARY_NAME=arduino-app-cli --build-arg DEB_NAME=arduino-app-cli --build-arg VERSION={{ .VERSION }} --build-arg ARCH={{ .ARCH }} --build-arg RELEASE={{ .RELEASE }} --output={{ .OUTPUT }} -f debian/Dockerfile .
106110
vars:
107111
ARCH: '{{.ARCH | default "arm64"}}'
112+
OUTPUT: '{{.OUTPUT | default "./build"}}'
108113

109114
build-deb:clone-examples:
110115
desc: "Clones the examples repo directly into the debian structure"
@@ -114,7 +119,7 @@ tasks:
114119
echo "Runner version set as: {{ .EXAMPLE_VERSION }}"
115120
TMP_PATH="$(mktemp -d)"
116121
DEST_PATH="debian/arduino-app-cli/home/arduino/.local/share/arduino-app-cli/"
117-
echo "Cloning arduino/app-bricks-example into temporary directory ${TMP_PATH}..."
122+
echo "Cloning arduino/app-bricks-examples into temporary directory ${TMP_PATH}..."
118123
git clone --depth 1 --branch "{{ .EXAMPLE_VERSION }}" https://github.com/arduino/app-bricks-examples "${TMP_PATH}"
119124
rm -rf "${DEST_PATH}/examples"
120125
mkdir -p "${DEST_PATH}"
@@ -190,7 +195,7 @@ tasks:
190195
TMP_PATH="$(mktemp -d)"
191196
192197
echo "Cloning examples into temporary directory ${TMP_PATH}..."
193-
git clone --depth 1 https://github.com/arduino/app-bricks-example.git "${TMP_PATH}"
198+
git clone --depth 1 https://github.com/arduino/app-bricks-examples.git "${TMP_PATH}"
194199
195200
echo "Installing examples to ${DEST_PATH}examples"
196201
rm -rf "${DEST_PATH}examples"

cmd/arduino-app-cli/app/app.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ func NewAppCmd(cfg config.Configuration) *cobra.Command {
3838
appCmd.AddCommand(newRestartCmd(cfg))
3939
appCmd.AddCommand(newLogsCmd(cfg))
4040
appCmd.AddCommand(newListCmd(cfg))
41-
appCmd.AddCommand(newPsCmd())
4241
appCmd.AddCommand(newMonitorCmd(cfg))
42+
appCmd.AddCommand(newCacheCleanCmd(cfg))
4343

4444
return appCmd
4545
}

cmd/arduino-app-cli/app/clean.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package app
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/spf13/cobra"
8+
9+
"github.com/arduino/arduino-app-cli/cmd/arduino-app-cli/completion"
10+
"github.com/arduino/arduino-app-cli/cmd/arduino-app-cli/internal/servicelocator"
11+
"github.com/arduino/arduino-app-cli/cmd/feedback"
12+
"github.com/arduino/arduino-app-cli/internal/orchestrator"
13+
"github.com/arduino/arduino-app-cli/internal/orchestrator/app"
14+
"github.com/arduino/arduino-app-cli/internal/orchestrator/config"
15+
)
16+
17+
func newCacheCleanCmd(cfg config.Configuration) *cobra.Command {
18+
var forceClean bool
19+
appCmd := &cobra.Command{
20+
Use: "clean-cache <app-id>",
21+
Short: "Delete app cache",
22+
Args: cobra.ExactArgs(1),
23+
RunE: func(cmd *cobra.Command, args []string) error {
24+
app, err := Load(args[0])
25+
if err != nil {
26+
return err
27+
}
28+
return cacheCleanHandler(cmd.Context(), app, forceClean)
29+
},
30+
ValidArgsFunction: completion.ApplicationNames(cfg),
31+
}
32+
appCmd.Flags().BoolVarP(&forceClean, "force", "", false, "Forcefully clean the cache even if the app is running")
33+
34+
return appCmd
35+
}
36+
37+
func cacheCleanHandler(ctx context.Context, app app.ArduinoApp, forceClean bool) error {
38+
err := orchestrator.CleanAppCache(
39+
ctx,
40+
servicelocator.GetDockerClient(),
41+
app,
42+
orchestrator.CleanAppCacheRequest{ForceClean: forceClean},
43+
)
44+
if err != nil {
45+
feedback.Fatal(err.Error(), feedback.ErrGeneric)
46+
}
47+
feedback.PrintResult(cacheCleanResult{
48+
AppName: app.Name,
49+
Path: app.ProvisioningStateDir().String(),
50+
})
51+
return nil
52+
}
53+
54+
type cacheCleanResult struct {
55+
AppName string `json:"appName"`
56+
Path string `json:"path"`
57+
}
58+
59+
func (r cacheCleanResult) String() string {
60+
return fmt.Sprintf("✓ Cache of %q App cleaned", r.AppName)
61+
}
62+
63+
func (r cacheCleanResult) Data() interface{} {
64+
return r
65+
}

cmd/arduino-app-cli/app/ps.go

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

cmd/arduino-app-cli/app/restart.go

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,18 @@
1616
package app
1717

1818
import (
19+
"context"
20+
"fmt"
21+
1922
"github.com/spf13/cobra"
23+
"golang.org/x/text/cases"
24+
"golang.org/x/text/language"
2025

2126
"github.com/arduino/arduino-app-cli/cmd/arduino-app-cli/completion"
27+
"github.com/arduino/arduino-app-cli/cmd/arduino-app-cli/internal/servicelocator"
2228
"github.com/arduino/arduino-app-cli/cmd/feedback"
29+
"github.com/arduino/arduino-app-cli/internal/orchestrator"
30+
"github.com/arduino/arduino-app-cli/internal/orchestrator/app"
2331
"github.com/arduino/arduino-app-cli/internal/orchestrator/config"
2432
)
2533

@@ -32,17 +40,63 @@ func newRestartCmd(cfg config.Configuration) *cobra.Command {
3240
if len(args) == 0 {
3341
return cmd.Help()
3442
}
35-
app, err := Load(args[0])
43+
appToStart, err := Load(args[0])
3644
if err != nil {
3745
feedback.Fatal(err.Error(), feedback.ErrBadArgument)
38-
return nil
39-
}
40-
if err := stopHandler(cmd.Context(), app); err != nil {
41-
feedback.Warnf("failed to stop app: %s", err.Error())
4246
}
43-
return startHandler(cmd.Context(), cfg, app)
47+
return restartHandler(cmd.Context(), cfg, appToStart)
4448
},
4549
ValidArgsFunction: completion.ApplicationNames(cfg),
4650
}
4751
return cmd
4852
}
53+
54+
func restartHandler(ctx context.Context, cfg config.Configuration, app app.ArduinoApp) error {
55+
out, _, getResult := feedback.OutputStreams()
56+
57+
stream := orchestrator.RestartApp(
58+
ctx,
59+
servicelocator.GetDockerClient(),
60+
servicelocator.GetProvisioner(),
61+
servicelocator.GetModelsIndex(),
62+
servicelocator.GetBricksIndex(),
63+
app,
64+
cfg,
65+
servicelocator.GetStaticStore(),
66+
)
67+
for message := range stream {
68+
switch message.GetType() {
69+
case orchestrator.ProgressType:
70+
fmt.Fprintf(out, "Progress[%s]: %.0f%%\n", message.GetProgress().Name, message.GetProgress().Progress)
71+
case orchestrator.InfoType:
72+
fmt.Fprintln(out, "[INFO]", message.GetData())
73+
case orchestrator.ErrorType:
74+
errMesg := cases.Title(language.AmericanEnglish).String(message.GetError().Error())
75+
feedback.Fatal(fmt.Sprintf("[ERROR] %s", errMesg), feedback.ErrGeneric)
76+
return nil
77+
}
78+
}
79+
80+
outputResult := getResult()
81+
feedback.PrintResult(restartAppResult{
82+
AppName: app.Name,
83+
Status: "restarted",
84+
Output: outputResult,
85+
})
86+
87+
return nil
88+
}
89+
90+
type restartAppResult struct {
91+
AppName string `json:"app_name"`
92+
Status string `json:"status"`
93+
Output *feedback.OutputStreamsResult `json:"output,omitempty"`
94+
}
95+
96+
func (r restartAppResult) String() string {
97+
return fmt.Sprintf("✓ App %q restarted successfully", r.AppName)
98+
}
99+
100+
func (r restartAppResult) Data() interface{} {
101+
return r
102+
}

cmd/arduino-app-cli/brick/bricks.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,18 @@ package brick
1717

1818
import (
1919
"github.com/spf13/cobra"
20+
21+
"github.com/arduino/arduino-app-cli/internal/orchestrator/config"
2022
)
2123

22-
func NewBrickCmd() *cobra.Command {
24+
func NewBrickCmd(cfg config.Configuration) *cobra.Command {
2325
appCmd := &cobra.Command{
2426
Use: "brick",
2527
Short: "Manage Arduino Bricks",
2628
}
2729

2830
appCmd.AddCommand(newBricksListCmd())
29-
appCmd.AddCommand(newBricksDetailsCmd())
31+
appCmd.AddCommand(newBricksDetailsCmd(cfg))
3032

3133
return appCmd
3234
}

cmd/arduino-app-cli/brick/details.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,28 @@ import (
2222

2323
"github.com/spf13/cobra"
2424

25+
"github.com/arduino/arduino-app-cli/cmd/arduino-app-cli/completion"
2526
"github.com/arduino/arduino-app-cli/cmd/arduino-app-cli/internal/servicelocator"
2627
"github.com/arduino/arduino-app-cli/cmd/feedback"
2728
"github.com/arduino/arduino-app-cli/internal/orchestrator/bricks"
29+
"github.com/arduino/arduino-app-cli/internal/orchestrator/config"
2830
)
2931

30-
func newBricksDetailsCmd() *cobra.Command {
32+
func newBricksDetailsCmd(cfg config.Configuration) *cobra.Command {
3133
return &cobra.Command{
3234
Use: "details",
3335
Short: "Details of a specific brick",
3436
Args: cobra.ExactArgs(1),
3537
Run: func(cmd *cobra.Command, args []string) {
36-
bricksDetailsHandler(args[0])
38+
bricksDetailsHandler(args[0], cfg)
3739
},
40+
ValidArgsFunction: completion.BrickIDs(),
3841
}
3942
}
4043

41-
func bricksDetailsHandler(id string) {
42-
res, err := servicelocator.GetBrickService().BricksDetails(id)
44+
func bricksDetailsHandler(id string, cfg config.Configuration) {
45+
res, err := servicelocator.GetBrickService().BricksDetails(id, servicelocator.GetAppIDProvider(),
46+
cfg)
4347
if err != nil {
4448
if errors.Is(err, bricks.ErrBrickNotFound) {
4549
feedback.Fatal(err.Error(), feedback.ErrBadArgument)

cmd/arduino-app-cli/completion/completion.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/arduino/arduino-app-cli/cmd/arduino-app-cli/internal/servicelocator"
2525
"github.com/arduino/arduino-app-cli/cmd/feedback"
2626
"github.com/arduino/arduino-app-cli/internal/orchestrator"
27+
"github.com/arduino/arduino-app-cli/internal/orchestrator/bricks"
2728
"github.com/arduino/arduino-app-cli/internal/orchestrator/config"
2829
)
2930

@@ -97,3 +98,24 @@ func ApplicationNamesWithFilterFunc(cfg config.Configuration, filter func(apps o
9798
return res, cobra.ShellCompDirectiveNoFileComp
9899
}
99100
}
101+
102+
func BrickIDs() cobra.CompletionFunc {
103+
return BrickIDsWithFilterFunc(func(_ bricks.BrickListItem) bool { return true })
104+
}
105+
106+
func BrickIDsWithFilterFunc(filter func(apps bricks.BrickListItem) bool) cobra.CompletionFunc {
107+
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
108+
brickList, err := servicelocator.GetBrickService().List()
109+
if err != nil {
110+
return nil, cobra.ShellCompDirectiveError
111+
}
112+
113+
var res []string
114+
for _, brick := range brickList.Bricks {
115+
if filter(brick) {
116+
res = append(res, brick.ID)
117+
}
118+
}
119+
return res, cobra.ShellCompDirectiveNoFileComp
120+
}
121+
}

cmd/arduino-app-cli/config/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import (
2929
func NewConfigCmd(cfg config.Configuration) *cobra.Command {
3030
appCmd := &cobra.Command{
3131
Use: "config",
32-
Short: "Manage arduino-app-cli config",
32+
Short: "Manage Arduino App CLI config",
3333
}
3434

3535
appCmd.AddCommand(newConfigGetCmd(cfg))

0 commit comments

Comments
 (0)