Repository navigation
Expand file tree
/
Copy pathrunner.go
More file actions
191 lines (156 loc) · 6.65 KB
/
Copy pathrunner.go
File metadata and controls
191 lines (156 loc) · 6.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
package plugin
import (
"fmt"
"io"
"strconv"
"strings"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/target/pull-request-code-coverage/internal/plugin/calculator"
"github.com/target/pull-request-code-coverage/internal/plugin/coverage"
"github.com/target/pull-request-code-coverage/internal/plugin/coverage/cobertura"
"github.com/target/pull-request-code-coverage/internal/plugin/coverage/jacoco"
"github.com/target/pull-request-code-coverage/internal/plugin/coverage/lcov"
"github.com/target/pull-request-code-coverage/internal/plugin/coverage/pythoncov"
"github.com/target/pull-request-code-coverage/internal/plugin/githubdiff"
"github.com/target/pull-request-code-coverage/internal/plugin/pluginhttp"
"github.com/target/pull-request-code-coverage/internal/plugin/pluginjson"
"github.com/target/pull-request-code-coverage/internal/plugin/reporter"
"github.com/target/pull-request-code-coverage/internal/plugin/sourcelines/unifieddiff"
)
// defaultGithubAPIBaseURL is the public GitHub REST API root. GitHub Enterprise
// users should set PARAMETER_GH_API_BASE_URL to their API root (e.g.
// https://git.example.com/api/v3).
const defaultGithubAPIBaseURL = "https://api.github.com"
type DefaultRunner struct{}
func NewRunner() *DefaultRunner {
return &DefaultRunner{}
}
// Run ...
// nolint: gocyclo
func (*DefaultRunner) Run(propertyGetter func(string) (string, bool), changedSourceLinesSource io.Reader, reportDefaultOut io.Writer) error {
logrus.Info("starting pull-request-code-coverage run")
rawSourceDirs, found := propertyGetter("PARAMETER_SOURCE_DIRS")
if !found {
return errors.New("Missing property PARAMETER_SOURCE_DIRS")
}
logrus.Info(fmt.Sprintf("PARAMETER_SOURCE_DIRS set to %v", rawSourceDirs))
sourceDirs := parseSourceDirs(rawSourceDirs)
coverageType, found := propertyGetter("PARAMETER_COVERAGE_TYPE")
if !found {
return errors.New("Missing property PARAMETER_COVERAGE_TYPE")
}
loader, getLoaderErr := getCoverageReportLoader(coverageType, sourceDirs)
if getLoaderErr != nil {
return errors.Wrap(getLoaderErr, "Failed opening coverage loader")
}
coverageFile, found := propertyGetter("PARAMETER_COVERAGE_FILE")
if !found {
return errors.New("Missing property PARAMETER_COVERAGE_FILE")
}
module, found := propertyGetter("PARAMETER_MODULE")
if !found {
logrus.Info("PARAMETER_MODULE was missing defaulting to false")
module = ""
}
ghAPIKey, ghAPIKeyFound := propertyGetter("PARAMETER_GH_API_KEY")
if !ghAPIKeyFound {
ghAPIKey, ghAPIKeyFound = propertyGetter("PLUGIN_GH_API_KEY")
if !ghAPIKeyFound {
logrus.Info("PARAMETER_GH_API_KEY/PLUGIN_GH_API_KEY was missing, will not send report to PR comments")
}
}
ghAPIBaseURL, ghAPIBaseURLFound := propertyGetter("PARAMETER_GH_API_BASE_URL")
if !ghAPIBaseURLFound || ghAPIBaseURL == "" {
ghAPIBaseURL = defaultGithubAPIBaseURL
logrus.Info(fmt.Sprintf("PARAMETER_GH_API_BASE_URL was missing, defaulting to %v", ghAPIBaseURL))
}
repoPR, repoPRFound := propertyGetter("BUILD_PULL_REQUEST_NUMBER")
if !repoPRFound {
logrus.Info("BUILD_PULL_REQUEST_NUMBER was missing, will not send report to PR comments")
}
repoOwner, repoOwnerFound := propertyGetter("REPOSITORY_ORG")
if !repoOwnerFound {
logrus.Info("REPOSITORY_ORG was missing, will not send report to PR comments")
}
repoName, repoNameFound := propertyGetter("REPOSITORY_NAME")
if !repoNameFound {
logrus.Info("REPOSITORY_NAME was missing, will not send report to PR comments")
}
coverageReport, loadCoverageErr := loader.Load(coverageFile)
if loadCoverageErr != nil {
return errors.Wrap(loadCoverageErr, "Failed loading coverage report")
}
diffSource, found := propertyGetter("PARAMETER_DIFF_SOURCE")
if !found || diffSource == "" {
logrus.Info("PARAMETER_DIFF_SOURCE was missing, defaulting to stdin")
diffSource = "stdin"
}
switch diffSource {
case "stdin":
// changedSourceLinesSource already points at the piped-in diff (stdin);
// nothing to do. This is the original, default behavior.
case "github":
if !ghAPIKeyFound || !repoPRFound || !repoOwnerFound || !repoNameFound {
return errors.New("PARAMETER_DIFF_SOURCE=github requires a GitHub API key (PARAMETER_GH_API_KEY), BUILD_PULL_REQUEST_NUMBER, REPOSITORY_ORG and REPOSITORY_NAME")
}
logrus.Info("PARAMETER_DIFF_SOURCE is github, fetching diff from the GitHub API")
diffReader, fetchErr := githubdiff.NewLoader(ghAPIKey, ghAPIBaseURL, repoPR, repoOwner, repoName, &pluginhttp.DefaultClient{}).Load()
if fetchErr != nil {
return errors.Wrap(fetchErr, "Failed fetching diff from github")
}
changedSourceLinesSource = diffReader
default:
return errors.Errorf("Unknown PARAMETER_DIFF_SOURCE %q (expected \"stdin\" or \"github\")", diffSource)
}
changedLines, changedLinesErr := unifieddiff.NewChangedSourceLinesLoader(module, sourceDirs).Load(changedSourceLinesSource)
if changedLinesErr != nil {
return errors.Wrap(changedLinesErr, "Failed loading changed lines")
}
debugStr, found := propertyGetter("PARAMETER_DEBUG")
if !found {
logrus.Info("PARAMETER_DEBUG was missing defaulting to false")
debugStr = "false"
}
debug, parseDebugErr := strconv.ParseBool(debugStr)
if parseDebugErr != nil {
logrus.Info("PARAMETER_DEBUG was invalid, defaulting to false")
debug = false
}
if debug {
logrus.SetLevel(logrus.DebugLevel)
}
changedLinesWithCoverage := calculator.NewCoverage().DetermineCoverage(changedLines, coverageReport)
reporters := []reporter.Reporter{reporter.NewSimple(reportDefaultOut)}
if ghAPIKeyFound && repoPRFound && repoOwnerFound && repoNameFound {
reporters = append(reporters, reporter.NewGithubPullRequest(ghAPIKey, ghAPIBaseURL, repoPR, repoOwner, repoName, &pluginhttp.DefaultClient{}, &pluginjson.DefaultClient{}))
}
logrus.Info("enabled reporters are ")
for _, eachOne := range reporters {
logrus.Info(eachOne.GetName())
}
return reporter.NewForking(reporters).Write(changedLinesWithCoverage)
}
func parseSourceDirs(rawSourceDirStr string) []string {
rawSourceDirs := strings.Split(rawSourceDirStr, ",")
resultSoruceDirs := make([]string, len(rawSourceDirs))
for idx, rs := range rawSourceDirs {
resultSoruceDirs[idx] = strings.TrimSpace(rs)
}
return resultSoruceDirs
}
func getCoverageReportLoader(coverageType string, sourceDirs []string) (coverage.Loader, error) {
switch coverageType {
case "cobertura":
if len(sourceDirs) != 1 {
return nil, errors.Errorf("Currently not supporting multiple source dirs with cobertura coverage report type.")
}
return cobertura.NewReportLoader(sourceDirs[0]), nil
case "python":
return pythoncov.NewReportLoader(), nil
case "lcov", "javascript", "typescript":
return lcov.NewReportLoader(), nil
default:
return jacoco.NewReportLoader(), nil
}
}