Skip to content

Commit

Permalink
Temp status
Browse files Browse the repository at this point in the history
  • Loading branch information
rajbos committed Dec 6, 2023
1 parent f259e01 commit 3c49498
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 35 deletions.
2 changes: 1 addition & 1 deletion vss-extension-dev.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"manifestVersion": 1,
"id": "GHAzDoWidget-DEV",
"version": "0.2.319",
"version": "0.2.330",
"public": false,
"name": "Advanced Security dashboard Widgets [DEV]",
"description": "[DEV] GitHub Advanced Security for Azure DevOps dashboard widgets",
Expand Down
163 changes: 146 additions & 17 deletions widgets/library.js
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,10 @@ async function getProjects(VSS, Service, CoreRestClient) {
id: project.id
}
});

// sort the projects based on the name
projects.sort((a, b) => (a.name > b.name) ? 1 : -1);

//consoleLog(`Converted projects to: ${JSON.stringify(projects)}`);

// save the repos to the document store for next time
Expand All @@ -378,6 +382,128 @@ async function getProjects(VSS, Service, CoreRestClient) {
}
}

const batchTimeOut = 1000
const repoBatchSize = 100
async function loadAllAlertsFromAllRepos(VSS, Service, GitWebApi, organization, projects, progressDiv) {
consoleLog(`Loading all alerts from all repos for organization [${organization}] for [${projects.length}] projects`);
// prepare the list of project calls to make
for (let index in projects) {
const project = projects[index];
//$queryinfocontainer.append(`<li id="${project.id}">${project.name}</li>\n`);

// place the repo definition in the array to process later
getProjectCalls.push({organization, project});
}
progressDiv.projectCount.textContent = `${projects.length}`

// wait for all the project promises to complete
console.log(`Waiting for [${getProjectCalls.length}] calls to complete`);
let position = 0;
let waiting = 0;
let alertBatchSize = repoBatchSize; // size of the calls to run at once
activeCalls = 0; // reset the active calls counter
let i = 0
while (i < getProjectCalls.length) {
if (activeCalls < alertBatchSize) {
let work = getProjectCalls[i];

// do the work, don't wait for it to complete to speed things up
getRepos(VSS, Service, GitWebApi, work.project.name, false).then(repos => {
activeCalls--;
showRepoInfo(repos, work.project, work.organization, progressDiv, activeCalls)
}).
catch(error => {
console.error(`Error handling get repos for ${work.project.name}: ${error}`);
activeCalls--;
})

activeCalls++;
i++
}
else {
//showCallStatus();
// wait for the next batch to complete
await new Promise(resolve => setTimeout(resolve, batchTimeOut));
}
}

while (activeCalls > 0) {
// wait for the last batch to complete
console.log(`Waiting for the last [${activeCalls}] project calls to complete`);
await new Promise(resolve => setTimeout(resolve, 500));
}
console.log(`All project calls completed`);

// loop over the alertCall array and load the alerts for each repo
position = 0;
waiting = 0;
alertBatchSize = 50; // size of the calls to run at once
activeCalls = 0;
i = 0
const repos = null // required param, but not used
while (i < getAlertCalls.length) {
if (activeCalls < alertBatchSize) {
let work = getAlertCalls[i];
// do the work
getAlerts(work.organization, work.project.name, work.repo.id, repos, work.project, work.repo).then(repoAlerts => {
activeCalls--;
showAlertInfo(work.organization, work.project, work.repo, repoAlerts, progressDiv, activeCalls)
//todo: store the overall results: results.push(repoAlerts);
}).
catch(error => {
console.error(`Error handling get alerts for ${work.repo.name}: ${error}`);
activeCalls--;
})

activeCalls++;
i++
}
else
{
showCallStatus();
// wait some time before starting the next batch
await new Promise(resolve => setTimeout(resolve, 500));
}
}
}
async function showRepoInfo(repos, project, organization, progressDiv, activeCalls) {
consoleLog(`Found [${repos?.length}] repos for project [${project.name}] to load alerts for`);

var currentValue = parseInt(progressDiv.repoCount.textContent);
progressDiv.repoCount.textContent = currentValue + repos?.length

// load the work to load the alerts for all repos
for (let repoIndex in repos) {
const repo = repos[repoIndex];
// only load the alerts if the repo has a size, otherwise it is still an empty repo
if (repo.size > 0) {
// add work definition to array
getAlertCalls.push({organization, project, repo});
}
}
}

function showAlertInfo(organization, project, repo, repoAlerts, progressDiv, activeCalls) {
if (repoAlerts && repoAlerts.values) {
//consoleLog(`Found [${JSON.stringify(repoAlerts)}] dependency alerts for repo [${repo.name}]`)

// show the alert counts
// todo: store the current count and skip the parsing
var currentValue = parseInt(progressDiv.dependencyAlertCount.textContent)
progressDiv.dependencyAlertCount.textContent = currentValue + repoAlerts.values.dependencyAlerts

var currentValue = parseInt(progressDiv.secretAlertCount.textContent)
progressDiv.secretAlertCount.textContent = currentValue + repoAlerts.values.secretAlerts

var currentValue = parseInt(progressDiv.codeAlertCount.textContent)
progressDiv.codeAlertCount.textContent = currentValue + repoAlerts.values.codeAlerts

// keep track of global state:
// endDateTime.text('End: ' + (new Date()).toISOString())
// showCallStatus()
}
}

async function getRepos(VSS, Service, GitWebApi, projectName, useCache = true) {

//consoleLog(`inside getRepos`);
Expand Down Expand Up @@ -465,25 +591,28 @@ async function getAlertSeverityCounts(organization, projectName, repoId, alertTy
url = `https://advsec.dev.azure.com/${organization}/${projectName}/_apis/${areaName}/repositories/${repoId}/alerts?top=5000&criteria.onlyDefaultBranchAlerts=true&criteria.alertType=${alertType.value}&criteria.states=1&api-version=${apiVersion}`;
//consoleLog(`Calling url: [${url}]`);
const alertResult = await authenticatedGet(url);
//consoleLog('alertResult: ' + JSON.stringify(alertResult));
consoleLog(`total alertResult count: ${alertResult.count} for alertType [${alertType.name}]`);

// group the alerts based on the severity
try {
consoleLog(`severityClasses.length: [${severityClasses.length}]`);

for (let index in severityClasses) {
let severityClass = severityClasses[index];
const severityAlertCount = alertResult.value.filter(alert => alert.severity === severityClass.severity);
consoleLog(`severityClass [${severityClass.severity}] has [${severityAlertCount.length}] alerts`);
severityClass.count = severityAlertCount.length;
};
}
catch (err) {
consoleLog('error in grouping the alerts: ' + err);
}
if (alertResult && alertResult.count) {
//consoleLog('alertResult: ' + JSON.stringify(alertResult));
consoleLog(`total alertResult count: ${alertResult.count} for alertType [${alertType.name}]`);

// group the alerts based on the severity
try {
consoleLog(`severityClasses.length: [${severityClasses.length}]`);

for (let index in severityClasses) {
let severityClass = severityClasses[index];
const severityAlertCount = alertResult.value.filter(alert => alert.severity === severityClass.severity);
consoleLog(`severityClass [${severityClass.severity}] has [${severityAlertCount.length}] alerts`);
severityClass.count = severityAlertCount.length;
};
}
catch (err) {
consoleLog('error in grouping the alerts: ' + err);
}

consoleLog('severityClasses summarized: ' + JSON.stringify(severityClasses));
consoleLog('severityClasses summarized: ' + JSON.stringify(severityClasses));
}
}
catch (err) {
consoleLog('error in calling the advec api: ' + err);
Expand Down
58 changes: 51 additions & 7 deletions widgets/widgets/hub/hub.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@
});

VSS.require([
"VSS/Service",
"TFS/Dashboards/WidgetHelpers",
"Charts/Services",
"VSS/Context",
"VSS/Authentication/Services"
//"VSS/Authentication/Services",
"TFS/VersionControl/GitRestClient",
"TFS/Core/RestClient"
],

// top level function
async function (WidgetHelpers, Services, context) {
async function (Service, WidgetHelpers, Services, context, GitWebApi, RestClient) {
consoleLog('VSS.require function');
try {
consoleLog('VSS.register Hub function');
Expand All @@ -39,10 +42,22 @@
consoleLog('project name: ' + projectName);
consoleLog('organization name: ' + organization);

const titleElement = $('h2.ghazdoTitle')[0];
const containerElement = $('#Chart-Container')[0];
// load all project data
const progressDivContainer = $('#LoadingInfoContainer')[0];
const progressDiv = {
projectCount: $(progressDivContainer).find('.projectCount')[0],
repoCount: $(progressDivContainer).find('.repoCount')[0],
dependencyAlertCount: $(progressDivContainer).find('.dependencyAlertCount')[0],
secretAlertCount: $(progressDivContainer).find('.secretAlertCount')[0],
codeAlertCount: $(progressDivContainer).find('.codeAlertCount')[0]
}
const projects = await getProjects(VSS, Service, RestClient);
consoleLog(`Found [${projects?.length}] projects`);
loadAllAlertsFromAllRepos(VSS, Service, GitWebApi, organization, projects, progressDiv)

// create the charts
const titleElement = $('h2.ghazdoTitle')[0];
const containerElement = $('#Chart-Container')[0];
await createCharts({chartService, containerElement, titleElement, projectName, organization});

consoleLog('returning WidgetStatusHelper.Success()');
Expand All @@ -55,9 +70,34 @@
);
</script>

<div class="widget">
<h2 class="loadingTitle">Loading information div</h2>
<div id="LoadingInfoContainer"></div>
<div class="widget" id="progressDivContainer">
<h2 class="loadingTitle">Loading information</h2>
<div id="LoadingInfoContainer" class="column-container">
<div class="column">
<h3>Projects</h3>
<p class="alertValue projectCount">0</p>
</div>

<div class="column">
<h3>Repos</h3>
<p class="alertValue repoCount">0</p>
</div>

<div class="column">
<h3>Dependencies</h3>
<p class="alertValue dependencyAlertCount">0</p>
</div>

<div class="column">
<h3>Secrets</h3>
<p class="alertValue secretAlertCount">0</p>
</div>

<div class="column">
<h3>Code</h3>
<p class="alertValue codeAlertCount">0</p>
</div>
</div>
</div>

<div class="widget">
Expand All @@ -77,6 +117,10 @@ <h2 class="ghazdoTitle">GHAzDo Hub test from Rob Bos's widget</h2>
.region-headerBreadcrumb {
display: none;
}

#progressDivContainer {
width: 435px;
}
</style>
</body>
</html>
4 changes: 2 additions & 2 deletions widgets/widgets/hub/hub.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ async function createHubChart({chartService, containerElement, titleElement, org
}
break
}
consoleLog('rendered chart')
consoleLog('Rendered chart')
}
else {
consoleLog('configuration is needed first, opening with empty values')
consoleLog('Configuration is needed first, opening with empty values')
// set the tile to indicate config is needed
titleElement.textContent = `Configure the widget to get Advanced Security alerts trend information`
}
Expand Down
7 changes: 0 additions & 7 deletions widgets/widgets/testing_widget/testing.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
// declare global variables
///var callCounter = 0;
</script>

<script src="../../../lib/VSS.SDK.min.js"></script>
<script src="../../library.js"></script>
<script src="../widget_1x1/widget_1x1.js"></script>
Expand Down Expand Up @@ -247,8 +242,6 @@

const projects = await getProjects(VSS, Service, RestClient);
consoleLog(`Found [${projects?.length}] projects`);
// sort the projects based on the name
projects.sort((a, b) => (a.name > b.name) ? 1 : -1);

showProjectInfo(VSS, Service, GitWebApi, organization, projects)
}
Expand Down
8 changes: 7 additions & 1 deletion z-status.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,10 @@ In this branch was added:
- write the loop to go over ALL repos in the org (might be already be available in another branch)


Do check the versions of the widget before pushing!
Do check the versions of the widget before pushing!


WIP:
Load all alerts in the hub and show them.
Currently the continue after the project calls does not go into loading the alerts,
for org xpirit, seems to work in raj-bos

0 comments on commit 3c49498

Please sign in to comment.