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

UiPath / uipathcli / 12369708205

17 Dec 2024 09:05AM UTC coverage: 86.931% (-2.6%) from 89.549%
12369708205

push

github

thschmitt
Add support to analyze studio projects

34 of 195 new or added lines in 6 files covered. (17.44%)

3 existing lines in 2 files now uncovered.

4643 of 5341 relevant lines covered (86.93%)

0.98 hits per line

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

6.0
/plugin/studio/package_analyze_command.go
1
package studio
2

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

19
        "github.com/UiPath/uipathcli/log"
20
        "github.com/UiPath/uipathcli/output"
21
        "github.com/UiPath/uipathcli/plugin"
22
        "github.com/UiPath/uipathcli/utils"
23
)
24

25
// The PackageAnalyzeCommand runs static code analyis on the project to detect common errors.
26
type PackageAnalyzeCommand struct {
27
        Exec utils.ExecProcess
28
}
29

30
func (c PackageAnalyzeCommand) Command() plugin.Command {
1✔
31
        return *plugin.NewCommand("studio").
1✔
32
                WithCategory("package", "Package", "UiPath Studio package-related actions").
1✔
33
                WithOperation("analyze", "Analyze Project", "Runs static code analysis on the project to detect common errors").
1✔
34
                WithParameter("source", plugin.ParameterTypeString, "Path to a project.json file or a folder containing project.json file", true)
1✔
35
}
1✔
36

NEW
37
func (c PackageAnalyzeCommand) Execute(context plugin.ExecutionContext, writer output.OutputWriter, logger log.Logger) error {
×
NEW
38
        source, err := c.getSource(context)
×
NEW
39
        if err != nil {
×
NEW
40
                return err
×
NEW
41
        }
×
NEW
42
        result, err := c.execute(source, context.Debug, logger)
×
NEW
43
        if err != nil {
×
NEW
44
                return err
×
NEW
45
        }
×
46

NEW
47
        json, err := json.Marshal(result)
×
NEW
48
        if err != nil {
×
NEW
49
                return fmt.Errorf("analyze command failed: %v", err)
×
NEW
50
        }
×
NEW
51
        return writer.WriteResponse(*output.NewResponseInfo(200, "200 OK", "HTTP/1.1", map[string][]string{}, bytes.NewReader(json)))
×
52
}
53

NEW
54
func (c PackageAnalyzeCommand) execute(source string, debug bool, logger log.Logger) (*packageAnalyzeResult, error) {
×
NEW
55
        if !debug {
×
NEW
56
                bar := c.newAnalyzingProgressBar(logger)
×
NEW
57
                defer close(bar)
×
NEW
58
        }
×
59

NEW
60
        jsonResultFilePath, err := c.getTemporaryJsonResultFilePath()
×
NEW
61
        if err != nil {
×
NEW
62
                return nil, err
×
NEW
63
        }
×
NEW
64
        defer os.Remove(jsonResultFilePath)
×
NEW
65
        args := []string{"package", "analyze", source, "--resultPath", jsonResultFilePath}
×
NEW
66

×
NEW
67
        uipcli := newUipcli(c.Exec, logger)
×
NEW
68
        cmd, err := uipcli.Execute(args...)
×
NEW
69
        if err != nil {
×
NEW
70
                return nil, err
×
NEW
71
        }
×
NEW
72
        stdout, err := cmd.StdoutPipe()
×
NEW
73
        if err != nil {
×
NEW
74
                return nil, fmt.Errorf("Could not run analyze command: %v", err)
×
NEW
75
        }
×
NEW
76
        defer stdout.Close()
×
NEW
77
        stderr, err := cmd.StderrPipe()
×
NEW
78
        if err != nil {
×
NEW
79
                return nil, fmt.Errorf("Could not run analyze command: %v", err)
×
NEW
80
        }
×
NEW
81
        defer stderr.Close()
×
NEW
82
        err = cmd.Start()
×
NEW
83
        if err != nil {
×
NEW
84
                return nil, fmt.Errorf("Could not run analyze command: %v", err)
×
NEW
85
        }
×
86

NEW
87
        stderrOutputBuilder := new(strings.Builder)
×
NEW
88
        stderrReader := io.TeeReader(stderr, stderrOutputBuilder)
×
NEW
89

×
NEW
90
        var wg sync.WaitGroup
×
NEW
91
        wg.Add(3)
×
NEW
92
        go c.readOutput(stdout, logger, &wg)
×
NEW
93
        go c.readOutput(stderrReader, logger, &wg)
×
NEW
94
        go c.wait(cmd, &wg)
×
NEW
95
        wg.Wait()
×
NEW
96

×
NEW
97
        _, err = c.readAnalyzeResult(jsonResultFilePath)
×
NEW
98
        if err != nil {
×
NEW
99
                return nil, err
×
NEW
100
        }
×
101

NEW
102
        exitCode := cmd.ExitCode()
×
NEW
103
        var result *packageAnalyzeResult
×
NEW
104
        if exitCode == 0 {
×
NEW
105
                result = newSucceededPackageAnalyzeResult()
×
NEW
106
        } else {
×
NEW
107
                result = newFailedPackageAnalyzeResult(
×
NEW
108
                        stderrOutputBuilder.String(),
×
NEW
109
                )
×
NEW
110
        }
×
NEW
111
        return result, nil
×
112
}
113

NEW
114
func (c PackageAnalyzeCommand) getTemporaryJsonResultFilePath() (string, error) {
×
NEW
115
        tempDirectory, err := utils.Directories{}.Temp()
×
NEW
116
        if err != nil {
×
NEW
117
                return "", err
×
NEW
118
        }
×
NEW
119
        fileName := c.randomJsonResultFileName()
×
NEW
120
        return filepath.Join(tempDirectory, fileName), nil
×
121
}
122

NEW
123
func (c PackageAnalyzeCommand) randomJsonResultFileName() string {
×
NEW
124
        value, _ := rand.Int(rand.Reader, big.NewInt(math.MaxInt64))
×
NEW
125
        return "analyzeresult-" + value.String() + ".json"
×
NEW
126
}
×
127

NEW
128
func (c PackageAnalyzeCommand) readAnalyzeResult(path string) (analyzeResultJson, error) {
×
NEW
129
        file, err := os.Open(path)
×
NEW
130
        if err != nil {
×
NEW
131
                return analyzeResultJson{}, fmt.Errorf("Error reading %s file: %v", filepath.Base(path), err)
×
NEW
132
        }
×
NEW
133
        defer file.Close()
×
NEW
134
        byteValue, err := io.ReadAll(file)
×
NEW
135
        if err != nil {
×
NEW
136
                return analyzeResultJson{}, fmt.Errorf("Error reading %s file: %v", filepath.Base(path), err)
×
NEW
137
        }
×
138

NEW
139
        var result analyzeResultJson
×
NEW
140
        err = json.Unmarshal(byteValue, &result)
×
NEW
141
        if err != nil {
×
NEW
142
                return analyzeResultJson{}, fmt.Errorf("Error parsing %s file: %v", filepath.Base(path), err)
×
NEW
143
        }
×
NEW
144
        return result, nil
×
145
}
146

NEW
147
func (c PackageAnalyzeCommand) wait(cmd utils.ExecCmd, wg *sync.WaitGroup) {
×
NEW
148
        defer wg.Done()
×
NEW
149
        _ = cmd.Wait()
×
NEW
150
}
×
151

NEW
152
func (c PackageAnalyzeCommand) newAnalyzingProgressBar(logger log.Logger) chan struct{} {
×
NEW
153
        progressBar := utils.NewProgressBar(logger)
×
NEW
154
        ticker := time.NewTicker(10 * time.Millisecond)
×
NEW
155
        cancel := make(chan struct{})
×
NEW
156
        go func() {
×
NEW
157
                for {
×
NEW
158
                        select {
×
NEW
159
                        case <-ticker.C:
×
NEW
160
                                progressBar.Tick("analyze...    ")
×
NEW
161
                        case <-cancel:
×
NEW
162
                                ticker.Stop()
×
NEW
163
                                progressBar.Remove()
×
NEW
164
                                return
×
165
                        }
166
                }
167
        }()
NEW
168
        return cancel
×
169
}
170

NEW
171
func (c PackageAnalyzeCommand) getSource(context plugin.ExecutionContext) (string, error) {
×
NEW
172
        source, _ := c.getParameter("source", context.Parameters)
×
NEW
173
        if source == "" {
×
NEW
174
                return "", errors.New("source is not set")
×
NEW
175
        }
×
NEW
176
        fileInfo, err := os.Stat(source)
×
NEW
177
        if err != nil {
×
NEW
178
                return "", fmt.Errorf("%s not found", defaultProjectJson)
×
NEW
179
        }
×
NEW
180
        if fileInfo.IsDir() {
×
NEW
181
                source = filepath.Join(source, defaultProjectJson)
×
NEW
182
        }
×
NEW
183
        return source, nil
×
184
}
185

NEW
186
func (c PackageAnalyzeCommand) readOutput(output io.Reader, logger log.Logger, wg *sync.WaitGroup) {
×
NEW
187
        defer wg.Done()
×
NEW
188
        scanner := bufio.NewScanner(output)
×
NEW
189
        scanner.Split(bufio.ScanRunes)
×
NEW
190
        for scanner.Scan() {
×
NEW
191
                logger.Log(scanner.Text())
×
NEW
192
        }
×
193
}
194

NEW
195
func (c PackageAnalyzeCommand) getParameter(name string, parameters []plugin.ExecutionParameter) (string, error) {
×
NEW
196
        for _, p := range parameters {
×
NEW
197
                if p.Name == name {
×
NEW
198
                        if data, ok := p.Value.(string); ok {
×
NEW
199
                                return data, nil
×
NEW
200
                        }
×
201
                }
202
        }
NEW
203
        return "", fmt.Errorf("Could not find '%s' parameter", name)
×
204
}
205

206
func NewPackageAnalyzeCommand() *PackageAnalyzeCommand {
1✔
207
        return &PackageAnalyzeCommand{utils.NewExecProcess()}
1✔
208
}
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