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

murex / TCR / 19010290325

02 Nov 2025 09:22AM UTC coverage: 89.66% (-0.03%) from 89.694%
19010290325

push

github

mengdaming
Update node dependencies

5272 of 5880 relevant lines covered (89.66%)

1054.41 hits per line

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

93.65
/src/toolchain/command/command_runner.go
1
/*
2
Copyright (c) 2024 Murex
3

4
Permission is hereby granted, free of charge, to any person obtaining a copy
5
of this software and associated documentation files (the "Software"), to deal
6
in the Software without restriction, including without limitation the rights
7
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
copies of the Software, and to permit persons to whom the Software is
9
furnished to do so, subject to the following conditions:
10

11
The above copyright notice and this permission notice shall be included in all
12
copies or substantial portions of the Software.
13

14
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
SOFTWARE.
21
*/
22

23
package command
24

25
import (
26
        "bufio"
27
        "io"
28
        "os/exec"
29
        "sync"
30

31
        "github.com/murex/tcr/report"
32
)
33

34
type (
35
        // Runner is in charge of managing the lifecycle of a command
36
        Runner struct {
37
                command *exec.Cmd
38
                // commandMutex is here to enforce that commands run in sequence
39
                commandMutex sync.Mutex
40
        }
41

42
        // Status is the result status of a Command execution
43
        Status string
44

45
        // Result contains the result from running a Command
46
        Result struct {
47
                Status Status
48
                Output string
49
        }
50
)
51

52
// Failed indicates is a Command failed
53
func (r Result) Failed() bool {
9✔
54
        return r.Status == StatusFail
9✔
55
}
9✔
56

57
// Passed indicates is a Command passed
58
func (r Result) Passed() bool {
9✔
59
        return r.Status == StatusPass
9✔
60
}
9✔
61

62
// List of possible values for Status
63
const (
64
        StatusPass    Status = "pass"
65
        StatusFail    Status = "fail"
66
        StatusUnknown Status = "unknown"
67
)
68

69
// runner singleton instance
70
var runner = &Runner{
71
        command: nil,
72
}
73

74
// GetRunner returns the command runner singleton instance
75
func GetRunner() *Runner {
19✔
76
        return runner
19✔
77
}
19✔
78

79
// Run launches the execution of the provided command
80
func (r *Runner) Run(fromDir string, cmd *Command) (result Result) {
11✔
81
        runner.commandMutex.Lock()
11✔
82
        result = Result{Status: StatusUnknown, Output: ""}
11✔
83
        report.PostText(cmd.AsCommandLine())
11✔
84

11✔
85
        // Prepare the command
11✔
86
        r.command = exec.Command(cmd.Path, cmd.Arguments...) //nolint:gosec
11✔
87
        if fromDir != "" {
11✔
88
                r.command.Dir = fromDir
×
89
        }
×
90

91
        // Allow simultaneous trace and capture of command's stdout and stderr
92
        outReader, _ := r.command.StdoutPipe()
11✔
93
        errReader, _ := r.command.StderrPipe()
11✔
94
        r.reportTrace(outReader)
11✔
95
        r.reportTrace(errReader)
11✔
96

11✔
97
        // Start the command asynchronously
11✔
98
        errStart := r.command.Start()
11✔
99
        if errStart != nil {
14✔
100
                report.PostError("Failed to run command: ", errStart.Error())
3✔
101
                // We currently return fail status when command cannot be launched.
3✔
102
                // This is to replicate previous implementation's behaviour where
3✔
103
                // we could not differentiate between failure to launch and failure from execution.
3✔
104
                // We could later on use a different return value in this situation,
3✔
105
                // but we need to ensure first that TCR engine can handle it correctly.
3✔
106
                result.Status = StatusFail
3✔
107
                r.command = nil
3✔
108
                runner.commandMutex.Unlock()
3✔
109
                return result
3✔
110
        }
3✔
111

112
        // Wait for the command to finish
113
        errWait := r.command.Wait()
8✔
114
        if errWait != nil {
13✔
115
                result.Status = StatusFail
5✔
116
        } else {
8✔
117
                result.Status = StatusPass
3✔
118
        }
3✔
119

120
        r.command = nil
8✔
121
        runner.commandMutex.Unlock()
8✔
122
        return result
8✔
123
}
124

125
func (*Runner) reportTrace(readCloser io.ReadCloser) {
22✔
126
        scanner := bufio.NewScanner(readCloser)
22✔
127
        go func() {
44✔
128
                for scanner.Scan() {
22✔
129
                        report.PostText(scanner.Text())
×
130
                }
×
131
        }()
132
}
133

134
// AbortRunningCommand triggers aborting of any command that is currently running
135
func (r *Runner) AbortRunningCommand() bool {
4✔
136
        if r.command == nil || r.command.Process == nil {
6✔
137
                report.PostWarning("There is no command running at this time")
2✔
138
                return false
2✔
139
        }
2✔
140
        report.PostWarning("Aborting command: \"", r.command.String(), "\"")
2✔
141
        _ = r.command.Process.Kill()
2✔
142
        // Calling Kill() may be a bit too brutal (may leave children process alive)
2✔
143
        //_ = r.command.Process.Signal(os.Kill)
2✔
144
        return true
2✔
145
}
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