diff --git a/src/format-check/scripts/format-check.js b/src/format-check/scripts/format-check.js deleted file mode 100644 index ec23b83..0000000 --- a/src/format-check/scripts/format-check.js +++ /dev/null @@ -1,493 +0,0 @@ -"use strict"; -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); -}; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); - return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.runFormatCheck = runFormatCheck; -exports.getChangedFilesInPR = getChangedFilesInPR; -exports.updatePullRequestThreads = updatePullRequestThreads; -exports.markResolvedThreadsAsClosed = markResolvedThreadsAsClosed; -exports.getStatusDescription = getStatusDescription; -exports.setPullRequestStatusAndDetermineShouldFailTask = setPullRequestStatusAndDetermineShouldFailTask; -var gi = __importStar(require("azure-devops-node-api/interfaces/GitInterfaces")); -var pull_request_file_change_1 = require("./types/pull-request-file-change"); -var pull_request_service_1 = require("./services/pull-request-service"); -var format_check_runner_1 = require("./services/format-check-runner"); -var path_normalizer_1 = require("./utils/path-normalizer"); -var commentPreamble = '[DotNetFormatTask][Automated]'; -/** - * The `runFormatCheck` is an asynchronous function that performs a formatting check on certain code files and updates pull request status accordingly. - * - * The function follows these main steps: - * 1. Initializes and starts a format check runner with appropriate file paths provided via Settings. - * 2. Generates annotated reports for the files checked. - * 3. If the scope is set to Pull Request, it retrieves the list of files involved in the Pull Request and updates the reports accordingly. - * 4. Updates the Pull Request comment threads based on the resulting check report. - * 5. Sets the final Pull Request status based on the check outcome and determines if the task should fail. - * - * @async - * @function runFormatCheck - * @param {Settings} settings - Settings object containing parameters needed for the format check runner and Pull Request Service. - * @returns {Promise} - Promise resolving to a boolean indicating if the task should fail due to formatting errors. - */ -function runFormatCheck(settings) { - return __awaiter(this, void 0, void 0, function () { - var pullRequestService, runner, reports, annotatedReports, changedInPR_1; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, (0, pull_request_service_1.getPullRequestService)(settings)]; - case 1: - pullRequestService = _a.sent(); - if (!settings.Parameters.statusCheck) return [3 /*break*/, 3]; - return [4 /*yield*/, pullRequestService.updatePullRequestStatus(gi.GitStatusState.Pending, getStatusDescription)]; - case 2: - _a.sent(); - _a.label = 3; - case 3: - runner = new format_check_runner_1.FormatCheckRunner(settings.Parameters.solutionPath, settings.Parameters.includePath, settings.Parameters.excludePath); - return [4 /*yield*/, runner.runFormatCheck()]; - case 4: - reports = _a.sent(); - annotatedReports = reports.map(function (r) { - return __assign(__assign({}, r), { FilePath: new path_normalizer_1.PathNormalizer(settings).normalizeFilePath(r.FilePath), commitId: '', changeType: gi.VersionControlChangeType.None }); - }); - if (!settings.Parameters.scopeToPullRequest) return [3 /*break*/, 6]; - console.log("Scoping issues to files part of the Pull Request."); - return [4 /*yield*/, getChangedFilesInPR(pullRequestService, settings)]; - case 5: - changedInPR_1 = _a.sent(); - annotatedReports = annotatedReports.map(function (report) { - var change = changedInPR_1.find(function (c) { return c.FilePath === report.FilePath; }); - if (change) { - report.commitId = change.CommitId; - report.changeType = change.changeType; - } - return report; - }).filter(function (x) { - var include = changedInPR_1.some(function (c) { return c.FilePath === x.FilePath; }); - if (include) { - console.log("\u2714 Include file: ".concat(x.FilePath)); - } - else { - console.log("\u274C Exclude file: ".concat(x.FilePath)); - } - return include; - }); - // Filter format issues to only include those in changed lines - annotatedReports = annotatedReports.map(function (report) { - var change = changedInPR_1.find(function (c) { return c.FilePath === report.FilePath; }); - if (change && change.lineChanges.length > 0) { - report.FileChanges = report.FileChanges.filter(function (changeData) { - return change.lineChanges.includes(changeData.LineNumber); - }); - } - return report; - }).filter(function (report) { return report.FileChanges.length > 0; }); - _a.label = 6; - case 6: - // Update the Pull Request comment threads based on the format check reports - return [4 /*yield*/, updatePullRequestThreads(pullRequestService, annotatedReports)]; - case 7: - // Update the Pull Request comment threads based on the format check reports - _a.sent(); - return [4 /*yield*/, setPullRequestStatusAndDetermineShouldFailTask(pullRequestService, annotatedReports.length > 0, settings.Parameters.failOnFormattingErrors, settings.Parameters.statusCheck)]; - case 8: - // Set final Pull Request status and determine if the task should fail - return [2 /*return*/, _a.sent()]; - } - }); - }); -} -/** - * The `getChangedFilesInPR` function retrieves - * all pull request file changes with respect to their commits it handles. - * - * @param {PullRequestService} pullRequestUtils - An instance of PullRequestService to interact with Pull Request API - * @param {Settings} settings - * @return {Promise} - Returns a Promise that resolves to an array of file changes. - * Each record denotes a path, commit id and change type in a file as a result of a commit. - * - * @description - * Function operates asynchronously, because of the nature of its service calls to GitService and PullRequestService. - */ -function getChangedFilesInPR(pullRequestUtils, settings) { - return __awaiter(this, void 0, void 0, function () { - var pullRequestChanges, maxRetries, attempt, error_1, files, _loop_1, _i, _a, change; - var _b, _c; - return __generator(this, function (_d) { - switch (_d.label) { - case 0: - console.log("Getting the PR commits..."); - maxRetries = 3; - attempt = 0; - _d.label = 1; - case 1: - if (!(attempt < maxRetries)) return [3 /*break*/, 8]; - _d.label = 2; - case 2: - _d.trys.push([2, 4, , 7]); - return [4 /*yield*/, pullRequestUtils.getPullRequestChanges()]; - case 3: - // Due to intermittent issues with Azure DevOps API (ECONNRESET), we implement a retry mechanism - pullRequestChanges = _d.sent(); - return [3 /*break*/, 8]; - case 4: - error_1 = _d.sent(); - attempt++; - console.warn("Attempt ".concat(attempt, " to getPullRequestChanges failed: ").concat(error_1)); - if (!(attempt < maxRetries)) return [3 /*break*/, 6]; - return [4 /*yield*/, new Promise(function (res) { return setTimeout(res, 1000 * attempt); })]; - case 5: - _d.sent(); - _d.label = 6; - case 6: return [3 /*break*/, 7]; - case 7: return [3 /*break*/, 1]; - case 8: - if (!pullRequestChanges) { - throw new Error("Pull request changes could not be retrieved."); - } - files = []; - _loop_1 = function (change) { - if (change.item.path == undefined) { - console.warn("Warning: File path is undefined for commit id " + ((_b = change.item) === null || _b === void 0 ? void 0 : _b.commitId)); - return "continue"; - } - var normalizedPath = new path_normalizer_1.PathNormalizer(settings).normalizeFilePath(change.item.path); - // Extract line changes if available - var lineChanges = []; - if (change) { - // Check if the change has a 'changes' property and handle it - if (change.changes && Array.isArray(change.changes)) { - for (var _e = 0, _f = change.changes; _e < _f.length; _e++) { - var fileChange = _f[_e]; - if (fileChange.addedLines && Array.isArray(fileChange.addedLines)) { - fileChange.addedLines.forEach(function (line) { - if (line && line.lineNumber > 0) { - lineChanges.push(line.lineNumber); - } - }); - } - if (fileChange.removedLines && Array.isArray(fileChange.removedLines)) { - fileChange.removedLines.forEach(function (line) { - if (line && line.lineNumber > 0) { - lineChanges.push(line.lineNumber); - } - }); - } - } - } - } - files.push(new pull_request_file_change_1.PullRequestFileChange(normalizedPath, (_c = change.item) === null || _c === void 0 ? void 0 : _c.commitId, change.changeType, lineChanges)); - }; - for (_i = 0, _a = pullRequestChanges; _i < _a.length; _i++) { - change = _a[_i]; - _loop_1(change); - } - console.log("All changed files considered to be part of this Pull Request: "); - files.forEach(function (file) { - console.log("".concat(file.FilePath, " - ").concat(file.changeType, " - ").concat(file.CommitId)); - if (file.lineChanges.length > 0) { - console.log(" Changed lines: ".concat(file.lineChanges.join(', '))); - } - }); - return [2 /*return*/, files]; - } - }); - }); -} -/** - * The `updatePullRequestThreads` function updates the pull request comment threads based on given format check reports. - * - * @param {PullRequestService} pullRequestService - An instance of PullRequestService to interact with the Pull Request API. - * @param {AnnotatedReports} reports - AnnotatedReports object containing information about every commit that contains formatting issues. - * - * @returns {Promise} - Returns a Promise that will be fulfilled after all the pull request comment threads have been updated. - * - * @description - * This function operates asynchronously due to the nature of its service calls to the PullRequestService. - * It fetches existing threads and for each report in `reports`, it generates a content for comments which keeps the track of active issues. - * If there is an existing thread for the active issue, it updates that thread; if not, it creates a new thread for the issue. - * Lastly, it also closes threads for resolved issues. - */ -function updatePullRequestThreads(pullRequestService, reports) { - return __awaiter(this, void 0, void 0, function () { - var existingThreads, activeIssuesContent, _i, reports_1, report, _loop_2, _a, _b, change; - return __generator(this, function (_c) { - switch (_c.label) { - case 0: - console.log("Fetching existing threads."); - return [4 /*yield*/, pullRequestService.getThreads()]; - case 1: - existingThreads = _c.sent(); - console.log("Completed fetching existing threads."); - activeIssuesContent = []; - _i = 0, reports_1 = reports; - _c.label = 2; - case 2: - if (!(_i < reports_1.length)) return [3 /*break*/, 7]; - report = reports_1[_i]; - _loop_2 = function (change) { - var content, existingThread, comment, thread, thread; - return __generator(this, function (_d) { - switch (_d.label) { - case 0: - content = "".concat(commentPreamble, " ").concat(change.DiagnosticId, ": ").concat(change.FormatDescription, " on line ").concat(change.LineNumber, ", position ").concat(change.CharNumber); - activeIssuesContent.push(content); // Keep track of active issues - existingThread = existingThreads.find(function (thread) { var _a; return (_a = thread.comments) === null || _a === void 0 ? void 0 : _a.some(function (comment) { return comment.content === content; }); }); - comment = { - content: content, - commentType: gi.CommentType.Text - }; - if (!existingThread) return [3 /*break*/, 2]; - console.log("Updating existing thread."); - if (!existingThread.id) { - throw new Error("Existing thread id is not set."); - } - thread = { - status: gi.CommentThreadStatus.Active, - lastUpdatedTime: new Date() - }; - return [4 /*yield*/, pullRequestService.updateThread(thread, existingThread.id)]; - case 1: - _d.sent(); - return [3 /*break*/, 4]; - case 2: - if (report.changeType === gi.VersionControlChangeType.Delete) { - console.log("Skipping creating thread for deleted file ".concat(report.FilePath, ".")); - return [2 /*return*/, "continue"]; - } - console.log("\uD83D\uDCDD Creating new thread for file ".concat(report.FilePath, ".")); - thread = { - comments: [comment], - status: gi.CommentThreadStatus.Active, - threadContext: { - filePath: report.FilePath, - rightFileStart: { line: change.LineNumber, offset: change.CharNumber }, - rightFileEnd: { line: change.LineNumber, offset: change.CharNumber + 1 } - } - }; - return [4 /*yield*/, pullRequestService.createThread(thread)]; - case 3: - _d.sent(); - _d.label = 4; - case 4: return [2 /*return*/]; - } - }); - }; - _a = 0, _b = report.FileChanges; - _c.label = 3; - case 3: - if (!(_a < _b.length)) return [3 /*break*/, 6]; - change = _b[_a]; - return [5 /*yield**/, _loop_2(change)]; - case 4: - _c.sent(); - _c.label = 5; - case 5: - _a++; - return [3 /*break*/, 3]; - case 6: - _i++; - return [3 /*break*/, 2]; - case 7: - // Close threads for resolved issues - return [4 /*yield*/, markResolvedThreadsAsClosed(pullRequestService, existingThreads, activeIssuesContent)]; - case 8: - // Close threads for resolved issues - _c.sent(); - return [2 /*return*/]; - } - }); - }); -} -/** - * Asynchronously marks threads that were previously marked as resolved now as closed. - * - * @param {PullRequestService} pullRequestService - An instance of PullRequestService to interact with the Pull Request API. - * @param {gi.GitPullRequestCommentThread[]} existingThreads - The current set of existing pull request comment threads. - * @param {string[]} activeIssuesContent - The content of comments that have active issues. - * - * @description - * Iterates over the existing threads filtered for those starting with a specific preamble. - * If the existing thread status is set to closed, it is ignored. Else, for each existing thread, its content is compared with the - * contents of active issues. If a particular threads content does not match, it is considered as resolved and hence marked as closed. - */ -function markResolvedThreadsAsClosed(pullRequestService, existingThreads, activeIssuesContent) { - return __awaiter(this, void 0, void 0, function () { - var _i, _a, existingThread, threadContent, closedThread; - var _b, _c; - return __generator(this, function (_d) { - switch (_d.label) { - case 0: - _i = 0, _a = existingThreads.filter(function (thread) { var _a; return (_a = thread.comments) === null || _a === void 0 ? void 0 : _a.some(function (comment) { var _a; return (_a = comment.content) === null || _a === void 0 ? void 0 : _a.startsWith(commentPreamble); }); }); - _d.label = 1; - case 1: - if (!(_i < _a.length)) return [3 /*break*/, 4]; - existingThread = _a[_i]; - console.log("Processing the existing thread for file ".concat((_b = existingThread.threadContext) === null || _b === void 0 ? void 0 : _b.filePath, ".")); - if (existingThread.status === gi.CommentThreadStatus.Closed) { - return [3 /*break*/, 3]; - } - threadContent = (_c = existingThread.comments[0]) === null || _c === void 0 ? void 0 : _c.content; - if (!(threadContent && !activeIssuesContent.includes(threadContent))) return [3 /*break*/, 3]; - console.log("🔒 Closing resolved thread."); - if (!existingThread.id) { - throw new Error("Existing thread id is not set."); - } - closedThread = { - status: gi.CommentThreadStatus.Closed - }; - return [4 /*yield*/, pullRequestService.updateThread(closedThread, existingThread.id)]; - case 2: - _d.sent(); - _d.label = 3; - case 3: - _i++; - return [3 /*break*/, 1]; - case 4: return [2 /*return*/]; - } - }); - }); -} -/** - * Function `getStatusDescription` provides human-reader friendly status messages based on git status state. - * @param {gi.GitStatusState} status - determines a state of the Git. - * @returns {string} - corresponding message to the Git state. - */ -function getStatusDescription(status) { - switch (status) { - case gi.GitStatusState.Pending: - return "Format check is running"; - case gi.GitStatusState.Failed: - return "Formatting errors found"; - case gi.GitStatusState.Error: - return "Formatting task failed with an error."; - default: - return "No formatting errors found"; - } -} -/** - * An asynchronous function named `setPullRequestStatusAndDetermineShouldFailTask` is used for setting the status for pull requests and determining if the task should fail or not. - * - * @param {PullRequestService} pullRequestService - An instance of PullRequestService which is used to handle interactions with the Pull Request API. - * @param {boolean} formatIssuesExist - It denotes whether issues related with code format exist or not. - * @param {boolean} failOnFormattingErrors - It signifies whether the formatting errors should cause the function to fail. - * @param {boolean} setStatusCheck - It signifies whether the status check is to be set or not. - * @returns {Promise} - The function returns a promise that resolves to a boolean indicating if the task should fail based on the code format. - * - * @description - * This function makes use of console variable for logging and PullRequestService for setting the pull request status. In case of formatting errors and when set to fail on such errors, - * the function logs a failure message and subsequently sets the pull request status to 'Failed'. If there are no formatting issues or the function is not set to fail on such issues, - * the successful log message is printed and the pull request status is set to 'Succeeded'. - */ -function setPullRequestStatusAndDetermineShouldFailTask(pullRequestService, formatIssuesExist, failOnFormattingErrors, setStatusCheck) { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - if (!formatIssuesExist) return [3 /*break*/, 3]; - if (!setStatusCheck) return [3 /*break*/, 2]; - return [4 /*yield*/, pullRequestService.updatePullRequestStatus(gi.GitStatusState.Failed, getStatusDescription)]; - case 1: - _a.sent(); - _a.label = 2; - case 2: - if (failOnFormattingErrors) { - console.log("##vso[task.complete result=Failed;]Code format is incorrect."); - return [2 /*return*/, true]; - } - else { - console.log("##vso[task.complete result=Succeeded;]Code format is incorrect."); - return [2 /*return*/, false]; - } - return [3 /*break*/, 6]; - case 3: - console.log("##vso[task.complete result=Succeeded;]Code format is correct."); - if (!setStatusCheck) return [3 /*break*/, 5]; - return [4 /*yield*/, pullRequestService.updatePullRequestStatus(gi.GitStatusState.Succeeded, getStatusDescription)]; - case 4: - _a.sent(); - _a.label = 5; - case 5: return [2 /*return*/, false]; - case 6: return [2 /*return*/]; - } - }); - }); -} diff --git a/src/format-check/scripts/format-check.test.js b/src/format-check/scripts/format-check.test.js deleted file mode 100644 index 436fe29..0000000 --- a/src/format-check/scripts/format-check.test.js +++ /dev/null @@ -1,422 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); - return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -jest.mock('fs'); -jest.mock('child_process'); -jest.mock('process'); -jest.mock('console', function () { return ({ - error: jest.fn(), -}); }); -jest.mock('node-fetch', function () { return jest.fn(function () { return Promise.resolve({ - json: function () { return __awaiter(void 0, void 0, void 0, function () { - return __generator(this, function (_a) { - return [2 /*return*/, ({ - changes: [ - { - changeType: gi.VersionControlChangeType.Edit, - item: { - path: "somefile.ts", - commitId: "commit123" - }, - changes: [ - { - addedLines: [{ lineNumber: 10 }, { lineNumber: 11 }], - removedLines: [{ lineNumber: 5 }] - } - ] - } - ] - })]; - }); - }); }, -}); }); }); -var gi = __importStar(require("azure-devops-node-api/interfaces/GitInterfaces")); -var globals_1 = require("@jest/globals"); -var pull_request_file_change_1 = require("./types/pull-request-file-change"); -var format_check_1 = require("./format-check"); -var base_git_api_service_1 = require("./services/base-git-api-service"); -var fs_1 = __importDefault(require("fs")); -var crypto_1 = require("crypto"); -var child_process = __importStar(require("child_process")); -(0, globals_1.describe)('getChangedFilesInPR', function () { - // mock PullRequestService - var pullRequestServiceMock = { - getPullRequestChanges: jest.fn() - }; - var settingsMock = { - Environment: { - sourcesDirectory: "/path/to" - } - }; - (0, globals_1.beforeEach)(function () { - jest.resetAllMocks(); - // mock console - global.console.warn = jest.fn(); - }); - (0, globals_1.it)('should return the list of changed files in a PR', function () { return __awaiter(void 0, void 0, void 0, function () { - var changesListMock, result; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - changesListMock = [ - { - changeType: gi.VersionControlChangeType.Edit, - item: { - path: 'path/to/test.ts', - commitId: 'commit123' - } - } - ]; - pullRequestServiceMock.getPullRequestChanges.mockReturnValue(changesListMock); - return [4 /*yield*/, (0, format_check_1.getChangedFilesInPR)(pullRequestServiceMock, settingsMock)]; - case 1: - result = _a.sent(); - // Assert - (0, globals_1.expect)(result).toHaveLength(1); - (0, globals_1.expect)(result).toEqual([new pull_request_file_change_1.PullRequestFileChange('path/to/test.ts', 'commit123', gi.VersionControlChangeType.Edit, [])]); - return [2 /*return*/]; - } - }); - }); }); - (0, globals_1.it)('should extract line changes from pull request changes', function () { return __awaiter(void 0, void 0, void 0, function () { - var changesListMock, result; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - changesListMock = [ - { - changeType: gi.VersionControlChangeType.Edit, - item: { - path: 'path/to/test.ts', - commitId: 'commit123' - }, - changes: [ - { - addedLines: [{ lineNumber: 10 }, { lineNumber: 11 }], - removedLines: [{ lineNumber: 5 }] - } - ] - } - ]; - pullRequestServiceMock.getPullRequestChanges.mockReturnValue(changesListMock); - return [4 /*yield*/, (0, format_check_1.getChangedFilesInPR)(pullRequestServiceMock, settingsMock)]; - case 1: - result = _a.sent(); - // Assert - (0, globals_1.expect)(result).toHaveLength(1); - (0, globals_1.expect)(result[0].FilePath).toEqual('path/to/test.ts'); - // Sort the lineChanges array to ensure consistent order - (0, globals_1.expect)(result[0].lineChanges.sort(function (a, b) { return a - b; })).toEqual([5, 10, 11].sort(function (a, b) { return a - b; })); - return [2 /*return*/]; - } - }); - }); }); - (0, globals_1.it)('should console warn if a change does not have a path', function () { return __awaiter(void 0, void 0, void 0, function () { - var changesListMock; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - changesListMock = [ - { - changeType: gi.VersionControlChangeType.Edit, - item: { - path: undefined, - commitId: 'commit123' - } - } - ]; - pullRequestServiceMock.getPullRequestChanges.mockReturnValue(changesListMock); - // Act - return [4 /*yield*/, (0, format_check_1.getChangedFilesInPR)(pullRequestServiceMock, settingsMock)]; - case 1: - // Act - _a.sent(); - // Assert - (0, globals_1.expect)(console.warn).toHaveBeenCalledWith("Warning: File path is undefined for commit id commit123"); - return [2 /*return*/]; - } - }); - }); }); -}); -(0, globals_1.describe)('runFormatCheck', function () { - var mockGitApi; - var mockSettings = { - Environment: { - orgUrl: "https://some-url/", - repoId: "rrrrr", - projectId: "ppppp", - pullRequestId: 123, - token: "some-token-secret", - sourcesDirectory: '/src', - pullRequestSourceCommit: '123123132123', - pullRequestTargetBranch: '/refs/heads/main' - }, - Parameters: { - statusCheck: true, - statusCheckContext: { - genre: "formatting", - name: "dotnet format check" - }, - scopeToPullRequest: true, - failOnFormattingErrors: false, - solutionPath: 'test', - includePath: 'test', - excludePath: 'test' - } - }; - (0, globals_1.beforeEach)(function () { - jest.resetAllMocks(); - mockGitApi = { - updatePullRequest: jest.fn(), - getPullRequestIterations: jest.fn(), - getPullRequest: jest.fn(), - getPullRequestById: jest.fn(), - createPullRequestStatus: jest.fn(), - getThreads: jest.fn(), - createThread: jest.fn(), - updateThread: jest.fn() - }; - }); - (0, globals_1.it)('should update PullRequest status and return false if there are format errors', function () { return __awaiter(void 0, void 0, void 0, function () { - var document, mockReport, mockGitCommitDiffs, _a, firstArg, mockReportWithMultipleIssues_1, _b, threadArgs; - return __generator(this, function (_c) { - switch (_c.label) { - case 0: - jest.spyOn(base_git_api_service_1.BaseGitApiService, 'getGitApi').mockReturnValue(Promise.resolve(mockGitApi)); - fs_1.default.existsSync.mockReturnValue(true); // Mock return value - jest.spyOn(child_process, 'execSync').mockReturnValue(Buffer.from('')); - document = { - Id: (0, crypto_1.randomUUID)(), - ProjectId: { - Id: (0, crypto_1.randomUUID)() - } - }; - mockReport = [ - { - DocumentId: document, - FileName: "somefile.ts", - FilePath: "/src/somefile.ts", - FileChanges: [ - { - CharNumber: 1, - DiagnosticId: (0, crypto_1.randomUUID)(), - LineNumber: 2, - FormatDescription: "some error" - } - ] - }, - { - DocumentId: document, - FileName: "file-not-in-pr.ts", - FilePath: "/src/file-not-in-pr.ts", - FileChanges: [ - { - CharNumber: 5, - DiagnosticId: (0, crypto_1.randomUUID)(), - LineNumber: 1, - FormatDescription: "some error not relevant" - } - ] - } - ]; - fs_1.default.readFileSync.mockImplementation(function () { return JSON.stringify(mockReport); }); - fs_1.default.unlinkSync.mockImplementation(function () { }); - fs_1.default.existsSync.mockImplementation(function () { return true; }); - mockGitApi.updatePullRequest.mockImplementation(jest.fn()); - mockGitApi.getPullRequestIterations.mockReturnValueOnce([ - { - id: 1, - description: 'Initial commit', - author: { - displayName: 'Mock Author', - id: 'mock_author_123', - }, - updatedAt: new Date() - } - ]); - mockGitApi.getPullRequestIterations.mockReturnValueOnce([ - { - id: 1, - description: 'Initial commit', - author: { - displayName: 'Mock Author', - id: 'mock_author_123', - }, - updatedAt: new Date() - } - ]); - mockGitApi.getPullRequestById.mockReturnValue(Promise.resolve({ - status: 'active', - createdBy: { - displayName: 'Test User', - id: 'test_user_123', - }, - creationDate: new Date() - })); - mockGitCommitDiffs = { - changes: [ - { - changeType: gi.VersionControlChangeType.Edit, - item: { - path: "/somefile.ts", - commitId: (0, crypto_1.randomUUID)() - }, - changes: [ - { - addedLines: [{ lineNumber: 10 }, { lineNumber: 11 }], - removedLines: [{ lineNumber: 5 }] - } - ] - } - ] - }; - jest.spyOn(globalThis, 'fetch').mockResolvedValue({ - ok: true, - status: 200, - json: function () { return Promise.resolve(mockGitCommitDiffs); }, - headers: new Headers({ 'Content-Type': 'application/json' }) - }); - mockGitApi.getThreads.mockReturnValue(Promise.resolve([ - { - id: 1, - comments: [ - { - content: '[DotNetFormatTask][Automated] Test comment', - } - ] - } - ])); - _a = globals_1.expect; - return [4 /*yield*/, (0, format_check_1.runFormatCheck)(mockSettings)]; - case 1: - _a.apply(void 0, [_c.sent()]).toEqual(false); - if (!(mockGitApi.createThread.mock.calls.length > 0)) return [3 /*break*/, 3]; - firstArg = mockGitApi.createThread.mock.calls[0][0]; - // expect the first call to be for '/src/somefile.ts' - (0, globals_1.expect)(firstArg).toMatchObject({ - threadContext: globals_1.expect.objectContaining({ - filePath: globals_1.expect.stringContaining('/somefile.ts') - }) - }); - // Loop through each call to ensure none of them contain '/src/some-file-not-in-pr.ts' - mockGitApi.createThread.mock.calls.forEach(function (call) { - var firstArg = call[0]; - (0, globals_1.expect)(firstArg).not.toMatchObject({ - threadContext: globals_1.expect.objectContaining({ - filePath: globals_1.expect.stringContaining('/src/file-not-in-pr.ts') - }) - }); - }); - mockReportWithMultipleIssues_1 = [ - { - DocumentId: document, - FileName: "somefile.ts", - FilePath: "/src/somefile.ts", - FileChanges: [ - { - CharNumber: 1, - DiagnosticId: (0, crypto_1.randomUUID)(), - LineNumber: 2, // Not in changed lines - FormatDescription: "some error" - }, - { - CharNumber: 1, - DiagnosticId: (0, crypto_1.randomUUID)(), - LineNumber: 10, // In changed lines - FormatDescription: "some error in changed line" - } - ] - } - ]; - fs_1.default.readFileSync.mockImplementation(function () { return JSON.stringify(mockReportWithMultipleIssues_1); }); - // Reset mocks - mockGitApi.createThread.mockReset(); - mockGitApi.updateThread.mockReset(); - _b = globals_1.expect; - return [4 /*yield*/, (0, format_check_1.runFormatCheck)(mockSettings)]; - case 2: - _b.apply(void 0, [_c.sent()]).toEqual(true); // Should return true because there is a formatting error in a changed line - // Verify that only the issue on line 10 (a changed line) was reported - (0, globals_1.expect)(mockGitApi.createThread).toHaveBeenCalled(); - threadArgs = mockGitApi.createThread.mock.calls[0][0]; - if (threadArgs.comments) { - (0, globals_1.expect)(threadArgs.comments[0].content).toContain("LineNumber: 10"); - (0, globals_1.expect)(threadArgs.comments[0].content).not.toContain("LineNumber: 2"); - } - _c.label = 3; - case 3: return [2 /*return*/]; - } - }); - }); }); -}); diff --git a/src/format-check/scripts/main.js b/src/format-check/scripts/main.js deleted file mode 100644 index a502393..0000000 --- a/src/format-check/scripts/main.js +++ /dev/null @@ -1,78 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); - return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var format_check_1 = require("./format-check"); -var base_git_api_service_1 = require("./services/base-git-api-service"); -var settings_1 = require("./types/settings"); -var dotenv_1 = __importDefault(require("dotenv")); -dotenv_1.default.config(); -function main() { - return __awaiter(this, void 0, void 0, function () { - var settings, shouldFail; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - settings = (0, settings_1.getSettings)(); - return [4 /*yield*/, base_git_api_service_1.BaseGitApiService.init(settings)]; - case 1: - _a.sent(); - return [4 /*yield*/, (0, format_check_1.runFormatCheck)(settings)]; - case 2: - shouldFail = _a.sent(); - // Exit the program based on the format check outcome - if (shouldFail) { - console.log("Format check task failed."); - process.exit(1); - } - else { - console.log("Format check task succeeded."); - process.exit(0); - } - return [2 /*return*/]; - } - }); - }); -} -// Call these functions in your main function and do your own error handling -main().catch(function (error) { - console.error(error); - process.exit(1); -}); diff --git a/src/format-check/scripts/services/base-git-api-service.js b/src/format-check/scripts/services/base-git-api-service.js deleted file mode 100644 index d3acbae..0000000 --- a/src/format-check/scripts/services/base-git-api-service.js +++ /dev/null @@ -1,128 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); - return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.BaseGitApiService = void 0; -var azdev = __importStar(require("azure-devops-node-api")); -var BaseGitApiService = /** @class */ (function () { - function BaseGitApiService() { - } - BaseGitApiService.init = function (settings) { - return __awaiter(this, void 0, void 0, function () { - var authHandler, connection, _a; - return __generator(this, function (_b) { - switch (_b.label) { - case 0: - if (this.GitApiPromise) - return [2 /*return*/]; - console.log("Creating personal access token handler."); - authHandler = azdev.getPersonalAccessTokenHandler(settings.Parameters.token); - console.log("Creating TFS connection."); - connection = new azdev.WebApi(settings.Environment.orgUrl, authHandler); - console.log("Getting Git API."); - this.GitApiPromise = connection.getGitApi(); - _a = this; - return [4 /*yield*/, this.GitApiPromise]; - case 1: - _a.GitApi = _b.sent(); - return [2 /*return*/]; - } - }); - }); - }; - BaseGitApiService.getGitApi = function () { - return __awaiter(this, void 0, void 0, function () { - var _a; - return __generator(this, function (_b) { - switch (_b.label) { - case 0: - if (this.GitApiPromise === null) { - throw new Error('call BaseGitApiService.init() first'); - } - if (!(this.GitApi === null)) return [3 /*break*/, 2]; - _a = this; - return [4 /*yield*/, this.GitApiPromise]; - case 1: - _a.GitApi = _b.sent(); - _b.label = 2; - case 2: return [2 /*return*/, this.GitApi]; - } - }); - }); - }; - BaseGitApiService.reset = function () { - this.GitApi = null; - this.GitApiPromise = null; - }; - BaseGitApiService.GitApi = null; - BaseGitApiService.GitApiPromise = null; - return BaseGitApiService; -}()); -exports.BaseGitApiService = BaseGitApiService; diff --git a/src/format-check/scripts/services/base-git-api-service.test.js b/src/format-check/scripts/services/base-git-api-service.test.js deleted file mode 100644 index e2c014c..0000000 --- a/src/format-check/scripts/services/base-git-api-service.test.js +++ /dev/null @@ -1,201 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); - return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var azdev = __importStar(require("azure-devops-node-api")); -var globals_1 = require("@jest/globals"); -var base_git_api_service_1 = require("./base-git-api-service"); -var crypto_1 = require("crypto"); -// Explicitly cast to jest.Mock -var MockedWebApi = azdev.WebApi; -var MockedGetPersonalAccessTokenHandler = azdev.getPersonalAccessTokenHandler; -globals_1.jest.mock('azure-devops-node-api'); -(0, globals_1.describe)('BaseGitApiService', function () { - var mockSettings; - (0, globals_1.beforeEach)(function () { - mockSettings = { - Environment: { - orgUrl: 'mockOrgUrl', - repoId: 'mockRepoId', - projectId: 'mockProjectId', - pullRequestId: 1, - token: 'mockToken', - sourcesDirectory: '/src', - pullRequestSourceCommit: (0, crypto_1.randomUUID)(), - pullRequestTargetBranch: '/refs/heads/main' - }, - Parameters: { - solutionPath: 'mockSolutionPath', - includePath: 'mockIncludePath', - excludePath: 'mockExcludePath', - statusCheck: true, - failOnFormattingErrors: false, - statusCheckContext: { - name: 'mockName', - genre: 'mockGenre' - }, - scopeToPullRequest: true, - token: 'mockToken' - } - }; - globals_1.jest.clearAllMocks(); - MockedWebApi.mockClear(); - base_git_api_service_1.BaseGitApiService.reset(); - }); - (0, globals_1.it)('should initialize Azure DevOps Git API', function () { return __awaiter(void 0, void 0, void 0, function () { - var mockGetGitApi, mockWebApiInstance; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - mockGetGitApi = globals_1.jest.fn(); - mockWebApiInstance = { getGitApi: mockGetGitApi }; - MockedGetPersonalAccessTokenHandler.mockReturnValue({}); - MockedWebApi.mockImplementation(function () { return mockWebApiInstance; }); - // Calling the function - return [4 /*yield*/, base_git_api_service_1.BaseGitApiService.init(mockSettings)]; - case 1: - // Calling the function - _a.sent(); - // Assertions - (0, globals_1.expect)(MockedGetPersonalAccessTokenHandler).toHaveBeenCalledWith(mockSettings.Parameters.token); - (0, globals_1.expect)(MockedWebApi).toHaveBeenCalledWith(mockSettings.Environment.orgUrl, {}); - (0, globals_1.expect)(mockGetGitApi).toHaveBeenCalledTimes(1); - return [2 /*return*/]; - } - }); - }); }); - (0, globals_1.it)('should return the initialized Git API instance', function () { return __awaiter(void 0, void 0, void 0, function () { - var mockGitApiInstance, returnedGitApi; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - mockGitApiInstance = { - baseUrl: "https://mockurl" - }; - base_git_api_service_1.BaseGitApiService.GitApiPromise = Promise.resolve(mockGitApiInstance); - base_git_api_service_1.BaseGitApiService.GitApi = mockGitApiInstance; - return [4 /*yield*/, base_git_api_service_1.BaseGitApiService.getGitApi()]; - case 1: - returnedGitApi = _a.sent(); - // Assertions - (0, globals_1.expect)(returnedGitApi).toBe(mockGitApiInstance); - return [2 /*return*/]; - } - }); - }); }); - (0, globals_1.it)('should throw error if init fails', function () { return __awaiter(void 0, void 0, void 0, function () { - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - MockedWebApi.mockImplementation(function () { - return { - getGitApi: function () { return Promise.reject(new Error('Initialization failed')); } - }; - }); - return [4 /*yield*/, (0, globals_1.expect)(base_git_api_service_1.BaseGitApiService.init(mockSettings)).rejects.toThrow('Initialization failed')]; - case 1: - _a.sent(); - return [2 /*return*/]; - } - }); - }); }); - (0, globals_1.it)('should throw an error if GitApi is not initialized', function () { return __awaiter(void 0, void 0, void 0, function () { - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - base_git_api_service_1.BaseGitApiService.GitApi = null; - return [4 /*yield*/, (0, globals_1.expect)(base_git_api_service_1.BaseGitApiService.getGitApi()).rejects.toStrictEqual(new Error('call BaseGitApiService.init() first'))]; - case 1: - _a.sent(); - return [2 /*return*/]; - } - }); - }); }); - (0, globals_1.it)('should not re-initialize if already initialized', function () { return __awaiter(void 0, void 0, void 0, function () { - var mockGetGitApi, mockWebApiInstance; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - console.log(" ===================== it('should not re-initialize if already initialized', async () => { ================"); - mockGetGitApi = globals_1.jest.fn(function () { return Promise.resolve(); }); - mockWebApiInstance = { getGitApi: mockGetGitApi }; - MockedWebApi.mockImplementation(function () { return mockWebApiInstance; }); - return [4 /*yield*/, base_git_api_service_1.BaseGitApiService.init(mockSettings)]; - case 1: - _a.sent(); - return [4 /*yield*/, base_git_api_service_1.BaseGitApiService.init(mockSettings)]; - case 2: - _a.sent(); - (0, globals_1.expect)(mockGetGitApi).toHaveBeenCalledTimes(1); - return [2 /*return*/]; - } - }); - }); }); -}); diff --git a/src/format-check/scripts/services/format-check-runner.js b/src/format-check/scripts/services/format-check-runner.js deleted file mode 100644 index 0c1e897..0000000 --- a/src/format-check/scripts/services/format-check-runner.js +++ /dev/null @@ -1,188 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); - return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.FormatCheckRunner = void 0; -var child_process_1 = require("child_process"); -var fs = __importStar(require("fs")); -/** - * @class FormatCheckRunner - * A utility class to run .NET format checks on a given solution. - */ -var FormatCheckRunner = /** @class */ (function () { - /** - * Initializes a new instance of FormatCheckRunner. - * - * @param {string} solutionPath - The path to the .NET solution file. - * @param {string} includePath - Files to include in the format check. - * @param {string} excludePath - Files to exclude from the format check. - * - * @example - * const runner = new FormatCheckRunner("./solution.sln", "./include", "./exclude"); - */ - function FormatCheckRunner(solutionPath, includePath, excludePath) { - this.solutionPath = solutionPath; - this.includePath = includePath; - this.excludePath = excludePath; - this.reportPath = "format-report.json"; - if (!fs.existsSync(solutionPath)) { - console.error("Solution file at solutionPath does not exist."); - process.exit(1); - } - if (fs.existsSync(this.reportPath)) { - fs.unlinkSync(this.reportPath); - console.log("Successfully deleted the existing report file."); - } - } - /** - * Runs the .NET format check command and returns a report. - * - * @returns {Promise} - The formatting error report. - * - * @example - * const report = await runner.runFormatCheck(); - * - * @throws Error when the command fails. - */ - FormatCheckRunner.prototype.runFormatCheck = function () { - return __awaiter(this, void 0, void 0, function () { - var formatCmd, dotnetFormatVersion, error_1; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - _a.trys.push([0, 2, , 3]); - formatCmd = this.getCommandString(); - console.log("Running dotnet format command. (".concat(formatCmd, ")")); - dotnetFormatVersion = (0, child_process_1.execSync)("dotnet format --version", { - encoding: "utf8", - }); - console.log("Using dotnet format version ".concat(dotnetFormatVersion)); - try { - (0, child_process_1.execSync)(formatCmd, { stdio: ["inherit", "inherit", "pipe"] }); - } - catch (error) { - this.handleDotnetFormatError(error); - } - console.log("Dotnet format command completed."); - return [4 /*yield*/, this.retrieveErrorReport()]; - case 1: return [2 /*return*/, _a.sent()]; - case 2: - error_1 = _a.sent(); - console.error("Dotnet format task failed with error ".concat(error_1)); - process.exit(1); - return [3 /*break*/, 3]; - case 3: return [2 /*return*/]; - } - }); - }); - }; - /** - * @private - * Generates the .NET format command string based on the given parameters. - * - * @returns {string} - The generated command string. - */ - FormatCheckRunner.prototype.getCommandString = function () { - return "dotnet format ".concat(this.solutionPath, " --verify-no-changes --verbosity diagnostic --report ").concat(this.reportPath, " ").concat(this.includePath ? "--include ".concat(this.includePath) : "", " ").concat(this.excludePath ? "--exclude ".concat(this.excludePath) : ""); - }; - /** - * @private - * Handles errors thrown by the `dotnet format` command. - * - * @param {any} error - The error to handle. - */ - FormatCheckRunner.prototype.handleDotnetFormatError = function (error) { - console.error("Dotnet format command failed with error ".concat(error)); - if ("stderr" in error && error.stderr) { - console.error("stderr output:", error.stderr.toString()); - } - if (!fs.existsSync(this.reportPath)) { - // Format command has failed. No report was generated. - console.error("No report found at reportPath."); - process.exit(1); - } - }; - /** - * @private - * Retrieves the formatting error report generated by the `dotnet format` command. - * - * @returns {Promise} - The formatting error report. - */ - FormatCheckRunner.prototype.retrieveErrorReport = function () { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - console.log("Loading error report."); - return [2 /*return*/, JSON.parse(fs.readFileSync(this.reportPath, "utf8"))]; - }); - }); - }; - return FormatCheckRunner; -}()); -exports.FormatCheckRunner = FormatCheckRunner; diff --git a/src/format-check/scripts/services/format-check-runner.test.js b/src/format-check/scripts/services/format-check-runner.test.js deleted file mode 100644 index 625e4a9..0000000 --- a/src/format-check/scripts/services/format-check-runner.test.js +++ /dev/null @@ -1,237 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); - return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var format_check_runner_1 = require("./format-check-runner"); -var child_process_1 = require("child_process"); -var fs = __importStar(require("fs")); -var globals_1 = require("@jest/globals"); -var crypto_1 = require("crypto"); -globals_1.jest.mock('child_process'); -var mockExecSync = globals_1.jest.mocked(child_process_1.execSync); -globals_1.jest.mock('process'); -globals_1.jest.mock('console', function () { return ({ - error: globals_1.jest.fn(), -}); }); -globals_1.jest.mock('fs'); -var mockUnlinkSync = globals_1.jest.mocked(fs.unlinkSync); -var mockExistsSync = globals_1.jest.mocked(fs.existsSync); -(0, globals_1.describe)('FormatCheckRunner', function () { - var runner; - var exitSpy; - var exitCode = 0; - (0, globals_1.beforeEach)(function () { - globals_1.jest.clearAllMocks(); - exitSpy = globals_1.jest.spyOn(process, 'exit').mockImplementation(function (code) { - exitCode = code === null ? 0 : (typeof code === 'number' ? code : 0); - return undefined; - }); - }); - (0, globals_1.afterEach)(function () { - // Clean up the spy - exitSpy.mockRestore(); - }); - (0, globals_1.it)('should construct without errors', function () { - fs.existsSync.mockReturnValue(true); // Mock return value - runner = new format_check_runner_1.FormatCheckRunner('./solution.sln', './include', './exclude'); - (0, globals_1.expect)(runner).toBeInstanceOf(format_check_runner_1.FormatCheckRunner); - }); - (0, globals_1.it)('should fail construction if solution does not exist', function () { - fs.existsSync.mockReturnValue(false); - // Mock process.exit before the test - var exitSpy = globals_1.jest.spyOn(process, 'exit').mockImplementation((function () { - })); - new format_check_runner_1.FormatCheckRunner('./solution.sln', './include', './exclude'); - // Check if process.exit has been called with code 1 - (0, globals_1.expect)(exitSpy).toHaveBeenCalledWith(1); - // Restore process.exit to its original function after the test - exitSpy.mockRestore(); - }); - (0, globals_1.it)('should run format check successfully', function () { return __awaiter(void 0, void 0, void 0, function () { - var mockReport, report; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - mockReport = [ - { - DocumentId: { - Id: (0, crypto_1.randomUUID)(), - ProjectId: { - Id: (0, crypto_1.randomUUID)() - } - }, - FileName: "somefile.ts", - FilePath: "/src/somefile.ts", - FileChanges: [ - { - CharNumber: 1, - DiagnosticId: (0, crypto_1.randomUUID)(), - LineNumber: 2, - FormatDescription: "some error" - } - ] - } - ]; - fs.existsSync.mockReturnValue(true); // Mock return value - fs.readFileSync.mockReturnValue(JSON.stringify(mockReport)); - runner = new format_check_runner_1.FormatCheckRunner('./solution.sln', './include', './exclude'); - return [4 /*yield*/, runner.runFormatCheck()]; - case 1: - report = _a.sent(); - (0, globals_1.expect)(report).toEqual(mockReport); - (0, globals_1.expect)(child_process_1.execSync).toHaveBeenCalled(); - return [2 /*return*/]; - } - }); - }); }); - (0, globals_1.it)('should handle dotnet format crashes', function () { return __awaiter(void 0, void 0, void 0, function () { - var mockError; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - mockError = new Error('Dotnet format crashed'); - mockExecSync.mockImplementation((function (command) { - if (command.startsWith('dotnet format')) { - throw mockError; - } - return Buffer.from('mock buffer content', 'utf-8'); - })); - mockExistsSync.mockReturnValue(false); - runner = new format_check_runner_1.FormatCheckRunner('./solution.sln', './include', './exclude'); - return [4 /*yield*/, runner.runFormatCheck()]; - case 1: - _a.sent(); - (0, globals_1.expect)(exitCode).toBe(1); - return [2 /*return*/]; - } - }); - }); }); - (0, globals_1.it)('should handle dotnet format errors', function () { return __awaiter(void 0, void 0, void 0, function () { - var mockReport; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - mockReport = [ - { - DocumentId: { - Id: (0, crypto_1.randomUUID)(), - ProjectId: { - Id: (0, crypto_1.randomUUID)() - } - }, - FileName: "somefile.ts", - FilePath: "/src/somefile.ts", - FileChanges: [ - { - CharNumber: 1, - DiagnosticId: (0, crypto_1.randomUUID)(), - LineNumber: 2, - FormatDescription: "some error" - } - ] - } - ]; - fs.readFileSync.mockReturnValue(JSON.stringify(mockReport)); - child_process_1.execSync - .mockImplementationOnce(function () { - }) - .mockImplementationOnce(function () { - }); - fs.existsSync.mockReturnValueOnce(true); - mockUnlinkSync.mockImplementation((function (path) { - if (path.toString().endsWith('format-report.json')) { - // do nothing - } - else { - throw new Error("not mocked"); - } - })); - runner = new format_check_runner_1.FormatCheckRunner('./solution.sln', './include', './exclude'); - return [4 /*yield*/, (0, globals_1.expect)(runner.runFormatCheck()).resolves.toEqual([{ - "DocumentId": { - "Id": mockReport[0].DocumentId.Id, - "ProjectId": { "Id": mockReport[0].DocumentId.ProjectId.Id } - }, - "FileChanges": [{ - "CharNumber": 1, - "DiagnosticId": mockReport[0].FileChanges[0].DiagnosticId, - "FormatDescription": "some error", - "LineNumber": 2 - }], - "FileName": "somefile.ts", - "FilePath": "/src/somefile.ts" - }])]; - case 1: - _a.sent(); - return [2 /*return*/]; - } - }); - }); }); -}); diff --git a/src/format-check/scripts/services/pull-request-service.js b/src/format-check/scripts/services/pull-request-service.js deleted file mode 100644 index 2deb551..0000000 --- a/src/format-check/scripts/services/pull-request-service.js +++ /dev/null @@ -1,350 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); - return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.PullRequestService = void 0; -exports.getPullRequestService = getPullRequestService; -var gi = __importStar(require("azure-devops-node-api/interfaces/GitInterfaces")); -var base_git_api_service_1 = require("./base-git-api-service"); -var node_fetch_1 = __importDefault(require("node-fetch")); -/** - * PullRequestService class is a service that offers methods to interact with pull requests. - * Its purpose is to help in performing operations related to pull requests like obtaining pull request commits, - * updating pull request statuses and working with threads in pull requests. - * - * @class - * @public - * - * @property {IGitApi} gitApi - An instance of IGitApi to interact with Azure DevOps Git API. - * @property {Settings} settings - An instance of Settings, containing project-specific parameters and environment variables. - * - * @method constructor(gitApi, settings) - Initializes a new instance of the PullRequestService class. - * @method async updatePullRequestStatus(status, getStatusDescription) - Asynchronously updates the pull request status. - * @method private async getLastPullRequestIteration() - Asynchronously obtains the last pull request iteration. - * @method async getPullRequestChanges() - Asynchronously fetches and returns the changes made in a pull request. - * @method async getThreads() - Asynchronously gets the threads related to a pull request. - * @method async updateThread(commentThread, existingThreadId) - Asynchronously updates a specific thread of a pull request. - * @method async createThread(thread) - Asynchronously creates a new thread in a pull request. - */ -var PullRequestService = /** @class */ (function () { - /** - * Constructor for PullRequestService. - * - * @param {IGitApi} gitApi - An instance of IGitApi to interact with Azure DevOps Git API. - * @param {Settings} settings - An instance of Settings to use project-specific parameters and environment variables. - */ - function PullRequestService(gitApi, settings) { - this.gitApi = gitApi; - this.settings = settings; - } - /** - * Async method that updates the pull request status. - * - * @method updatePullRequestStatus - * @public - * @async - * - * @param {gi.GitStatusState} status - The status enum of GitStatusState, representing the status of the pull request. - * @param {Function} getStatusDescription - A function that returns the description of the GitStatusState status. - * - * This method first gets the last pull request iteration ID, then creates a GitPullRequestStatus object. - * Finally, it calls the `createPullRequestStatus` method from the `gitApi` to update the pull request status. - * - * @returns {Promise} A promise that resolves when the pull request status has been updated. - */ - PullRequestService.prototype.updatePullRequestStatus = function (status, getStatusDescription) { - return __awaiter(this, void 0, void 0, function () { - var logMsg, iterationId, prStatus; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - if (!this.settings.Parameters.statusCheck) { - console.warn("updatePullRequestStatus called to set status check, but statusCheck task parameter is false"); - return [2 /*return*/]; - } - if (!this.settings.Parameters.statusCheckContext) { - throw new Error("statusCheckContext is not set in the settings"); - } - logMsg = "Setting status check '".concat(this.settings.Parameters.statusCheckContext.genre, "\\").concat(this.settings.Parameters.statusCheckContext.name, "' to: ").concat(gi.GitStatusState[status]); - console.log(logMsg); - return [4 /*yield*/, this.getLastPullRequestIteration()]; - case 1: - iterationId = _a.sent(); - prStatus = { - context: this.settings.Parameters.statusCheckContext, - state: status, - description: getStatusDescription(status), - iterationId: iterationId, - }; - return [4 /*yield*/, this.gitApi.createPullRequestStatus(prStatus, this.settings.Environment.repoId, this.settings.Environment.pullRequestId)]; - case 2: - _a.sent(); - return [2 /*return*/]; - } - }); - }); - }; - /** - * Asynchronously fetches and returns the changes made in a pull request. - * - * @method getPullRequestChanges - * @public - * @async - * - * This method first fetches an instance of the pull request with the help of the `gitApi.getPullRequest` method, - * using repository id, pull request id, and project id derived from `settings.Environment`. - * Then, it fetches the differences between the base version (source branch) and the target version (target branch) - * of the pull request using the `gitApi.getCommitDiffs` method. - * - * The `baseVersion`, `baseVersionOptions`, `baseVersionType`, `targetVersion`, `targetVersionOptions`, - * and `targetVersionType` parameters for `gitApi.getCommitDiffs` method are set using the properties of - * the obtained pull request instance. - * - * @returns {Promise} A promise that fulfills with an array of GitChange objects that represents the changes - * made in the pull request. If there are no changes, an empty array is returned. - */ - PullRequestService.prototype.getPullRequestChanges = function () { - return __awaiter(this, void 0, void 0, function () { - var pr, sourceRefName, targetRefName, token, encodedToken, url, response, commitDiffs, error_1; - var _a, _b; - return __generator(this, function (_c) { - switch (_c.label) { - case 0: return [4 /*yield*/, this.gitApi.getPullRequestById(this.settings.Environment.pullRequestId, this.settings.Environment.projectId)]; - case 1: - pr = _c.sent(); - sourceRefName = (_a = pr.sourceRefName) === null || _a === void 0 ? void 0 : _a.replace('refs/heads/', ''); - targetRefName = (_b = pr.targetRefName) === null || _b === void 0 ? void 0 : _b.replace('refs/heads/', ''); - console.log("Checking for file changes between ".concat(sourceRefName, " and ").concat(targetRefName)); - token = this.settings.Parameters.token; - encodedToken = Buffer.from(":".concat(token)).toString('base64'); - url = "".concat(this.settings.Environment.orgUrl).concat(this.settings.Environment.projectId, "/") + - "_apis/git/repositories/".concat(this.settings.Environment.repoId, "/diffs/commits") + - "?api-version=4.1&baseVersion=".concat(targetRefName, "&targetVersion=").concat(sourceRefName) + - "&targetVersionType=branch&baseVersionType=branch&diffCommonCommit=false&inlineChangedLines=true"; - console.log("Fetching ".concat(url)); - return [4 /*yield*/, (0, node_fetch_1.default)(url, { - headers: { - 'Authorization': "Basic ".concat(encodedToken) - } - })]; - case 2: - response = _c.sent(); - _c.label = 3; - case 3: - _c.trys.push([3, 5, , 6]); - return [4 /*yield*/, response.json()]; - case 4: - commitDiffs = (_c.sent()); - return [3 /*break*/, 6]; - case 5: - error_1 = _c.sent(); - console.error("Error parsing JSON response:", error_1); - return [2 /*return*/, []]; - case 6: return [2 /*return*/, (commitDiffs === null || commitDiffs === void 0 ? void 0 : commitDiffs.changes) || []]; - } - }); - }); - }; - /** - * Asynchronously fetches and returns discussion threads related to a specific pull request. - * - * @method getThreads - * @public - * @async - * - * This method uses the `gitApi` instance to call the `getThreads` function where it fetches all discussion threads for - * a specific pull request in the Azure DevOps Git API. The repository id, pull request id, and project id derived from - * the properties of `settings.EnvVars` specified in the Settings instance are used to target the correct pull request. - * Fetching pull request threads can be beneficial when wanting to analyze the discussions and comments related to a pull - * request. - * - * @returns {Promise} A promise that fulfills with an array of - * GitPullRequestCommentThread objects representing all the threads involved in the pull request discussion. Each - * GitPullRequestCommentThread object encapsulates information regarding a single thread including the comments, - * the status of the thread, and so on. - */ - PullRequestService.prototype.getThreads = function () { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, this.gitApi.getThreads(this.settings.Environment.repoId, this.settings.Environment.pullRequestId, this.settings.Environment.projectId)]; - case 1: return [2 /*return*/, _a.sent()]; - } - }); - }); - }; - /** - * Asynchronously updates a specific thread of a pull request. - * - * @method updateThread - * @public - * @async - * - * @param {GitPullRequestCommentThread} commentThread - The comment thread object containing the modifications. - * @param {number} existingThreadId - The ID of the existing thread to be updated. - * - * This method leverages the `gitApi` instance to interact with the Azure DevOps Git API's `updateThread` method. - * It uses the repository id, pull request id, and project id from `settings.EnvVars` to pinpoint the desired pull request. - * This is used when modifications are required in a specific discussion thread concerning a pull request. - * - * @returns {Promise} A promise that fulfills with the updated GitPullRequestCommentThread - * object once the thread update operation completes. - */ - PullRequestService.prototype.updateThread = function (commentThread, existingThreadId) { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, this.gitApi.updateThread(commentThread, this.settings.Environment.repoId, this.settings.Environment.pullRequestId, existingThreadId, this.settings.Environment.projectId)]; - case 1: return [2 /*return*/, _a.sent()]; - } - }); - }); - }; - /** - * Asynchronously creates a new discussion thread in a specific pull request. - * - * @method createThread - * @public - * @async - * - * @param {GitPullRequestCommentThread} thread - The comment thread object to be created in the pull request. - * - * This method employs the `gitApi` instance to call the Azure DevOps Git API's `createThread` method. - * It uses attributes like repository id, pull request id, and project id from `settings.EnvVars` to - * target the intended pull request. Typically, a new thread could be created to start a discussion about - * some aspect of the pull request. - * - * @returns {Promise} A promise that fulfills with the newly created - * GitPullRequestCommentThread object after the thread creation operation is done. - */ - PullRequestService.prototype.createThread = function (thread) { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - return [2 /*return*/, this.gitApi.createThread(thread, this.settings.Environment.repoId, this.settings.Environment.pullRequestId, this.settings.Environment.projectId)]; - }); - }); - }; - /** - * Private asynchronous method that retrieves the last pull request iteration's ID. - * - * @private - * @async - * - * @method getLastPullRequestIteration - * - * This method internally queries the Azure DevOps Git API to fetch all iterations of a pull request - * by utilizing project-specific parameters and environment variables provided in the Settings instance. - * From the received data, it retrieves and returns the ID of the last pull request iteration. - * - * @returns {Promise} A promise that fulfills with the ID of the last iteration of the pull request. - */ - PullRequestService.prototype.getLastPullRequestIteration = function () { - return __awaiter(this, void 0, void 0, function () { - var pullRequestIterations, lastIteration; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, this.gitApi.getPullRequestIterations(this.settings.Environment.repoId, this.settings.Environment.pullRequestId, this.settings.Environment.projectId, true)]; - case 1: - pullRequestIterations = _a.sent(); - lastIteration = pullRequestIterations.pop(); - if (!(lastIteration === null || lastIteration === void 0 ? void 0 : lastIteration.id)) { - throw new Error("Last PullRequest Iteration ID not set"); - } - return [2 /*return*/, lastIteration.id]; - } - }); - }); - }; - return PullRequestService; -}()); -exports.PullRequestService = PullRequestService; -/** - * The async function `getPullRequestService` initializes the BaseGitApiService with the specified settings and then returns - * a new instance of the PullRequestService with the BaseGitApiService's GitApi and the specified settings. - * - * @param {Settings} settings - An instance of Settings containing project-specific parameters and environment variables. - * @returns {Promise} A promise that resolves to a new instance of PullRequestService. - */ -function getPullRequestService(settings) { - return __awaiter(this, void 0, void 0, function () { - var _a; - return __generator(this, function (_b) { - switch (_b.label) { - case 0: - _a = PullRequestService.bind; - return [4 /*yield*/, base_git_api_service_1.BaseGitApiService.getGitApi()]; - case 1: return [2 /*return*/, new (_a.apply(PullRequestService, [void 0, _b.sent(), settings]))()]; - } - }); - }); -} diff --git a/src/format-check/scripts/services/pull-request-service.test.js b/src/format-check/scripts/services/pull-request-service.test.js deleted file mode 100644 index ea95101..0000000 --- a/src/format-check/scripts/services/pull-request-service.test.js +++ /dev/null @@ -1,321 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); - return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var node_fetch_1 = __importDefault(require("node-fetch")); -jest.mock('node-fetch', function () { return jest.fn(); }); -jest.mock('./base-git-api-service', function () { - return { - BaseGitApiService: { - getGitApi: jest.fn().mockReturnValue({}), - }, - }; -}); -var pull_request_service_1 = require("./pull-request-service"); -var gi = __importStar(require("azure-devops-node-api/interfaces/GitInterfaces")); -var globals_1 = require("@jest/globals"); -var crypto_1 = require("crypto"); -(0, globals_1.describe)('PullRequestService', function () { - var mockGitApi; - var settings; - var service; - (0, globals_1.beforeEach)(function () { - mockGitApi = { - getChanges: jest.fn(), - createThread: jest.fn(), - updateThread: jest.fn(), - getThreads: jest.fn(), - getPullRequestById: jest.fn(), - createPullRequestStatus: jest.fn(), - getPullRequestIterations: jest.fn() - }; - settings = { - Environment: { - orgUrl: 'https://mockOrgUrl/', - repoId: 'mockRepoId', - projectId: 'mockProjectId', - pullRequestId: 1, - token: 'mockToken', - sourcesDirectory: '/src', - pullRequestSourceCommit: (0, crypto_1.randomUUID)(), - pullRequestTargetBranch: '/refs/heads/main' - }, - Parameters: { - solutionPath: 'mockSolutionPath', - includePath: 'mockIncludePath', - excludePath: 'mockExcludePath', - statusCheck: true, - failOnFormattingErrors: false, - statusCheckContext: { - name: 'mockName', - genre: 'mockGenre' - }, - scopeToPullRequest: true, - token: 'mockToken' - } - }; - service = new pull_request_service_1.PullRequestService(mockGitApi, settings); - }); - (0, globals_1.it)('should updatePullRequestStatus correctly', function () { return __awaiter(void 0, void 0, void 0, function () { - var status, descriptionFunc; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - status = gi.GitStatusState.Succeeded; - descriptionFunc = function (_status) { return 'description'; }; - mockGitApi.getPullRequestIterations.mockReturnValue([ - { - id: 1, - description: 'Initial commit', - author: { - displayName: 'Mock Author', - id: 'mock_author_123', - }, - updatedAt: new Date(), - }, - { - id: 2, - description: 'Updated commit', - author: { - displayName: 'Mock Author', - id: 'mock_author_123', - }, - updatedAt: new Date(), - } - ]); - return [4 /*yield*/, service.updatePullRequestStatus(status, descriptionFunc)]; - case 1: - _a.sent(); - (0, globals_1.expect)(mockGitApi.createPullRequestStatus).toHaveBeenCalled(); // Add more assertions based on your logic - return [2 /*return*/]; - } - }); - }); }); - (0, globals_1.it)('should getPullRequestChanges correctly', function () { return __awaiter(void 0, void 0, void 0, function () { - var mockReturnValue, changes; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - mockGitApi.getPullRequestById.mockReturnValue({ - pullRequestId: settings.Environment.pullRequestId, - repository: { - id: settings.Environment.repoId - }, - sourceRefName: 'refs/heads/feature/test', - targetRefName: 'targetRef', - }); - mockReturnValue = { - changeCounts: { - edit: 2, - add: 3, - delete: 1 - }, - changes: [ - { - changeType: gi.VersionControlChangeType.Edit, - item: { - path: '/path1', - }, - }, - { - changeType: gi.VersionControlChangeType.Edit, - item: { - path: '/path2', - }, - }, - { - changeType: gi.VersionControlChangeType.Add, - item: { - path: '/path3', - }, - }, - { - changeType: gi.VersionControlChangeType.Add, - item: { - path: '/path4', - }, - }, - { - changeType: gi.VersionControlChangeType.Add, - item: { - path: '/path5', - }, - }, - { - changeType: gi.VersionControlChangeType.Delete, - item: { - path: '/path6', - }, - }, - ], - diffCommonCommit: { - commitId: 'mockCommitId', - }, - }; - node_fetch_1.default.mockResolvedValueOnce({ - status: 200, - json: function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) { - return [2 /*return*/, mockReturnValue]; - }); }); }, - }); - return [4 /*yield*/, service.getPullRequestChanges()]; - case 1: - changes = _a.sent(); - (0, globals_1.expect)(changes).toEqual(mockReturnValue.changes); - return [2 /*return*/]; - } - }); - }); }); - (0, globals_1.it)('should getThreads correctly', function () { return __awaiter(void 0, void 0, void 0, function () { - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, service.getThreads()]; - case 1: - _a.sent(); - (0, globals_1.expect)(mockGitApi.getThreads).toHaveBeenCalled(); - return [2 /*return*/]; - } - }); - }); }); - (0, globals_1.it)('should updateThread correctly', function () { return __awaiter(void 0, void 0, void 0, function () { - var thread, existingThreadId; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - thread = { /* populate this */}; - existingThreadId = 1; - return [4 /*yield*/, service.updateThread(thread, existingThreadId)]; - case 1: - _a.sent(); - (0, globals_1.expect)(mockGitApi.updateThread).toHaveBeenCalled(); - return [2 /*return*/]; - } - }); - }); }); - (0, globals_1.it)('should createThread correctly', function () { return __awaiter(void 0, void 0, void 0, function () { - var thread; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - thread = { /* populate this */}; - return [4 /*yield*/, service.createThread(thread)]; - case 1: - _a.sent(); - (0, globals_1.expect)(mockGitApi.createThread).toHaveBeenCalled(); - return [2 /*return*/]; - } - }); - }); }); -}); -(0, globals_1.describe)('getPullRequestService function', function () { - var settings; - (0, globals_1.beforeEach)(function () { - settings = { - Environment: { - orgUrl: 'mockOrgUrl', - repoId: 'mockRepoId', - projectId: 'mockProjectId', - pullRequestId: 1, - token: 'mockToken', - sourcesDirectory: '/src', - pullRequestSourceCommit: (0, crypto_1.randomUUID)(), - pullRequestTargetBranch: '/refs/heads/main' - }, - Parameters: { - solutionPath: 'mockSolutionPath', - includePath: 'mockIncludePath', - excludePath: 'mockExcludePath', - statusCheck: true, - failOnFormattingErrors: false, - statusCheckContext: { - name: 'mockName', - genre: 'mockGenre' - }, - scopeToPullRequest: true, - token: 'mockToken' - } - }; - }); - (0, globals_1.it)('should return a new PullRequestService instance', function () { return __awaiter(void 0, void 0, void 0, function () { - var result; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, (0, pull_request_service_1.getPullRequestService)(settings)]; - case 1: - result = _a.sent(); - (0, globals_1.expect)(result).toBeInstanceOf(pull_request_service_1.PullRequestService); - return [2 /*return*/]; - } - }); - }); }); -}); diff --git a/src/format-check/scripts/types/annotated-report.js b/src/format-check/scripts/types/annotated-report.js deleted file mode 100644 index 06af690..0000000 --- a/src/format-check/scripts/types/annotated-report.js +++ /dev/null @@ -1,36 +0,0 @@ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -exports.AnnotatedReport = void 0; -var format_report_1 = require("./format-report"); -/** - * @class AnnotatedReport - * Extends FormatReport to include version control information. - * - * @extends {FormatReport} - */ -var AnnotatedReport = /** @class */ (function (_super) { - __extends(AnnotatedReport, _super); - function AnnotatedReport(commitId, changeType) { - var _this = _super.call(this) || this; - _this.commitId = commitId; - _this.changeType = changeType; - return _this; - } - return AnnotatedReport; -}(format_report_1.FormatReport)); -exports.AnnotatedReport = AnnotatedReport; diff --git a/src/format-check/scripts/types/environment.js b/src/format-check/scripts/types/environment.js deleted file mode 100644 index 50c56b7..0000000 --- a/src/format-check/scripts/types/environment.js +++ /dev/null @@ -1,17 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Environment = void 0; -/** -* Environment class parameters. -* @property {string | undefined} orgUrl - The organization URL. -* @property {string | undefined} repoId - The repository ID. -* @property {string | undefined} projectId - The project ID. -* @property {number | undefined} pullRequestId - The pull request ID. -* @property {string | undefined} token - The access token used for authentication. -*/ -var Environment = /** @class */ (function () { - function Environment() { - } - return Environment; -}()); -exports.Environment = Environment; diff --git a/src/format-check/scripts/types/format-report.js b/src/format-check/scripts/types/format-report.js deleted file mode 100644 index 148bce8..0000000 --- a/src/format-check/scripts/types/format-report.js +++ /dev/null @@ -1,42 +0,0 @@ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -exports.FormatReports = exports.FormatReport = void 0; -/** - * @class FormatReport - * A class to represent the report of a single file's formatting issues. - */ -var FormatReport = /** @class */ (function () { - function FormatReport() { - } - return FormatReport; -}()); -exports.FormatReport = FormatReport; -/** -* @class FormatReports -* An array-like class to hold multiple FormatReport instances. -* -* @extends {Array} -*/ -var FormatReports = /** @class */ (function (_super) { - __extends(FormatReports, _super); - function FormatReports() { - return _super !== null && _super.apply(this, arguments) || this; - } - return FormatReports; -}(Array)); -exports.FormatReports = FormatReports; diff --git a/src/format-check/scripts/types/parameters.js b/src/format-check/scripts/types/parameters.js deleted file mode 100644 index 00d7e0c..0000000 --- a/src/format-check/scripts/types/parameters.js +++ /dev/null @@ -1,23 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Parameters = void 0; -/** - * The Parameters class models the attributes for configuration settings. - * - * @class - * - * @param {string | undefined} solutionPath - The path of the solution to check. Can be undefined. - * @param {string | undefined} excludePath - Path to exclude from the files to check. Can be undefined. - * @param {boolean} failOnFormattingErrors - Whether to fail the process on formatting errors. - * @param {string | undefined} includePath - Path to include for files to check. Can be undefined. - * @param {boolean} scopeToPullRequest - Whether the operation scope is limited to thr pull request or not. - * @param {boolean} statusCheck - Whether to set the status check or not. - * @param {Object} statusCheckContext - Context for the status check comprising genre and name attributes. - * @param {string | undefined} token - Authentication token. Can be undefined. - */ -var Parameters = /** @class */ (function () { - function Parameters() { - } - return Parameters; -}()); -exports.Parameters = Parameters; diff --git a/src/format-check/scripts/types/pull-request-file-change.js b/src/format-check/scripts/types/pull-request-file-change.js deleted file mode 100644 index 690ef7f..0000000 --- a/src/format-check/scripts/types/pull-request-file-change.js +++ /dev/null @@ -1,47 +0,0 @@ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -exports.PullRequestFileChanges = exports.PullRequestFileChange = void 0; -/** - * @class PullRequestFileChange - * A class to represent individual file changes within a Pull Request. - */ -var PullRequestFileChange = /** @class */ (function () { - function PullRequestFileChange(FilePath, CommitId, changeType, lineChanges) { - if (lineChanges === void 0) { lineChanges = []; } - this.FilePath = FilePath; - this.CommitId = CommitId; - this.changeType = changeType; - this.lineChanges = lineChanges; - } - return PullRequestFileChange; -}()); -exports.PullRequestFileChange = PullRequestFileChange; -/** - * @class PullRequestFileChanges - * An array-like class to hold multiple PullRequestFileChange instances. - * - * @extends {Array} - */ -var PullRequestFileChanges = /** @class */ (function (_super) { - __extends(PullRequestFileChanges, _super); - function PullRequestFileChanges() { - return _super !== null && _super.apply(this, arguments) || this; - } - return PullRequestFileChanges; -}(Array)); -exports.PullRequestFileChanges = PullRequestFileChanges; diff --git a/src/format-check/scripts/types/settings.js b/src/format-check/scripts/types/settings.js deleted file mode 100644 index 9fa05d0..0000000 --- a/src/format-check/scripts/types/settings.js +++ /dev/null @@ -1,78 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.getSettings = void 0; -/** - * Returns an object of type `Settings` populated from environment variables. - * - * @function getSettings - * @returns {Settings} - An object that holds various environmental variables and parameters. - * - * @throws {Error} Will exit the process if `SYSTEM_PULLREQUEST_PULLREQUESTID` or `SolutionPath` is not set. - */ -var getSettings = function () { - var _a, _b, _c; - var pullRequestId = parseInt(process.env.SYSTEM_PULLREQUEST_PULLREQUESTID, 10); - if (!pullRequestId) { - console.log("Not a PR build. Skipping."); - process.exit(0); - } - var settings = { - Environment: { - orgUrl: process.env.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI || (function () { - throw new Error("SYSTEM_TEAMFOUNDATIONCOLLECTIONURI is not set."); - })(), - repoId: process.env.BUILD_REPOSITORY_ID || (function () { - throw new Error("BUILD_REPOSITORY_ID is not set."); - })(), - projectId: process.env.SYSTEM_TEAMPROJECTID || (function () { - throw new Error("SYSTEM_TEAMPROJECTID is not set."); - })(), - pullRequestId: pullRequestId, - token: process.env.SYSTEM_ACCESSTOKEN, - sourcesDirectory: process.env.BUILD_SOURCESDIRECTORY || (function () { - throw new Error("BUILD_SOURCESDIRECTORY is not set."); - })(), - pullRequestSourceCommit: process.env.SYSTEM_PULLREQUEST_SOURCECOMMITID || (function () { - throw new Error("SYSTEM_PULLREQUEST_SOURCECOMMITID is not set."); - })(), - pullRequestTargetBranch: process.env.SYSTEM_PULLREQUEST_TARGETBRANCH || (function () { - throw new Error("SYSTEM_PULLREQUEST_TARGETBRANCH is not set."); - })(), - }, - Parameters: { - solutionPath: process.env.INPUT_SOLUTIONPATH, - includePath: process.env.INPUT_INCLUDEPATH, - excludePath: process.env.INPUT_EXCLUDEPATH, - statusCheck: process.env.INPUT_STATUSCHECK === 'true', - failOnFormattingErrors: process.env.INPUT_FAILONFORMATTINGERRORS === 'true', - statusCheckContext: process.env.INPUT_STATUSCHECKNAME && process.env.INPUT_STATUSCHECKGENRE ? { - name: process.env.INPUT_STATUSCHECKNAME, - genre: process.env.INPUT_STATUSCHECKGENRE, - } : undefined, - scopeToPullRequest: process.env.INPUT_SCOPETOPULLREQUEST === 'true', - token: process.env.INPUT_PAT || process.env.SYSTEM_ACCESSTOKEN || (function () { - throw new Error("Token is not set."); - })() - } - }; - console.log('task input parameters:'); - console.log("Solution Path: ".concat(settings.Parameters.solutionPath)); - console.log("Include Path: ".concat(settings.Parameters.includePath)); - console.log("Exclude Path: ".concat(settings.Parameters.excludePath)); - console.log("Status Check: ".concat(settings.Parameters.statusCheck)); - console.log("Fail On Formatting Errors: ".concat(settings.Parameters.failOnFormattingErrors)); - console.log("Status Check Name: ".concat((_a = settings.Parameters.statusCheckContext) === null || _a === void 0 ? void 0 : _a.name)); - console.log("Status Check Genre: ".concat((_b = settings.Parameters.statusCheckContext) === null || _b === void 0 ? void 0 : _b.genre)); - console.log("Scope To Pull Request: ".concat(settings.Parameters.scopeToPullRequest)); - console.log("OrgUrl: ".concat(settings.Environment.orgUrl)); - console.log("RepoId: ".concat(settings.Environment.repoId)); - console.log("ProjectId: ".concat(settings.Environment.projectId)); - console.log("PullRequestId: ".concat(settings.Environment.pullRequestId)); - console.log("Sources Directory: ".concat(settings.Environment.sourcesDirectory)); - if (!((_c = settings.Parameters.solutionPath) === null || _c === void 0 ? void 0 : _c.trim())) { - console.error("SolutionPath is not set."); - process.exit(1); - } - return settings; -}; -exports.getSettings = getSettings; diff --git a/src/format-check/scripts/types/settings.test.js b/src/format-check/scripts/types/settings.test.js deleted file mode 100644 index e37043a..0000000 --- a/src/format-check/scripts/types/settings.test.js +++ /dev/null @@ -1,84 +0,0 @@ -"use strict"; -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var settings_1 = require("./settings"); // Adjust the import to match your actual file layout -var globals_1 = require("@jest/globals"); -(0, globals_1.describe)('getSettings', function () { - var consoleLogSpy; - var originalEnv; - (0, globals_1.beforeAll)(function () { - // Save the original process.env - originalEnv = __assign({}, process.env); - }); - (0, globals_1.beforeEach)(function () { - consoleLogSpy = globals_1.jest.spyOn(console, 'log').mockImplementation(function (_message) { - var _options = []; - for (var _i = 1; _i < arguments.length; _i++) { - _options[_i - 1] = arguments[_i]; - } - }); - }); - (0, globals_1.afterEach)(function () { - // Restore the original process.env and console.log - process.env = __assign({}, originalEnv); - consoleLogSpy.mockRestore(); - }); - (0, globals_1.it)('should not log the token', function () { - // Mock necessary environment variables - process.env.BUILD_REPOSITORY_ID = 'repoId'; - process.env.BUILD_SOURCESDIRECTORY = '/src'; - process.env.SYSTEM_PULLREQUEST_PULLREQUESTID = '123'; - process.env.SYSTEM_PULLREQUEST_SOURCECOMMITID = '123123-1231230123123-13123'; - process.env.SYSTEM_PULLREQUEST_TARGETBRANCH = '/refs/heads/main'; - process.env.SYSTEM_TEAMPROJECTID = 'projectId'; - process.env.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI = 'uri'; - process.env.INPUT_SOLUTIONPATH = 'solutionPath'; - process.env.INPUT_INCLUDEPATH = '.*'; - process.env.INPUT_EXCLUDEPATH = '.*.test.ts'; - process.env.INPUT_STATUSCHECK = 'true'; - process.env.INPUT_STATUSCHECKNAME = 'code formatting'; - process.env.INPUT_STATUSCHECKGENRE = 'formatting check'; - process.env.INPUT_FAILONFORMATTINGERRORS = 'true'; - process.env.INPUT_SCOPETOPULLREQUEST = 'true'; - process.env.SYSTEM_ACCESSTOKEN = 'token'; - process.env.INPUT_PAT = 'token'; - var settings = (0, settings_1.getSettings)(); - // Verify token is not logged - (0, globals_1.expect)(consoleLogSpy).not.toHaveBeenCalledWith(globals_1.expect.stringContaining('token')); - (0, globals_1.expect)(settings).toEqual({ - Environment: { - orgUrl: 'uri', - repoId: 'repoId', - projectId: 'projectId', - pullRequestId: 123, - token: 'token', - sourcesDirectory: '/src', - pullRequestSourceCommit: '123123-1231230123123-13123', - pullRequestTargetBranch: '/refs/heads/main' - }, - Parameters: { - excludePath: '.*.test.ts', - failOnFormattingErrors: true, - includePath: '.*', - scopeToPullRequest: true, - solutionPath: 'solutionPath', - statusCheck: true, - statusCheckContext: { - genre: 'formatting check', - name: 'code formatting' - }, - token: 'token' - } - }); - }); -}); diff --git a/src/format-check/scripts/utils/path-normalizer.js b/src/format-check/scripts/utils/path-normalizer.js deleted file mode 100644 index 14833b6..0000000 --- a/src/format-check/scripts/utils/path-normalizer.js +++ /dev/null @@ -1,37 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.PathNormalizer = void 0; -/** - * PathNormalizer is a class for path normalization tasks. It uses the settings object for its behavioural config. - * The main task is to convert an absolute file path to a relative path from the project's source directory. - * - * @class - * @property {Settings} settings - An object of Type Settings necessary for the working of PathNormalizer. - * @constructor - * @param {Settings} settings - Configurable settings used in path normalization tasks. - * @method - * public normalizeFilePath(filePath: string): string - Takes an absolute file path and normalizes it to be relative to the - * source directory specified in the `settings` object. - */ -var PathNormalizer = /** @class */ (function () { - function PathNormalizer(settings) { - this.settings = settings; - } - /** - * Takes a file path as input and returns a normalized version of the path, relative to the project's source directory. - * - * @public - * @param {string} filePath - The absolute file path to normalise. - * @returns {string} Normalized version of the supplied file path, relative to the project's source directory. - */ - PathNormalizer.prototype.normalizeFilePath = function (filePath) { - // remove trailing slash from sourcesDirectory - var pathToStrip = this.settings.Environment.sourcesDirectory.replace(/\/$/, ''); - // remove the path to the source directory from the file path - var relativeToSourceDir = filePath.replace("".concat(pathToStrip), ''); - // replace \ with / for windows - return relativeToSourceDir.replace(/\\/g, '/'); - }; - return PathNormalizer; -}()); -exports.PathNormalizer = PathNormalizer; diff --git a/src/format-check/scripts/utils/path-normalizer.test.js b/src/format-check/scripts/utils/path-normalizer.test.js deleted file mode 100644 index 6af0953..0000000 --- a/src/format-check/scripts/utils/path-normalizer.test.js +++ /dev/null @@ -1,43 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var path_normalizer_1 = require("./path-normalizer"); -var globals_1 = require("@jest/globals"); -(0, globals_1.describe)('PathNormalizer', function () { - var originalBuildSourcesDirectory; - (0, globals_1.beforeEach)(function () { - // Save the original environment variable - originalBuildSourcesDirectory = process.env.BUILD_SOURCESDIRECTORY; - }); - (0, globals_1.afterEach)(function () { - // Restore the original environment variable - process.env.BUILD_SOURCESDIRECTORY = originalBuildSourcesDirectory; - }); - (0, globals_1.it)('should normalize file path by removing Settings.Environment.sourcesDirectory', function () { - // Arrange - var mockSettings = { - Environment: { - sourcesDirectory: '/source' - } - }; - var filePath = '/source/folder/file.txt'; - var normalizer = new path_normalizer_1.PathNormalizer(mockSettings); - // Act - var normalized = normalizer.normalizeFilePath(filePath); - // Assert - (0, globals_1.expect)(normalized).toBe('/folder/file.txt'); - }); - (0, globals_1.it)('should normalize file path and always keep a /', function () { - // Arrange - var mockSettings = { - Environment: { - sourcesDirectory: '/source/' - } - }; - var filePath = '/source/folder/file.txt'; - var normalizer = new path_normalizer_1.PathNormalizer(mockSettings); - // Act - var normalized = normalizer.normalizeFilePath(filePath); - // Assert - (0, globals_1.expect)(normalized).toBe('/folder/file.txt'); - }); -});