UNPKG

create-adobug-azure-helper

Version:

A helper library for Azure DevOps automation functions (bug creation, test result update, step logging, etc.)

150 lines (147 loc) 6.93 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CreateBugADOHelper = void 0; const axios_retry_1 = __importDefault(require("axios-retry")); const crypto_1 = __importDefault(require("crypto")); const path_1 = __importDefault(require("path")); const fs_1 = __importDefault(require("fs")); const axios_1 = __importDefault(require("axios")); //import { extractReproSteps } from './BugUtilities/extractReproSteps'; //import { getMostRecentFile } from './BugUtilities/getMostRecentFile'; const moduleUserMapping_1 = require("./moduleUserMapping"); class CreateBugADOHelper { //private httpsAgent: https.Agent; constructor(azureUrl, adoProjectName, initialMapping = {}) { this.azureUrl = azureUrl; this.adoProjectName = adoProjectName; this.moduleUserMapping = new moduleUserMapping_1.ModuleUserMapping(initialMapping); //this.httpsAgent = new https.Agent({ keepAlive: true }); (0, axios_retry_1.default)(axios_1.default, { retries: 3 }); // Retry up to 3 times } decryptPAT(encryptedData, iv, key) { const algorithm = 'aes-256-cbc'; const decipher = crypto_1.default.createDecipheriv(algorithm, Buffer.from(key, 'hex'), Buffer.from(iv, 'hex')); let decrypted = decipher.update(Buffer.from(encryptedData, 'hex')); decrypted = Buffer.concat([decrypted, decipher.final()]); return decrypted.toString(); } async createBugInADO(moduleName, bugTitle, bugDescription, steps, failedStep, attachmentDirPath, userDetails) { const decryptedPAT = this.decryptPAT(userDetails.encryptedData, userDetails.iv, userDetails.key); const auth = Buffer.from(`:${decryptedPAT}`).toString('base64'); const assignedTo = this.moduleUserMapping.getUserForModule(moduleName); if (!assignedTo) { throw new Error(`No user found for module: ${moduleName}`); } let attachmentUrls = []; if (attachmentDirPath) { const resolvedDirPath = path_1.default.resolve(attachmentDirPath); console.log(`Scanning directory for attachments: ${resolvedDirPath}`); if (fs_1.default.existsSync(resolvedDirPath)) { const files = fs_1.default.readdirSync(resolvedDirPath); if (files.length > 0) { for (const file of files) { const filePath = path_1.default.join(resolvedDirPath, file); try { const attachmentUrl = await this.uploadAttachment(auth, filePath); attachmentUrls.push(attachmentUrl); } catch (uploadError) { console.error(`Failed to upload attachment ${file}:`, uploadError); } } } else { console.log(`No files found in the directory: ${resolvedDirPath}`); } } else { console.error(`Directory not found: ${resolvedDirPath}`); } } const formattedReproSteps = ` ### Steps to Reproduce: ${steps .map((step, index) => { if (step.step === failedStep) { return null; // Exclude the failed step from the "Passed" list } return `**Step ${index + 1}:** - ${step.status}`; }) .filter(Boolean) .join('\n')} --- ### Failed Step: **Step ${steps.findIndex(step => step.step === failedStep) + 1}: ${failedStep}** `; const createBugUrl = `${this.azureUrl}/${this.adoProjectName}/_apis/wit/workitems/$Bug?api-version=6.0`; const bugPayload = [ { op: 'add', path: '/fields/System.Title', value: bugTitle }, { op: 'add', path: '/fields/Microsoft.VSTS.TCM.ReproSteps', value: formattedReproSteps }, { op: 'add', path: '/fields/System.Description', value: bugDescription }, { op: 'add', path: '/fields/System.AssignedTo', value: assignedTo }, { op: 'add', path: '/fields/System.Tags', value: 'Automation' } ]; for (const attachmentUrl of attachmentUrls) { bugPayload.push({ op: 'add', path: '/relations/-', value: JSON.stringify({ rel: 'AttachedFile', url: attachmentUrl, attributes: { comment: 'Attached file for debugging' }, }), }); } try { const createBugResponse = await axios_1.default.post(createBugUrl, bugPayload, { headers: { 'Content-Type': 'application/json-patch+json', Authorization: `Basic ${auth}`, }, timeout: 60000, }); if (!createBugResponse || !createBugResponse.data || typeof createBugResponse.data.id !== 'number') { throw new Error('Bug creation response is invalid or missing required fields.'); } const bugId = createBugResponse.data.id; console.log(`Bug created successfully with ID: ${bugId}`); } catch (error) { console.error('Error creating bug in Azure DevOps:', error); throw new Error('Failed to create bug in Azure DevOps.'); } } async uploadAttachment(auth, filePath) { const fileName = path_1.default.basename(filePath); const fileContent = fs_1.default.readFileSync(filePath); const uploadUrl = `${this.azureUrl}/${this.adoProjectName}/_apis/wit/attachments?fileName=${fileName}&api-version=6.0`; try { const response = await axios_1.default.post(uploadUrl, fileContent, { headers: { 'Content-Type': 'application/octet-stream', Authorization: `Basic ${auth}`, }, //httpsAgent: this.httpsAgent, }); if (response && response.data && typeof response.data === 'object' && 'url' in response.data) { if (typeof response.data.url === 'string') { return response.data.url; } else { throw new Error('Attachment URL is not a string.'); } } else { throw new Error('Unexpected response format.'); } } catch (error) { console.error('Error uploading attachment:', error); throw new Error('Failed to upload attachment.'); } } } exports.CreateBugADOHelper = CreateBugADOHelper;