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

samsmithnz / RepoGovernance / 16895891586

12 Aug 2025 12:47AM UTC coverage: 44.71% (-26.7%) from 71.373%
16895891586

Pull #1001

github

web-flow
Merge 666b2ba0a into a12c1cae9
Pull Request #1001: Add repository details page with recommendation ignore functionality

401 of 1078 branches covered (37.2%)

Branch coverage included in aggregate %.

75 of 272 new or added lines in 6 files covered. (27.57%)

4 existing lines in 1 file now uncovered.

1023 of 2107 relevant lines covered (48.55%)

37.75 hits per line

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

16.99
/src/RepoGovernance.Service/Controllers/SummaryItemsController.cs
1
using Microsoft.AspNetCore.Mvc;
2
using RepoGovernance.Core;
3
using RepoGovernance.Core.Models;
4
using RepoGovernance.Service.Models;
5

6
namespace RepoGovernance.Service.Controllers
7
{
8
    [Route("api/[controller]")]
9
    [ApiController]
10
    public class SummaryItemsController : ControllerBase
11
    {
12
        private readonly IConfiguration Configuration;
13

14
        public SummaryItemsController(IConfiguration configuration)
5✔
15
        {
5✔
16
            Configuration = configuration;
5✔
17
        }
5✔
18

19
        [HttpGet("GetRepos")]
20
        public async Task<ActionResult<List<UserOwnerRepo>>> GetRepos(string owner)
21
        {
×
22
            if (!ModelState.IsValid)
×
23
            {
×
24
                return BadRequest(ModelState);
×
25
            }
26

27
            return await SummaryItemsDA.GetRepos(Configuration["AppSettings:CosmosDBConnectionString"], owner);
×
28
        }
×
29

30
        /// <summary>
31
        /// Update a target of summary item
32
        /// </summary>
33
        /// <param name="user">The user - often is also the owner, that has access to organizations</param>
34
        /// <param name="owner">The owner or organization</param>
35
        /// <param name="repo">the repository being updated</param>
36
        /// <returns></returns>
37
        [HttpGet("UpdateSummaryItem")]
38
        public async Task<ActionResult<int>> UpdateSummaryItem(string user, string owner, string repo)
39
        {
×
40
            if (!ModelState.IsValid)
×
41
            {
×
42
                return BadRequest(ModelState);
×
43
            }
44

45
            return await SummaryItemsDA.UpdateSummaryItem(
×
46
                Configuration["AppSettings:GitHubClientId"],
×
47
                Configuration["AppSettings:GitHubClientSecret"],
×
48
                Configuration["AppSettings:CosmosDBConnectionString"],//Configuration["AppSettings:StorageConnectionString"],
×
49
                Configuration["AppSettings:DevOpsServiceURL"],
×
50
                user, owner, repo,
×
51
                Configuration["AppSettings:GitHubId"],
×
52
                Configuration["AppSettings:GitHubSecret"],
×
53
                Configuration["AppSettings:AzureTenantId"],
×
54
                Configuration["AppSettings:AzureClientId"],
×
55
                Configuration["AppSettings:AzureClientSecret"]);
×
56
        }
×
57

58
        /// <summary>
59
        /// Update a target of summary item with optional NuGet package data
60
        /// </summary>
61
        /// <param name="request">The update request containing user, owner, repo, and optional NuGet payloads</param>
62
        /// <returns></returns>
63
        [HttpPost("UpdateSummaryItem")]
64
        public async Task<ActionResult<int>> UpdateSummaryItemWithNuGet(UpdateSummaryItemRequest request)
65
        {
2✔
66
            if (!ModelState.IsValid)
2!
67
            {
×
68
                return BadRequest(ModelState);
×
69
            }
70

71
            if (request?.User == null || request?.Owner == null || request?.Repo == null)
2!
72
            {
2✔
73
                return BadRequest("User, Owner, and Repo are required");
2✔
74
            }
75

76
            return await SummaryItemsDA.UpdateSummaryItem(
×
77
                Configuration["AppSettings:GitHubClientId"],
×
78
                Configuration["AppSettings:GitHubClientSecret"],
×
79
                Configuration["AppSettings:CosmosDBConnectionString"],
×
80
                Configuration["AppSettings:DevOpsServiceURL"],
×
81
                request.User, request.Owner, request.Repo,
×
82
                Configuration["AppSettings:GitHubId"],
×
83
                Configuration["AppSettings:GitHubSecret"],
×
84
                Configuration["AppSettings:AzureTenantId"],
×
85
                Configuration["AppSettings:AzureClientId"],
×
86
                Configuration["AppSettings:AzureClientSecret"],
×
87
                null, // azureDeployment
×
88
                request.NugetDeprecatedPayload,
×
89
                request.NugetOutdatedPayload,
×
90
                request.NugetVulnerablePayload);
×
91
        }
2✔
92

93
        [HttpPost("UpdateSummaryItemNuGetPackageStats")]
94
        public async Task<ActionResult<int>> UpdateSummaryItemNuGetPackageStats(NuGetPayload nugetPayload)
95
        {
2✔
96
            if (!ModelState.IsValid)
2!
97
            {
×
98
                return BadRequest(ModelState);
×
99
            }
100

101
            if (nugetPayload != null)
2✔
102
            {
1✔
103
                string? repo = nugetPayload?.Repo;
1!
104
                string? owner = nugetPayload?.Owner;
1!
105
                string? user = nugetPayload?.User;
1!
106
                //There is some weirdness when the json is embedded in this object and then the object is serialized a second time - it returns an array of strings.
107
                string? jsonPayload = nugetPayload?.JsonPayloadString;
1!
108
                string? payloadType = nugetPayload?.PayloadType;
1!
109

110
                if (repo == null || owner == null || user == null || jsonPayload == null || payloadType == null)
1!
111
                {
1✔
112
                    return BadRequest("Repo, Owner, User, JsonPayloadString, and PayloadType are required");
1✔
113
                }
114
                return await SummaryItemsDA.UpdateSummaryItemNuGetPackageStats(
×
115
                    Configuration["AppSettings:CosmosDBConnectionString"],
×
116
                    user, owner, repo,
×
117
                    Configuration["AppSettings:GitHubId"],
×
118
                    Configuration["AppSettings:GitHubSecret"],
×
119
                    jsonPayload, payloadType);
×
120
            }
121
            else
122
            {
1✔
123
                return BadRequest("NuGet payload is required");
1✔
124
            }
125
        }
2✔
126

127
        /// <summary>
128
        /// Get a list of summary item
129
        /// </summary>
130
        /// <param name="user">The user - often is also the owner, that has access to organizations</param>
131
        /// <returns></returns>
132
        [HttpGet("GetSummaryItems")]
133
        public async Task<ActionResult<List<SummaryItem>>> GetSummaryItems(string user)
134
        {
×
135
            if (!ModelState.IsValid)
×
136
            {
×
137
                return BadRequest(ModelState);
×
138
            }
139

140
            return await SummaryItemsDA.GetSummaryItems(
×
141
                Configuration["AppSettings:CosmosDBConnectionString"], //Configuration["AppSettings:StorageConnectionString"],
×
142
                user,
×
143
                Configuration["AppSettings:GitHubId"],
×
144
                Configuration["AppSettings:GitHubSecret"]);
×
145
        }
×
146

147
        /// <summary>
148
        /// Get a summary item
149
        /// </summary>
150
        /// <param name="owner">the owner or organization</param>
151
        /// <param name="repo">the repo</param>
152
        /// <returns></returns>
153
        [HttpGet("GetSummaryItem")]
154
        public async Task<ActionResult<SummaryItem?>> GetSummaryItem(string user, string owner, string repo)
155
        {
×
156
            if (!ModelState.IsValid)
×
157
            {
×
158
                return BadRequest(ModelState);
×
159
            }
160

161
            return await SummaryItemsDA.GetSummaryItem(
×
162
                Configuration["AppSettings:CosmosDBConnectionString"],
×
163
                user, owner, repo,
×
164
                Configuration["AppSettings:GitHubId"],
×
165
                Configuration["AppSettings:GitHubSecret"]);
×
166
        }
×
167

168

169
        [HttpGet("ApproveSummaryItemPRs")]
170
        public async Task<ActionResult<bool>> ApproveSummaryItemPRs(//string user, 
171
            string owner, string repo, string approver)
172
        {
×
173
            if (!ModelState.IsValid)
×
174
            {
×
175
                return BadRequest(ModelState);
×
176
            }
177

178
            return await SummaryItemsDA.ApproveSummaryItemPRs(
×
179
               Configuration["AppSettings:GitHubClientId"],
×
180
               Configuration["AppSettings:GitHubClientSecret"],
×
181
               owner, repo, approver);
×
182
        }
×
183

184
        /// <summary>
185
        /// Ignore a recommendation
186
        /// </summary>
187
        /// <param name="user">The user - often is also the owner, that has access to organizations</param>
188
        /// <param name="owner">The owner or organization</param>
189
        /// <param name="repo">The repository name</param>
190
        /// <param name="recommendationType">The recommendation type</param>
191
        /// <param name="recommendationDetails">The recommendation details</param>
192
        /// <returns>True if successful, false otherwise</returns>
193
        [HttpPost("IgnoreRecommendation")]
194
        public async Task<ActionResult<bool>> IgnoreRecommendation(string user, string owner, string repo, string recommendationType, string recommendationDetails)
NEW
195
        {
×
NEW
196
            if (!ModelState.IsValid)
×
NEW
197
            {
×
NEW
198
                return BadRequest(ModelState);
×
199
            }
200

NEW
201
            if (string.IsNullOrEmpty(user) || string.IsNullOrEmpty(owner) || string.IsNullOrEmpty(repo) || 
×
NEW
202
                string.IsNullOrEmpty(recommendationType) || string.IsNullOrEmpty(recommendationDetails))
×
NEW
203
            {
×
NEW
204
                return BadRequest("User, owner, repo, recommendationType, and recommendationDetails are required");
×
205
            }
206

207
            try
NEW
208
            {
×
NEW
209
                string connectionString = Configuration.GetConnectionString("DefaultConnection") ?? "UseDevelopmentStorage=true";
×
NEW
210
                IgnoredRecommendationsDA ignoredRecommendationsDA = new IgnoredRecommendationsDA(connectionString);
×
NEW
211
                await ignoredRecommendationsDA.IgnoreRecommendation(user, owner, repo, recommendationType, recommendationDetails);
×
NEW
212
                return true;
×
213
            }
NEW
214
            catch
×
NEW
215
            {
×
NEW
216
                return false;
×
217
            }
NEW
218
        }
×
219

220
        /// <summary>
221
        /// Restore/unignore a recommendation
222
        /// </summary>
223
        /// <param name="user">The user - often is also the owner, that has access to organizations</param>
224
        /// <param name="owner">The owner or organization</param>
225
        /// <param name="repo">The repository name</param>
226
        /// <param name="recommendationType">The recommendation type</param>
227
        /// <param name="recommendationDetails">The recommendation details</param>
228
        /// <returns>True if successful, false otherwise</returns>
229
        [HttpPost("RestoreRecommendation")]
230
        public async Task<ActionResult<bool>> RestoreRecommendation(string user, string owner, string repo, string recommendationType, string recommendationDetails)
NEW
231
        {
×
NEW
232
            if (!ModelState.IsValid)
×
NEW
233
            {
×
NEW
234
                return BadRequest(ModelState);
×
235
            }
236

NEW
237
            if (string.IsNullOrEmpty(user) || string.IsNullOrEmpty(owner) || string.IsNullOrEmpty(repo) || 
×
NEW
238
                string.IsNullOrEmpty(recommendationType) || string.IsNullOrEmpty(recommendationDetails))
×
NEW
239
            {
×
NEW
240
                return BadRequest("User, owner, repo, recommendationType, and recommendationDetails are required");
×
241
            }
242

243
            try
NEW
244
            {
×
NEW
245
                string connectionString = Configuration.GetConnectionString("DefaultConnection") ?? "UseDevelopmentStorage=true";
×
NEW
246
                IgnoredRecommendationsDA ignoredRecommendationsDA = new IgnoredRecommendationsDA(connectionString);
×
NEW
247
                await ignoredRecommendationsDA.UnignoreRecommendation(user, owner, repo, recommendationType, recommendationDetails);
×
NEW
248
                return true;
×
249
            }
NEW
250
            catch
×
NEW
251
            {
×
NEW
252
                return false;
×
253
            }
NEW
254
        }
×
255

256
        /// <summary>
257
        /// Get all ignored recommendations for a user, owner, and repository
258
        /// </summary>
259
        /// <param name="user">The user - often is also the owner, that has access to organizations</param>
260
        /// <param name="owner">The owner or organization</param>
261
        /// <param name="repo">The repository name</param>
262
        /// <returns>List of ignored recommendations</returns>
263
        [HttpGet("GetIgnoredRecommendations")]
264
        public async Task<ActionResult<List<IgnoredRecommendation>>> GetIgnoredRecommendations(string user, string owner, string repo)
NEW
265
        {
×
NEW
266
            if (!ModelState.IsValid)
×
NEW
267
            {
×
NEW
268
                return BadRequest(ModelState);
×
269
            }
270

NEW
271
            if (string.IsNullOrEmpty(user) || string.IsNullOrEmpty(owner) || string.IsNullOrEmpty(repo))
×
NEW
272
            {
×
NEW
273
                return BadRequest("User, owner, and repo are required");
×
274
            }
275

276
            try
NEW
277
            {
×
NEW
278
                string connectionString = Configuration.GetConnectionString("DefaultConnection") ?? "UseDevelopmentStorage=true";
×
NEW
279
                IgnoredRecommendationsDA ignoredRecommendationsDA = new IgnoredRecommendationsDA(connectionString);
×
NEW
280
                List<IgnoredRecommendation> results = await ignoredRecommendationsDA.GetIgnoredRecommendations(user, owner, repo);
×
NEW
281
                return results;
×
282
            }
NEW
283
            catch
×
NEW
284
            {
×
NEW
285
                return new List<IgnoredRecommendation>();
×
286
            }
NEW
287
        }
×
288

289
        /// <summary>
290
        /// Get all ignored recommendations for a user across all repositories
291
        /// </summary>
292
        /// <param name="user">The user - often is also the owner, that has access to organizations</param>
293
        /// <returns>List of ignored recommendations</returns>
294
        [HttpGet("GetAllIgnoredRecommendations")]
295
        public async Task<ActionResult<List<IgnoredRecommendation>>> GetAllIgnoredRecommendations(string user)
NEW
296
        {
×
NEW
297
            if (!ModelState.IsValid)
×
NEW
298
            {
×
NEW
299
                return BadRequest(ModelState);
×
300
            }
301

NEW
302
            if (string.IsNullOrEmpty(user))
×
NEW
303
            {
×
NEW
304
                return BadRequest("User is required");
×
305
            }
306

307
            try
NEW
308
            {
×
NEW
309
                string connectionString = Configuration.GetConnectionString("DefaultConnection") ?? "UseDevelopmentStorage=true";
×
NEW
310
                IgnoredRecommendationsDA ignoredRecommendationsDA = new IgnoredRecommendationsDA(connectionString);
×
NEW
311
                List<IgnoredRecommendation> results = await ignoredRecommendationsDA.GetIgnoredRecommendations(user);
×
NEW
312
                return results;
×
313
            }
NEW
314
            catch
×
NEW
315
            {
×
NEW
316
                return new List<IgnoredRecommendation>();
×
317
            }
NEW
318
        }
×
319
    }
320
}
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