Skip to content

Dev/chrisnielsen recreate debug drop #26

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@microsoft/security-devops-azdevops-task-lib",
"version": "1.10.1",
"version": "1.11.0",
"description": "Microsoft Security DevOps for Azure DevOps task library.",
"author": "Microsoft Corporation",
"license": "MIT",
Expand Down
141 changes: 141 additions & 0 deletions src/msdo-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as tl from 'azure-pipelines-task-lib/task';
import { IExecOptions } from "azure-pipelines-task-lib/toolrunner";
import * as common from './msdo-common';
import * as installer from './msdo-installer';
import AdmZip = require('adm-zip');

/**
* The default version of Guardian to install if no version is specified.
Expand Down Expand Up @@ -87,10 +88,23 @@ async function init() {
*/
export async function run(inputArgs: string[], successfulExitCodes: number[] = null, publish: boolean = true, publishArtifactName: string = null, telemetryEnvironment: string = 'azdevops'): Promise<void> {
let tool = null;
let debugDrop = common.parseBool(process.env.GDN_DEBUG_DROP);

let sarifFile: string = path.join(process.env.BUILD_STAGINGDIRECTORY, '.gdn', 'msdo.sarif');
tl.debug(`sarifFile = ${sarifFile}`);

const gdnTaskLibFolder = path.resolve(__dirname);
tl.debug(`gdnTaskLibFolder = ${gdnTaskLibFolder}`);

const nodeModulesFolder = path.dirname(path.dirname(gdnTaskLibFolder));
tl.debug(`nodeModulesFolder = ${nodeModulesFolder}`);

const taskFolder = path.dirname(nodeModulesFolder);
tl.debug(`taskFolder = ${taskFolder}`);

const debugFolder = path.join(taskFolder, 'debug');
tl.debug(`debugFolder = ${debugFolder}`);

try {

if (successfulExitCodes == null) {
Expand Down Expand Up @@ -140,6 +154,18 @@ export async function run(inputArgs: string[], successfulExitCodes: number[] = n

tool.arg('--telemetry-environment');
tool.arg(telemetryEnvironment);

// Include the debug drop option on the command line if applicable.
tl.debug(`GdnDebugDrop = ${debugDrop}`);
if (debugDrop)
{
const dropPathValue = path.join(taskFolder, 'debug');
tool.arg('--debug-drop').arg('--debug-drop-path').arg(dropPathValue);
const dropPathName = `GDN_DEBUGDROPPATH`;

tl.debug(`Debug Drop enabled. ${dropPathName}: ${dropPathValue}`);
process.env[dropPathName] = dropPathValue;
}
} catch (error) {
console.error('Exception occurred while initializing MSDO:');
tl.setResult(tl.TaskResult.Failed, error);
Expand All @@ -154,6 +180,9 @@ export async function run(inputArgs: string[], successfulExitCodes: number[] = n

tl.debug('Running Microsoft Security DevOps...');

// Ensure debug folder starts clean
cleanupDirectory(debugFolder);

let exitCode = await tool.exec(options);

let success = false;
Expand All @@ -164,6 +193,40 @@ export async function run(inputArgs: string[], successfulExitCodes: number[] = n
}
}

// Package up debug drop if applicable.
let debugStagingDir = '';
tl.debug(`GdnDebugDrop = ${debugDrop}`);
if (debugDrop) {
if (fs.existsSync(debugFolder)) {
tl.debug("Creating debug drop archive...");
let zippedOutput = getZippedFolder(debugFolder);

const taskFilePath = path.join(taskFolder, `task.json`);
tl.debug(`taskFilePath = ${taskFilePath}`);
const taskFile = require(taskFilePath);
const taskName = taskFile.name.toUpperCase();

const instanceDirectory = getInstanceDirectory();
debugStagingDir = path.join(instanceDirectory, '.gdn', 'debugdrop');
if (!fs.existsSync(debugStagingDir)) {
tl.debug(`Creating missing folder: ${debugStagingDir}`)
fs.mkdirSync(debugStagingDir)
}

let debugDropArtifact = path.join(debugStagingDir, `${taskName}_debug.zip`);
let dupeCount = 0;
while (fs.existsSync(debugDropArtifact)) {
dupeCount += 1;
debugDropArtifact = path.join(debugStagingDir, `${taskName}_${dupeCount}_debug.zip`)
}
fs.copyFileSync(zippedOutput, debugDropArtifact);
tl.debug(`Finished creating: ${debugDropArtifact}`);
tl.debug(`Cleaning up: ${path.join(taskFolder, 'debug')}`);
cleanupDirectory(path.join(taskFolder, 'debug'));
tl.debug(`Successfully cleaned up debug dump.`);
}
}

if (publish && fs.existsSync(sarifFile)) {
if (common.isNullOrWhiteSpace(publishArtifactName)) {
publishArtifactName = 'CodeAnalysisLogs';
Expand All @@ -172,10 +235,88 @@ export async function run(inputArgs: string[], successfulExitCodes: number[] = n
console.log(`##vso[artifact.upload artifactname=${publishArtifactName}]${sarifFile}`);
}

if (publish && fs.existsSync(debugStagingDir)) {
console.log(`##vso[artifact.upload artifactname=DebugDrop]${debugStagingDir}`);
}

if (!success) {
throw `MSDO CLI exited with an error exit code: ${exitCode}`;
}
} catch (error) {
tl.setResult(tl.TaskResult.Failed, error);
}
}

function getInstanceDirectory(): string {
let hostType = process.env.SYSTEM_HOSTTYPE;
if (hostType) {
hostType = hostType.toUpperCase();
}

if (hostType == "RELEASE") {
return process.env.AGENT_RELEASEDIRECTORY;
} else { // hostType == "BUILD" or default
return process.env.BUILD_SOURCESDIRECTORY;
}
}

function getZippedFolder(dir): string {
tl.debug(`Zipping up folder: ${dir}`)
let allPaths = getFilePathsRecursively(dir);
const zip = new AdmZip();
for (let filePath of allPaths) {
tl.debug(`Adding file to archive: ${filePath}`);
zip.addLocalFile(filePath);
}

let destPath = `${dir}.zip`;
tl.debug(`Writing to file: ${destPath}`)
zip.writeZip(destPath);
if (fs.existsSync(destPath)) {
tl.debug(`Successfully wrote file: ${destPath}`)
} else {
tl.debug(`Something went wrong! File does not exist: ${destPath}`)
}
return destPath;
}

// Returns a flat array of absolute paths to all files contained in the dir
function getFilePathsRecursively(dir) {
tl.debug(`Searching for files under dir: ${dir}`)
var files = [];
let fileList = fs.readdirSync(dir);
var remaining = fileList.length;
if (!remaining) return files;

for (let file of fileList) {
file = path.resolve(dir, file);
let stat = fs.statSync(file);
if (stat && stat.isDirectory()) {
let f = getFilePathsRecursively(file);
files = files.concat(f);
} else {
files.push(file);
}
if (!--remaining) {
return files;
}
}
}

function cleanupDirectory(dir) {
if (!fs.existsSync(dir)) return;

let items = fs.readdirSync(dir);

for (let item of items) {
item = path.resolve(dir, item)
let stat = fs.statSync(item);
if (stat && stat.isDirectory()) {
cleanupDirectory(item)
} else {
fs.unlinkSync(item);
}
}

fs.rmdirSync(dir);
}
Loading