This repository was archived by the owner on Jul 3, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathProgram.cs
executable file
·205 lines (178 loc) · 8.28 KB
/
Program.cs
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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
using System;
using System.Net;
using System.Net.Http;
using System.Text;
using Codacy.CSharpCoverage.Models.Result;
using Codacy.CSharpCoverage.Parsing.Processors;
using CommandLine;
namespace Codacy.CSharpCoverage
{
internal class Program
{
private static int Main(string[] args)
{
int exitcode = 0;
// parse the option arguments
Parser.Default.ParseArguments<Options>(args)
.WithParsed(opt =>
{
if (opt.Final)
{
MakeFinalRequest(opt.CommitUUID, opt.Token);
}
else if (string.IsNullOrEmpty(opt.ReportFile))
{
throw new FormatException(
"Unspecified report file! Use -r or type --help");
}
else if (string.IsNullOrEmpty(opt.ReportType))
{
throw new FormatException(
"Unspecified report type! Use -e or type --help");
}
else
{
CodacyReport report;
switch (opt.ReportType)
{
case "dotcover":
var dotCoverProcessor = new DotCoverProcessor();
var dotCoverParsed = dotCoverProcessor.Parse(opt.ReportFile);
report = dotCoverProcessor.Transform(dotCoverParsed);
break;
case "opencover":
var openCoverProcessor = new OpenCoverProcessor();
var openCoverParsed = openCoverProcessor.Parse(opt.ReportFile);
report = openCoverProcessor.Transform(openCoverParsed);
break;
default:
throw new FormatException(
"Unrecognized report format, please choose dotcover or opencover");
}
SendReport(report, opt.CommitUUID, opt.Token, opt.Partial);
}
})
.WithNotParsed(errs => exitcode = 1);
return exitcode;
}
/// <summary>
/// Send the report using Codacy API
/// </summary>
/// <param name="report">codacy report result</param>
/// <param name="commitUuid">commit uuid</param>
/// <param name="projectToken">project token</param>
/// <param name="isPartial">partial flag</param>
/// <exception cref="FormatException">if it's passed an invalid commit uuid or project token</exception>
/// <exception cref="HttpRequestException">if the api response status code is not 200.</exception>
private static void SendReport(CodacyReport report, string commitUuid, string projectToken, bool isPartial)
{
if (string.IsNullOrEmpty(commitUuid))
{
throw new FormatException("Invalid commit UUID");
}
if (string.IsNullOrEmpty(projectToken))
{
throw new FormatException("Invalid project token");
}
MakeReportRequest(report.ToString(), commitUuid, projectToken, isPartial);
Console.WriteLine(report.GetStats());
}
/// <summary>
/// Get base API URL or the default as a fallback.
/// </summary>
/// <returns>Return Codacy base API URL</returns>
/// <exception cref="FormatException">If environment variable has an invalid URL</exception>
private static string GetBaseApiOrDefault()
{
// gets the environment variable
var envApi = Environment.GetEnvironmentVariable("CODACY_API_BASE_URL");
// check if the url is valid
if (!(envApi?.StartsWith("http") ?? true))
{
throw new FormatException(
"Invalid custom API base URL! Need to start w/ http");
}
// return environment variable or default as a fallback
return envApi ?? "https://api.codacy.com";
}
/// <summary>
/// Make the final request to the API.
/// To complete a coverage report, you need to send this, otherwise,
/// the partial coverage reports will not be aggregated and then not available.
/// </summary>
/// <param name="commitUuid">commit uuid</param>
/// <param name="projectToken">project token</param>
/// <returns>an async http response</returns>
private static HttpResponseMessage MakeFinalRequest(string commitUuid, string projectToken)
{
return MakeRequest("{}", $"/2.0/commit/{commitUuid}/coverageFinal",
projectToken);
}
/// <summary>
/// Make the coverage report request to the API.
/// To send a coverage report, you need to send this request.
/// </summary>
/// <param name="json">string-based json (body content of the request)</param>
/// <param name="commitUuid">commit uuid</param>
/// <param name="projectToken">project token</param>
/// <param name="isPartial">partial flag</param>
/// <returns></returns>
private static HttpResponseMessage MakeReportRequest(string json, string commitUuid,
string projectToken,
bool isPartial)
{
var partial = isPartial ? "true" : "false";
return MakeRequest(json,
$"/2.0/coverage/{commitUuid}/CSharp?partial={partial}", projectToken);
}
/// <summary>
/// Make a generic request to Codacy API.
/// This sets the required request headers and send the specified content to
/// a certain endpoint.
/// </summary>
/// <param name="content">string-based json content</param>
/// <param name="endpoint">api endpoint</param>
/// <param name="projectToken">project token</param>
/// <returns></returns>
private static HttpResponseMessage MakeRequest(string content, string endpoint, string projectToken)
{
//prepare url with base api url and the endpoint
var destUri = new Uri($"{GetBaseApiOrDefault()}{endpoint}");
//required headers
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Accept", "application/json");
client.DefaultRequestHeaders.Add("project_token", projectToken);
//post request
var res = client.PostAsync(destUri, new StringContent(content, Encoding.UTF8, "application/json")).Result;
Console.WriteLine(res.Content);
Console.WriteLine("Response status: " + res.StatusCode);
if (res.StatusCode != HttpStatusCode.OK)
{
throw new HttpRequestException("Unexpected response status code!");
}
else
{
return res;
}
}
/// <summary>
/// Program options.
/// This class specifies the arguments passed to the program when it's called.
/// </summary>
public class Options
{
[Option('p', "partial", Required = false, HelpText = "Send report as a partial report", Default = false)]
public bool Partial { get; set; }
[Option('f', "final", Required = false, HelpText = "Send final coverage report request", Default = false)]
public bool Final { get; set; }
[Option('c', "commit", Required = true, HelpText = "Specify the commit UUID")]
public string CommitUUID { get; set; }
[Option('t', "token", Required = true, HelpText = "Specify the project token")]
public string Token { get; set; }
[Option('r', "report", Required = false, HelpText = "Path to the coverage report")]
public string ReportFile { get; set; }
[Option('e', "engine", Required = false, HelpText = "Engine Report Type (dotcover, opencover).")]
public string ReportType { get; set; }
}
}
}