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

UiPath / uipathcli / 12392579821

18 Dec 2024 12:05PM UTC coverage: 88.981% (+2.9%) from 86.121%
12392579821

push

github

thschmitt
Add support to analyze studio projects

211 of 270 new or added lines in 8 files covered. (78.15%)

40 existing lines in 4 files now uncovered.

4813 of 5409 relevant lines covered (88.98%)

1.0 hits per line

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

80.38
/plugin/studio/package_pack_command.go
1
package studio
2

3
import (
4
        "bufio"
5
        "bytes"
6
        "encoding/json"
7
        "errors"
8
        "fmt"
9
        "io"
10
        "os"
11
        "path/filepath"
12
        "strings"
13
        "sync"
14
        "time"
15

16
        "github.com/UiPath/uipathcli/log"
17
        "github.com/UiPath/uipathcli/output"
18
        "github.com/UiPath/uipathcli/plugin"
19
        "github.com/UiPath/uipathcli/utils"
20
)
21

22
const defaultProjectJson = "project.json"
23

24
// The PackagePackCommand packs a project into a single NuGet package
25
type PackagePackCommand struct {
26
        Exec utils.ExecProcess
27
}
28

29
func (c PackagePackCommand) Command() plugin.Command {
1✔
30
        return *plugin.NewCommand("studio").
1✔
31
                WithCategory("package", "Package", "UiPath Studio package-related actions").
1✔
32
                WithOperation("pack", "Package Project", "Packs a project into a single package").
1✔
33
                WithParameter("source", plugin.ParameterTypeString, "Path to a project.json file or a folder containing project.json file", true).
1✔
34
                WithParameter("destination", plugin.ParameterTypeString, "The output folder", true).
1✔
35
                WithParameter("package-version", plugin.ParameterTypeString, "The package version", false).
1✔
36
                WithParameter("auto-version", plugin.ParameterTypeBoolean, "Auto-generate package version", false).
1✔
37
                WithParameter("output-type", plugin.ParameterTypeString, "Force the output to a specific type", false).
1✔
38
                WithParameter("split-output", plugin.ParameterTypeBoolean, "Enables the output split to runtime and design libraries", false).
1✔
39
                WithParameter("release-notes", plugin.ParameterTypeString, "Add release notes", false)
1✔
40
}
1✔
41

42
func (c PackagePackCommand) Execute(context plugin.ExecutionContext, writer output.OutputWriter, logger log.Logger) error {
1✔
43
        source, err := c.getSource(context)
1✔
44
        if err != nil {
2✔
45
                return err
1✔
46
        }
1✔
47
        destination, err := c.getDestination(context)
1✔
48
        if err != nil {
1✔
UNCOV
49
                return err
×
UNCOV
50
        }
×
51
        packageVersion, _ := c.getParameter("package-version", context.Parameters)
1✔
52
        autoVersion, _ := c.getBoolParameter("auto-version", context.Parameters)
1✔
53
        outputType, _ := c.getParameter("output-type", context.Parameters)
1✔
54
        splitOutput, _ := c.getBoolParameter("split-output", context.Parameters)
1✔
55
        releaseNotes, _ := c.getParameter("release-notes", context.Parameters)
1✔
56
        params := newPackagePackParams(source, destination, packageVersion, autoVersion, outputType, splitOutput, releaseNotes)
1✔
57

1✔
58
        result, err := c.execute(*params, context.Debug, logger)
1✔
59
        if err != nil {
1✔
UNCOV
60
                return err
×
61
        }
×
62

63
        json, err := json.Marshal(result)
1✔
64
        if err != nil {
1✔
UNCOV
65
                return fmt.Errorf("pack command failed: %v", err)
×
UNCOV
66
        }
×
67
        return writer.WriteResponse(*output.NewResponseInfo(200, "200 OK", "HTTP/1.1", map[string][]string{}, bytes.NewReader(json)))
1✔
68
}
69

70
func (c PackagePackCommand) execute(params packagePackParams, debug bool, logger log.Logger) (*packagePackResult, error) {
1✔
71
        if !debug {
2✔
72
                bar := c.newPackagingProgressBar(logger)
1✔
73
                defer close(bar)
1✔
74
        }
1✔
75

76
        args := []string{"package", "pack", params.Source, "--output", params.Destination}
1✔
77
        if params.PackageVersion != "" {
1✔
78
                args = append(args, "--version", params.PackageVersion)
×
UNCOV
79
        }
×
80
        if params.AutoVersion {
1✔
81
                args = append(args, "--autoVersion")
×
UNCOV
82
        }
×
83
        if params.OutputType != "" {
1✔
UNCOV
84
                args = append(args, "--outputType", params.OutputType)
×
UNCOV
85
        }
×
86
        if params.SplitOutput {
1✔
87
                args = append(args, "--splitOutput")
×
UNCOV
88
        }
×
89
        if params.ReleaseNotes != "" {
1✔
90
                args = append(args, "--releaseNotes", params.ReleaseNotes)
×
91
        }
×
92

93
        uipcli := newUipcli(c.Exec, logger)
1✔
94
        cmd, err := uipcli.Execute(args...)
1✔
95
        if err != nil {
1✔
NEW
96
                return nil, err
×
97
        }
×
98
        stdout, err := cmd.StdoutPipe()
1✔
99
        if err != nil {
1✔
UNCOV
100
                return nil, fmt.Errorf("Could not run pack command: %v", err)
×
UNCOV
101
        }
×
102
        defer stdout.Close()
1✔
103
        stderr, err := cmd.StderrPipe()
1✔
104
        if err != nil {
1✔
UNCOV
105
                return nil, fmt.Errorf("Could not run pack command: %v", err)
×
UNCOV
106
        }
×
107
        defer stderr.Close()
1✔
108
        err = cmd.Start()
1✔
109
        if err != nil {
1✔
UNCOV
110
                return nil, fmt.Errorf("Could not run pack command: %v", err)
×
111
        }
×
112

113
        stderrOutputBuilder := new(strings.Builder)
1✔
114
        stderrReader := io.TeeReader(stderr, stderrOutputBuilder)
1✔
115

1✔
116
        var wg sync.WaitGroup
1✔
117
        wg.Add(3)
1✔
118
        go c.readOutput(stdout, logger, &wg)
1✔
119
        go c.readOutput(stderrReader, logger, &wg)
1✔
120
        go c.wait(cmd, &wg)
1✔
121
        wg.Wait()
1✔
122

1✔
123
        projectJson, err := c.readProjectJson(params.Source)
1✔
124
        if err != nil {
1✔
UNCOV
125
                return nil, err
×
UNCOV
126
        }
×
127

128
        exitCode := cmd.ExitCode()
1✔
129
        var result *packagePackResult
1✔
130
        if exitCode == 0 {
2✔
131
                nupkgFile := c.findNupkg(params.Destination)
1✔
132
                version := c.extractVersion(nupkgFile)
1✔
133
                result = newSucceededPackagePackResult(
1✔
134
                        filepath.Join(params.Destination, nupkgFile),
1✔
135
                        projectJson.Name,
1✔
136
                        projectJson.Description,
1✔
137
                        projectJson.ProjectId,
1✔
138
                        version)
1✔
139
        } else {
2✔
140
                result = newFailedPackagePackResult(
1✔
141
                        stderrOutputBuilder.String(),
1✔
142
                        &projectJson.Name,
1✔
143
                        &projectJson.Description,
1✔
144
                        &projectJson.ProjectId)
1✔
145
        }
1✔
146
        return result, nil
1✔
147
}
148

149
func (c PackagePackCommand) findNupkg(destination string) string {
1✔
150
        newestFile := ""
1✔
151
        newestTime := time.Time{}
1✔
152

1✔
153
        files, _ := os.ReadDir(destination)
1✔
154
        for _, file := range files {
2✔
155
                extension := filepath.Ext(file.Name())
1✔
156
                if strings.EqualFold(extension, ".nupkg") {
2✔
157
                        fileInfo, _ := file.Info()
1✔
158
                        time := fileInfo.ModTime()
1✔
159
                        if time.After(newestTime) {
2✔
160
                                newestTime = time
1✔
161
                                newestFile = file.Name()
1✔
162
                        }
1✔
163
                }
164
        }
165
        return newestFile
1✔
166
}
167

168
func (c PackagePackCommand) extractVersion(nupkgFile string) string {
1✔
169
        parts := strings.Split(nupkgFile, ".")
1✔
170
        len := len(parts)
1✔
171
        if len < 4 {
1✔
UNCOV
172
                return ""
×
UNCOV
173
        }
×
174
        return fmt.Sprintf("%s.%s.%s", parts[len-4], parts[len-3], parts[len-2])
1✔
175
}
176

177
func (c PackagePackCommand) wait(cmd utils.ExecCmd, wg *sync.WaitGroup) {
1✔
178
        defer wg.Done()
1✔
179
        _ = cmd.Wait()
1✔
180
}
1✔
181

182
func (c PackagePackCommand) newPackagingProgressBar(logger log.Logger) chan struct{} {
1✔
183
        progressBar := utils.NewProgressBar(logger)
1✔
184
        ticker := time.NewTicker(10 * time.Millisecond)
1✔
185
        cancel := make(chan struct{})
1✔
186
        go func() {
2✔
187
                for {
2✔
188
                        select {
1✔
189
                        case <-ticker.C:
1✔
190
                                progressBar.Tick("packaging...  ")
1✔
191
                        case <-cancel:
1✔
192
                                ticker.Stop()
1✔
193
                                progressBar.Remove()
1✔
194
                                return
1✔
195
                        }
196
                }
197
        }()
198
        return cancel
1✔
199
}
200

201
func (c PackagePackCommand) getSource(context plugin.ExecutionContext) (string, error) {
1✔
202
        source, _ := c.getParameter("source", context.Parameters)
1✔
203
        if source == "" {
1✔
UNCOV
204
                return "", errors.New("source is not set")
×
UNCOV
205
        }
×
206
        fileInfo, err := os.Stat(source)
1✔
207
        if err != nil {
2✔
208
                return "", fmt.Errorf("%s not found", defaultProjectJson)
1✔
209
        }
1✔
210
        if fileInfo.IsDir() {
2✔
211
                source = filepath.Join(source, defaultProjectJson)
1✔
212
        }
1✔
213
        return source, nil
1✔
214
}
215

216
func (c PackagePackCommand) readProjectJson(path string) (projectJson, error) {
1✔
217
        file, err := os.Open(path)
1✔
218
        if err != nil {
1✔
UNCOV
219
                return projectJson{}, fmt.Errorf("Error reading %s file: %v", defaultProjectJson, err)
×
UNCOV
220
        }
×
221
        defer file.Close()
1✔
222
        byteValue, err := io.ReadAll(file)
1✔
223
        if err != nil {
1✔
UNCOV
224
                return projectJson{}, fmt.Errorf("Error reading %s file: %v", defaultProjectJson, err)
×
UNCOV
225
        }
×
226

227
        var project projectJson
1✔
228
        err = json.Unmarshal(byteValue, &project)
1✔
229
        if err != nil {
1✔
UNCOV
230
                return projectJson{}, fmt.Errorf("Error parsing %s file: %v", defaultProjectJson, err)
×
UNCOV
231
        }
×
232
        return project, nil
1✔
233
}
234

235
func (c PackagePackCommand) getDestination(context plugin.ExecutionContext) (string, error) {
1✔
236
        destination, _ := c.getParameter("destination", context.Parameters)
1✔
237
        if destination == "" {
1✔
UNCOV
238
                return "", errors.New("destination is not set")
×
UNCOV
239
        }
×
240
        return destination, nil
1✔
241
}
242

243
func (c PackagePackCommand) readOutput(output io.Reader, logger log.Logger, wg *sync.WaitGroup) {
1✔
244
        defer wg.Done()
1✔
245
        scanner := bufio.NewScanner(output)
1✔
246
        scanner.Split(bufio.ScanRunes)
1✔
247
        for scanner.Scan() {
2✔
248
                logger.Log(scanner.Text())
1✔
249
        }
1✔
250
}
251

252
func (c PackagePackCommand) getParameter(name string, parameters []plugin.ExecutionParameter) (string, error) {
1✔
253
        for _, p := range parameters {
2✔
254
                if p.Name == name {
2✔
255
                        if data, ok := p.Value.(string); ok {
2✔
256
                                return data, nil
1✔
257
                        }
1✔
258
                }
259
        }
260
        return "", fmt.Errorf("Could not find '%s' parameter", name)
1✔
261
}
262

263
func (c PackagePackCommand) getBoolParameter(name string, parameters []plugin.ExecutionParameter) (bool, error) {
1✔
264
        for _, p := range parameters {
2✔
265
                if p.Name == name {
1✔
UNCOV
266
                        if data, ok := p.Value.(bool); ok {
×
UNCOV
267
                                return data, nil
×
UNCOV
268
                        }
×
269
                }
270
        }
271
        return false, fmt.Errorf("Could not find '%s' parameter", name)
1✔
272
}
273

274
func NewPackagePackCommand() *PackagePackCommand {
1✔
275
        return &PackagePackCommand{utils.NewExecProcess()}
1✔
276
}
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

© 2025 Coveralls, Inc