Skip to content

Commit 430b572

Browse files
authored
fix hub (#41)
* reset the hub locations * adding back overwritten changes * Rerelease with correct fixes * Adding missing things
1 parent 4969764 commit 430b572

File tree

8 files changed

+86
-35
lines changed

8 files changed

+86
-35
lines changed

img/hub.png

234 KB
Loading

overview.md

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ Install from the marketplace: https://marketplace.visualstudio.com/items?itemNam
1212

1313
> Note: only project level dashboards are supported at the moment.
1414
15+
## Dashboard
16+
This extension also adds a dashboard to the menu that shows the overall status of the entire project. All alerts from all repositories are loaded and shown in a single dashboard.
17+
![Screenshot of the hub in action](/img/hub.png)
18+
1519
## Pipeline tasks
1620
* Advanced-Security-Review: lets you check the pull request for newly introduced alerts from Dependency Scanning or Code Scanning (configurable). If new alerts are introduced, the task will fail.
1721
> Note:

vss-extension-dev.json

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifestVersion": 1,
33
"id": "GHAzDoWidget-DEV",
4-
"version": "0.2.397",
4+
"version": "0.2.404",
55
"public": false,
66
"name": "Advanced Security dashboard Widgets [DEV]",
77
"description": "[DEV] GitHub Advanced Security for Azure DevOps dashboard widgets",
@@ -221,11 +221,10 @@
221221
"type": "ms.vss-web.hub",
222222
"description": "[DEV] GHAzDO Hub",
223223
"targets": [
224-
"ms.vss-work-web.work-hub-group",
225224
"ms.vss-code-web.code-hub-group"
226225
],
227226
"properties": {
228-
"name": "Advanced Security Dashboard",
227+
"name": "Advanced Security [DEV]",
229228
"uri": "widgets/widgets/hub/hub.html",
230229
"iconName": "Shield",
231230
"order": 99

vss-extension.json

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifestVersion": 1,
33
"id": "GHAzDoWidget",
4-
"version": "0.0.1.14",
4+
"version": "0.0.1.17",
55
"public": true,
66
"name": "Advanced Security dashboard Widgets",
77
"description": "GitHub Advanced Security for Azure DevOps dashboard widgets",
@@ -162,6 +162,20 @@
162162
"uri": "widgets/widgets/chart/configuration_2x2.html"
163163
}
164164
},
165+
{
166+
"id": "GHAzDoWidget.Hub",
167+
"type": "ms.vss-web.hub",
168+
"description": "GHAzDO Hub",
169+
"targets": [
170+
"ms.vss-code-web.code-hub-group"
171+
],
172+
"properties": {
173+
"name": "Advanced Security Dashboard",
174+
"uri": "widgets/widgets/hub/hub.html",
175+
"iconName": "Shield",
176+
"order": 99
177+
}
178+
},
165179
{
166180
"id": "GHAzDoDependencyReviewTask",
167181
"type": "ms.vss-distributed-task.task",

widgets/library.js

+23-13
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ async function storeAlerts(repoId, alertResult) {
187187
}
188188
}
189189

190-
async function getAlertsTrendLines(organization, projectName, repoId) {
190+
async function getAlertsTrendLines(organization, projectName, repoId, daysToGoBack, summaryBucket) {
191191
consoleLog(`getAlertsTrend for organization [${organization}], project [${projectName}], repo [${repoId}]`)
192192
try {
193193
alertResult = null
@@ -203,19 +203,29 @@ async function getAlertsTrendLines(organization, projectName, repoId) {
203203
alertResult = await authenticatedGet(url)
204204
//consoleLog('alertResult: ' + JSON.stringify(alertResult))
205205
}
206-
consoleLog('alertResult count: ' + alertResult.count)
206+
if (alertResult) {
207+
consoleLog('alertResult count: ' + alertResult.count)
208+
}
209+
else {
210+
consoleLog('alertResult is null')
211+
return {
212+
secretAlertsTrend: [],
213+
dependencyAlertsTrend: [],
214+
codeAlertsTrend: []
215+
}
216+
}
207217

208218
// load the Secret alerts and create a trend line over the last 3 weeks
209219
const secretAlerts = alertResult.value.filter(alert => alert.alertType === AlertType.SECRET.name)
210-
const secretAlertsTrend = getAlertsTrendLine(secretAlerts, 'secret')
220+
const secretAlertsTrend = getAlertsTrendLine(secretAlerts, AlertType.SECRET.name, daysToGoBack, summaryBucket)
211221
consoleLog('')
212222
// load the Dependency alerts and create a trend line over the last 3 weeks
213223
const dependencyAlerts = alertResult.value.filter(alert => alert.alertType === AlertType.DEPENDENCY.name)
214-
const dependencyAlertsTrend = getAlertsTrendLine(dependencyAlerts, 'dependency')
224+
const dependencyAlertsTrend = getAlertsTrendLine(dependencyAlerts, AlertType.DEPENDENCY.name, daysToGoBack, summaryBucket)
215225
consoleLog('')
216226
// load the Code alerts and create a trend line over the last 3 weeks
217227
const codeAlerts = alertResult.value.filter(alert => alert.alertType === AlertType.CODE.name)
218-
const codeAlertsTrend = getAlertsTrendLine(codeAlerts, 'code')
228+
const codeAlertsTrend = getAlertsTrendLine(codeAlerts, AlertType.CODE.name, daysToGoBack, summaryBucket)
219229

220230
return {
221231
secretAlertsTrend: secretAlertsTrend,
@@ -248,16 +258,16 @@ function checkAlertActiveOnDate(alert, dateStr) {
248258
return seenClosed;
249259
}
250260

251-
function getAlertsTrendLine(alerts, type) {
261+
function getAlertsTrendLine(alerts, type, daysToGoBack = 21, summaryBucket = 1) {
252262
consoleLog(`getAlertsTrendLine for type ${type}`);
253263

254264
const trendLine = [];
255265
const trendLineSimple = [];
256266
const today = new Date();
257-
const threeWeeksAgo = new Date();
258-
threeWeeksAgo.setDate(today.getDate() - 21);
267+
const startDate = new Date();
268+
startDate.setDate(today.getDate() - daysToGoBack);
259269

260-
for (let d = threeWeeksAgo; d <= today; d.setDate(d.getDate() + 1)) {
270+
for (let d = startDate; d <= today; d.setDate(d.getDate() + summaryBucket)) {
261271
const date = new Date(d);
262272
const dateStr = date.toISOString().split('T')[0];
263273

@@ -275,13 +285,13 @@ function getAlertsTrendLine(alerts, type) {
275285
return trendLineSimple;
276286
}
277287

278-
function getDatePoints() {
288+
function getDatePoints(daysToGoBack = 21, summaryBucket = 1) {
279289
const trendDates = [];
280290
const today = new Date();
281-
const threeWeeksAgo = new Date();
282-
threeWeeksAgo.setDate(today.getDate() - 21);
291+
const startDate = new Date();
292+
startDate.setDate(today.getDate() - daysToGoBack);
283293

284-
for (let d = threeWeeksAgo; d <= today; d.setDate(d.getDate() + 1)) {
294+
for (let d = startDate; d <= today; d.setDate(d.getDate() + summaryBucket)) {
285295
const date = new Date(d);
286296
const dateStr = date.toISOString().split('T')[0];
287297
trendDates.push(dateStr);

widgets/widgets/chart/chart.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
async function createChart($container, chartService, alertTrendLines, widgetSize) {
1+
async function createChart($container, chartService, alertTrendLines, widgetSize, daysToGoBack = 21, summaryBucket = 1) {
22

3-
const datePoints = getDatePoints();
3+
const datePoints = getDatePoints(daysToGoBack, summaryBucket);
44
var chartOptions = {
55
"hostOptions": {
66
"height": "290",
@@ -94,16 +94,16 @@ async function renderPieChart(organization, projectName, repoId, $container, cha
9494
}
9595
}
9696

97-
async function renderTrendLine(organization, projectName, repoId, $container, chartService, widgetSize) {
97+
async function renderTrendLine(organization, projectName, repoId, $container, chartService, widgetSize, daysToGoBack = 21, summaryBucket = 1) {
9898
consoleLog('renderTrendLine');
9999
try {
100100
// get the trend data for alerts first
101-
const alertTrendLines = await getAlertsTrendLines(organization, projectName, repoId)
101+
const alertTrendLines = await getAlertsTrendLines(organization, projectName, repoId, daysToGoBack, summaryBucket)
102102
consoleLog('Dependencies AlertTrend: ' + JSON.stringify(alertTrendLines.dependencyAlertsTrend));
103103
consoleLog('Code scanning AlertTrend: ' + JSON.stringify(alertTrendLines.codeAlertsTrend));
104104
consoleLog('Secrets AlertTrend: ' + JSON.stringify(alertTrendLines.secretAlertsTrend));
105105

106-
createChart($container, chartService, alertTrendLines, widgetSize);
106+
createChart($container, chartService, alertTrendLines, widgetSize, daysToGoBack, summaryBucket);
107107
}
108108
catch (err) {
109109
consoleLog(`Error loading the alerts trend: ${err}`);

widgets/widgets/hub/hub.html

+27-10
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,18 @@
3535
const organization = webContext.account.name
3636
const projectId = project.id
3737
// convert project.name to url encoding
38-
const projectName = project.name.replace(/ /g, "%20").replace(/&/g, "%26")
3938
const chartService = await Services.ChartsService.getService()
4039

41-
await createCharts({chartService, projectName, organization})
40+
await createCharts({chartService, projectName: project.name, organization})
41+
42+
const debugging = document.getElementById('debugInfoCheckbox')
43+
// wait at least 5 seconds before hiding the progress div
44+
setTimeout(() => {
45+
if (!debugging.checked) {
46+
const progressDivContainer = document.getElementById('progressDivContainer')
47+
progressDivContainer.style.display = 'none'
48+
}
49+
}, 5000)
4250
}
4351
consoleLog('VSS.require function')
4452
try {
@@ -49,11 +57,8 @@
4957
const project = webContext.project
5058
const organization = webContext.account.name
5159
const projectId = project.id
52-
// convert project.name to url encoding
53-
const projectName = project.name.replace(/ /g, "%20").replace(/&/g, "%26")
5460

5561
consoleLog('project id: ' + projectId)
56-
consoleLog('project name: ' + projectName)
5762
consoleLog('organization name: ' + organization)
5863

5964
// Get the header element
@@ -71,11 +76,13 @@
7176
codeAlertCount: $(progressDivContainer).find('.codeAlertCount')[0]
7277
}
7378
const projects = await getProjects(VSS, Service, RestClient)
79+
// filter the projects to only the current project
80+
const currentProject = projects.filter(p => p.id === projectId)
7481
consoleLog(`Found [${projects?.length}] projects`)
75-
loadAllAlertsFromAllRepos(VSS, Service, GitWebApi, organization, projects, progressDiv, redrawCharts)
82+
loadAllAlertsFromAllRepos(VSS, Service, GitWebApi, organization, currentProject, progressDiv, redrawCharts)
7683

7784
// create the empty charts
78-
await createCharts({chartService, projectName, organization})
85+
await createCharts({chartService, projectName: project.name, organization})
7986

8087
consoleLog('returning WidgetStatusHelper.Success()')
8188
}
@@ -90,7 +97,11 @@
9097
<div class="widget" id="progressDivContainer">
9198
<div>
9299
<div class="float" style="font-weight:600;font-size:larger;margin-right:7px;">Loading data</div>
93-
<div class="loadingTitle float float-break"></div>
100+
<div class="loadingTitle float margin-right:7px;"></div>
101+
<div class="float float-break" style="margin-right:7px;">
102+
<input type="checkbox" id="debugInfoCheckbox" name="debugInfoCheckbox" value="debugInfoCheckbox" unchecked>
103+
<label for="debugInfoCheckbox">Show debugging</label>
104+
</div>
94105
</div>
95106
<div>
96107
<div id="debugInfo" class="float float-break" date-startTime=""></div>
@@ -123,11 +134,13 @@ <h3>Code</h3>
123134
</div>
124135
</div>
125136

126-
<div class="widget float">
137+
<div class="widget trendlineWidget float float-break">
127138
<h2 class="ghazdoTitle" id="TitleOverallTrend">Overall alert trend</h2>
128139
<div id="ChartContainerOverallTrend"></div>
129140
</div>
130141

142+
<div style="clear: both;"></div>
143+
131144
<div class="widget float">
132145
<h2 class="ghazdoTitle" id="TitleOverallDependencyPie">Overall dependencies alert levels</h2>
133146
<div id="ChartContainerOverallDependencyPie"></div>
@@ -151,12 +164,16 @@ <h2 class="ghazdoTitle" id="TitleOverallCodeScanningPie">Overall code scanning a
151164
padding: 5px 5px 5px 5px;
152165
}
153166

167+
.trendlineWidget {
168+
width: 650px;
169+
}
170+
154171
.region-headerBreadcrumb {
155172
display: none;
156173
}
157174

158175
#progressDivContainer {
159-
width: 435px;
176+
width: 440px;
160177
}
161178

162179
.float {

widgets/widgets/hub/hub.js

+10-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ async function createCharts({chartService, projectName, organization}) {
66
alertType: 1,
77
repo: "All repos",
88
repoId: "-1",
9+
widgetWidth: 4,
910
containerName: "ChartContainerOverallTrend",
1011
titleName: "TitleOverallTrend"
1112
}
@@ -79,12 +80,16 @@ async function createHubChart({chartService, organization, projectName, data}) {
7980
columnSpan: 2
8081
}
8182

83+
if (data.widgetWidth) {
84+
chartSize.columnSpan = data.widgetWidth;
85+
}
86+
8287
switch (chartType) {
8388
case "2":
8489
try {
8590
const alertType = GetAlertTypeFromValue(alertTypeConfig)
8691
if (titleElement) {
87-
titleElement.textContent = `${alertType.display} Alerts by Severity`
92+
titleElement.textContent = `${alertType.display} alerts by severity`
8893
}
8994
await renderPieChart(organization, projectName, repoId, containerElement, chartService, alertType, chartSize)
9095
}
@@ -95,9 +100,11 @@ async function createHubChart({chartService, organization, projectName, data}) {
95100
default:
96101
try {
97102
if (titleElement) {
98-
titleElement.textContent = `Advanced Security Alerts Trend`
103+
titleElement.textContent = `Advanced Security alerts trend for ${projectName}`
99104
}
100-
await renderTrendLine(organization, projectName, repoId, containerElement, chartService, chartSize)
105+
const daysToGoBack = 26 * 7 // look back half a year in chunks that count up to today
106+
const summaryBucket = 7
107+
await renderTrendLine(organization, projectName, repoId, containerElement, chartService, chartSize, daysToGoBack, summaryBucket)
101108
}
102109
catch (err) {
103110
consoleLog(`Error loading the alerts trend: ${err}`)

0 commit comments

Comments
 (0)