Skip to content

Commit fa0f8ba

Browse files
Merge pull request #26 from microsoft/dev/chrisnielsen_recreateDebugDrop
Dev/chrisnielsen recreate debug drop
2 parents b936959 + 8f710eb commit fa0f8ba

File tree

3 files changed

+144
-3
lines changed

3 files changed

+144
-3
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@microsoft/security-devops-azdevops-task-lib",
3-
"version": "1.10.1",
3+
"version": "1.11.0",
44
"description": "Microsoft Security DevOps for Azure DevOps task library.",
55
"author": "Microsoft Corporation",
66
"license": "MIT",

src/msdo-client.ts

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import * as tl from 'azure-pipelines-task-lib/task';
55
import { IExecOptions } from "azure-pipelines-task-lib/toolrunner";
66
import * as common from './msdo-common';
77
import * as installer from './msdo-installer';
8+
import AdmZip = require('adm-zip');
89

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

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

96+
const gdnTaskLibFolder = path.resolve(__dirname);
97+
tl.debug(`gdnTaskLibFolder = ${gdnTaskLibFolder}`);
98+
99+
const nodeModulesFolder = path.dirname(path.dirname(gdnTaskLibFolder));
100+
tl.debug(`nodeModulesFolder = ${nodeModulesFolder}`);
101+
102+
const taskFolder = path.dirname(nodeModulesFolder);
103+
tl.debug(`taskFolder = ${taskFolder}`);
104+
105+
const debugFolder = path.join(taskFolder, 'debug');
106+
tl.debug(`debugFolder = ${debugFolder}`);
107+
94108
try {
95109

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

141155
tool.arg('--telemetry-environment');
142156
tool.arg(telemetryEnvironment);
157+
158+
// Include the debug drop option on the command line if applicable.
159+
tl.debug(`GdnDebugDrop = ${debugDrop}`);
160+
if (debugDrop)
161+
{
162+
const dropPathValue = path.join(taskFolder, 'debug');
163+
tool.arg('--debug-drop').arg('--debug-drop-path').arg(dropPathValue);
164+
const dropPathName = `GDN_DEBUGDROPPATH`;
165+
166+
tl.debug(`Debug Drop enabled. ${dropPathName}: ${dropPathValue}`);
167+
process.env[dropPathName] = dropPathValue;
168+
}
143169
} catch (error) {
144170
console.error('Exception occurred while initializing MSDO:');
145171
tl.setResult(tl.TaskResult.Failed, error);
@@ -154,6 +180,9 @@ export async function run(inputArgs: string[], successfulExitCodes: number[] = n
154180

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

183+
// Ensure debug folder starts clean
184+
cleanupDirectory(debugFolder);
185+
157186
let exitCode = await tool.exec(options);
158187

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

196+
// Package up debug drop if applicable.
197+
let debugStagingDir = '';
198+
tl.debug(`GdnDebugDrop = ${debugDrop}`);
199+
if (debugDrop) {
200+
if (fs.existsSync(debugFolder)) {
201+
tl.debug("Creating debug drop archive...");
202+
let zippedOutput = getZippedFolder(debugFolder);
203+
204+
const taskFilePath = path.join(taskFolder, `task.json`);
205+
tl.debug(`taskFilePath = ${taskFilePath}`);
206+
const taskFile = require(taskFilePath);
207+
const taskName = taskFile.name.toUpperCase();
208+
209+
const instanceDirectory = getInstanceDirectory();
210+
debugStagingDir = path.join(instanceDirectory, '.gdn', 'debugdrop');
211+
if (!fs.existsSync(debugStagingDir)) {
212+
tl.debug(`Creating missing folder: ${debugStagingDir}`)
213+
fs.mkdirSync(debugStagingDir)
214+
}
215+
216+
let debugDropArtifact = path.join(debugStagingDir, `${taskName}_debug.zip`);
217+
let dupeCount = 0;
218+
while (fs.existsSync(debugDropArtifact)) {
219+
dupeCount += 1;
220+
debugDropArtifact = path.join(debugStagingDir, `${taskName}_${dupeCount}_debug.zip`)
221+
}
222+
fs.copyFileSync(zippedOutput, debugDropArtifact);
223+
tl.debug(`Finished creating: ${debugDropArtifact}`);
224+
tl.debug(`Cleaning up: ${path.join(taskFolder, 'debug')}`);
225+
cleanupDirectory(path.join(taskFolder, 'debug'));
226+
tl.debug(`Successfully cleaned up debug dump.`);
227+
}
228+
}
229+
167230
if (publish && fs.existsSync(sarifFile)) {
168231
if (common.isNullOrWhiteSpace(publishArtifactName)) {
169232
publishArtifactName = 'CodeAnalysisLogs';
@@ -172,10 +235,88 @@ export async function run(inputArgs: string[], successfulExitCodes: number[] = n
172235
console.log(`##vso[artifact.upload artifactname=${publishArtifactName}]${sarifFile}`);
173236
}
174237

238+
if (publish && fs.existsSync(debugStagingDir)) {
239+
console.log(`##vso[artifact.upload artifactname=DebugDrop]${debugStagingDir}`);
240+
}
241+
175242
if (!success) {
176243
throw `MSDO CLI exited with an error exit code: ${exitCode}`;
177244
}
178245
} catch (error) {
179246
tl.setResult(tl.TaskResult.Failed, error);
180247
}
248+
}
249+
250+
function getInstanceDirectory(): string {
251+
let hostType = process.env.SYSTEM_HOSTTYPE;
252+
if (hostType) {
253+
hostType = hostType.toUpperCase();
254+
}
255+
256+
if (hostType == "RELEASE") {
257+
return process.env.AGENT_RELEASEDIRECTORY;
258+
} else { // hostType == "BUILD" or default
259+
return process.env.BUILD_SOURCESDIRECTORY;
260+
}
261+
}
262+
263+
function getZippedFolder(dir): string {
264+
tl.debug(`Zipping up folder: ${dir}`)
265+
let allPaths = getFilePathsRecursively(dir);
266+
const zip = new AdmZip();
267+
for (let filePath of allPaths) {
268+
tl.debug(`Adding file to archive: ${filePath}`);
269+
zip.addLocalFile(filePath);
270+
}
271+
272+
let destPath = `${dir}.zip`;
273+
tl.debug(`Writing to file: ${destPath}`)
274+
zip.writeZip(destPath);
275+
if (fs.existsSync(destPath)) {
276+
tl.debug(`Successfully wrote file: ${destPath}`)
277+
} else {
278+
tl.debug(`Something went wrong! File does not exist: ${destPath}`)
279+
}
280+
return destPath;
281+
}
282+
283+
// Returns a flat array of absolute paths to all files contained in the dir
284+
function getFilePathsRecursively(dir) {
285+
tl.debug(`Searching for files under dir: ${dir}`)
286+
var files = [];
287+
let fileList = fs.readdirSync(dir);
288+
var remaining = fileList.length;
289+
if (!remaining) return files;
290+
291+
for (let file of fileList) {
292+
file = path.resolve(dir, file);
293+
let stat = fs.statSync(file);
294+
if (stat && stat.isDirectory()) {
295+
let f = getFilePathsRecursively(file);
296+
files = files.concat(f);
297+
} else {
298+
files.push(file);
299+
}
300+
if (!--remaining) {
301+
return files;
302+
}
303+
}
304+
}
305+
306+
function cleanupDirectory(dir) {
307+
if (!fs.existsSync(dir)) return;
308+
309+
let items = fs.readdirSync(dir);
310+
311+
for (let item of items) {
312+
item = path.resolve(dir, item)
313+
let stat = fs.statSync(item);
314+
if (stat && stat.isDirectory()) {
315+
cleanupDirectory(item)
316+
} else {
317+
fs.unlinkSync(item);
318+
}
319+
}
320+
321+
fs.rmdirSync(dir);
181322
}

0 commit comments

Comments
 (0)