• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

UiPath / uipathcli / 14386649619

10 Apr 2025 05:30PM UTC coverage: 90.345% (-0.2%) from 90.504%
14386649619

push

github

thschmitt
Add restore command for UiPath Studio projects

Add new command to restore the packages. The existing pack command
already performs restore but also creates the nupkg package. This new
restore command only restores the dependency packages.

`uipath studio package restore` restores the packages for the project
in the current working directory into a packages/ folder.

Implements https://github.com/UiPath/uipathcli/issues/159

116 of 140 new or added lines in 4 files covered. (82.86%)

6101 of 6753 relevant lines covered (90.35%)

1.01 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.85
/plugin/studio/package_restore_command.go
1
package studio
2

3
import (
4
        "bytes"
5
        "encoding/json"
6
        "fmt"
7
        "os"
8
        "path/filepath"
9
        "strings"
10
        "time"
11

12
        "github.com/UiPath/uipathcli/log"
13
        "github.com/UiPath/uipathcli/output"
14
        "github.com/UiPath/uipathcli/plugin"
15
        "github.com/UiPath/uipathcli/utils/process"
16
        "github.com/UiPath/uipathcli/utils/visualization"
17
)
18

19
// The PackageRestoreCommand restores the packages of the project
20
type PackageRestoreCommand struct {
21
        Exec process.ExecProcess
22
}
23

24
func (c PackageRestoreCommand) Command() plugin.Command {
1✔
25
        return *plugin.NewCommand("studio").
1✔
26
                WithCategory("package", "Package", "UiPath Studio package-related actions").
1✔
27
                WithOperation("restore", "Package Project", "Restores the packages of the project").
1✔
28
                WithParameter("source", plugin.ParameterTypeString, "Path to a project.json file or a folder containing project.json file (default: .)", false).
1✔
29
                WithParameter("destination", plugin.ParameterTypeString, "The output folder (default ./packages)", false)
1✔
30
}
1✔
31

32
func (c PackageRestoreCommand) Execute(ctx plugin.ExecutionContext, writer output.OutputWriter, logger log.Logger) error {
1✔
33
        source, err := c.getSource(ctx)
1✔
34
        if err != nil {
2✔
35
                return err
1✔
36
        }
1✔
37
        destination := c.getDestination(ctx)
1✔
38

1✔
39
        params := newPackageRestoreParams(
1✔
40
                ctx.Organization,
1✔
41
                ctx.Tenant,
1✔
42
                ctx.BaseUri,
1✔
43
                ctx.Auth.Token,
1✔
44
                source,
1✔
45
                destination)
1✔
46

1✔
47
        result, err := c.execute(*params, ctx.Debug, logger)
1✔
48
        if err != nil {
1✔
NEW
49
                return err
×
NEW
50
        }
×
51

52
        json, err := json.Marshal(result)
1✔
53
        if err != nil {
1✔
NEW
54
                return fmt.Errorf("restore command failed: %v", err)
×
NEW
55
        }
×
56
        return writer.WriteResponse(*output.NewResponseInfo(200, "200 OK", "HTTP/1.1", map[string][]string{}, bytes.NewReader(json)))
1✔
57
}
58

59
func (c PackageRestoreCommand) execute(params packageRestoreParams, debug bool, logger log.Logger) (*packageRestoreResult, error) {
1✔
60
        projectReader := newStudioProjectReader(params.Source)
1✔
61
        project, err := projectReader.ReadMetadata()
1✔
62
        if err != nil {
1✔
NEW
63
                return nil, err
×
NEW
64
        }
×
65
        supported, err := project.TargetFramework.IsSupported()
1✔
66
        if !supported {
1✔
NEW
67
                return nil, err
×
NEW
68
        }
×
69

70
        uipcli := newUipcli(c.Exec, logger)
1✔
71
        err = uipcli.Initialize(project.TargetFramework)
1✔
72
        if err != nil {
1✔
NEW
73
                return nil, err
×
NEW
74
        }
×
75

76
        if !debug {
2✔
77
                bar := c.newProgressBar(logger)
1✔
78
                defer close(bar)
1✔
79
        }
1✔
80
        args := c.prepareRestoreArguments(params)
1✔
81
        exitCode, stdErr, err := uipcli.ExecuteAndWait(args...)
1✔
82
        if err != nil {
1✔
NEW
83
                return nil, err
×
NEW
84
        }
×
85

86
        var result *packageRestoreResult
1✔
87
        if exitCode == 0 {
2✔
88
                if err != nil {
1✔
NEW
89
                        return nil, err
×
NEW
90
                }
×
91
                result = newSucceededPackageRestoreResult(
1✔
92
                        params.Destination,
1✔
93
                        project.Name,
1✔
94
                        project.Description,
1✔
95
                        project.ProjectId)
1✔
NEW
96
        } else {
×
NEW
97
                result = newFailedPackageRestoreResult(
×
NEW
98
                        stdErr,
×
NEW
99
                        &project.Name,
×
NEW
100
                        &project.Description,
×
NEW
101
                        &project.ProjectId)
×
NEW
102
        }
×
103
        return result, nil
1✔
104
}
105

106
func (c PackageRestoreCommand) prepareRestoreArguments(params packageRestoreParams) []string {
1✔
107
        source, _ := strings.CutSuffix(params.Source, defaultProjectJson)
1✔
108
        args := []string{"package", "restore", source, "--restoreFolder", params.Destination}
1✔
109
        if params.AuthToken != nil && params.Organization != "" {
2✔
110
                args = append(args, "--libraryOrchestratorUrl", params.BaseUri.String())
1✔
111
                args = append(args, "--libraryOrchestratorAuthToken", params.AuthToken.Value)
1✔
112
                args = append(args, "--libraryOrchestratorAccountName", params.Organization)
1✔
113
                if params.Tenant != "" {
2✔
114
                        args = append(args, "--libraryOrchestratorTenant", params.Tenant)
1✔
115
                }
1✔
116
        }
117
        return args
1✔
118
}
119

120
func (c PackageRestoreCommand) newProgressBar(logger log.Logger) chan struct{} {
1✔
121
        progressBar := visualization.NewProgressBar(logger)
1✔
122
        ticker := time.NewTicker(10 * time.Millisecond)
1✔
123
        cancel := make(chan struct{})
1✔
124
        var percent float64 = 0
1✔
125
        go func() {
2✔
126
                for {
2✔
127
                        select {
1✔
128
                        case <-ticker.C:
1✔
129
                                progressBar.UpdatePercentage("restoring...  ", percent)
1✔
130
                                percent = percent + 1
1✔
131
                                if percent > 100 {
2✔
132
                                        percent = 0
1✔
133
                                }
1✔
134
                        case <-cancel:
1✔
135
                                ticker.Stop()
1✔
136
                                progressBar.Remove()
1✔
137
                                return
1✔
138
                        }
139
                }
140
        }()
141
        return cancel
1✔
142
}
143

144
func (c PackageRestoreCommand) getSource(ctx plugin.ExecutionContext) (string, error) {
1✔
145
        source := c.getParameter("source", ".", ctx.Parameters)
1✔
146
        source, _ = filepath.Abs(source)
1✔
147
        fileInfo, err := os.Stat(source)
1✔
148
        if err != nil {
2✔
149
                return "", fmt.Errorf("%s not found", defaultProjectJson)
1✔
150
        }
1✔
151
        if fileInfo.IsDir() {
2✔
152
                source = filepath.Join(source, defaultProjectJson)
1✔
153
        }
1✔
154
        return source, nil
1✔
155
}
156

157
func (c PackageRestoreCommand) getDestination(ctx plugin.ExecutionContext) string {
1✔
158
        destination := c.getParameter("destination", "./packages/", ctx.Parameters)
1✔
159
        destination, _ = filepath.Abs(destination)
1✔
160
        return destination
1✔
161
}
1✔
162

163
func (c PackageRestoreCommand) getParameter(name string, defaultValue string, parameters []plugin.ExecutionParameter) string {
1✔
164
        result := defaultValue
1✔
165
        for _, p := range parameters {
2✔
166
                if p.Name == name {
2✔
167
                        if data, ok := p.Value.(string); ok {
2✔
168
                                result = data
1✔
169
                                break
1✔
170
                        }
171
                }
172
        }
173
        return result
1✔
174
}
175

176
func NewPackageRestoreCommand() *PackageRestoreCommand {
1✔
177
        return &PackageRestoreCommand{process.NewExecProcess()}
1✔
178
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc