From 9c6893830b53bb4b561293a427c3c20c9ae96f55 Mon Sep 17 00:00:00 2001
From: janssen <118828444+janssen-tiobe@users.noreply.github.com>
Date: Tue, 3 Dec 2024 14:03:49 +0100
Subject: [PATCH 1/2] #35462: Added support for multiple itemTypes
---
dist/index.js | 813 ++++++++++---------
package-lock.json | 6 +-
src/action/decorate/summary.ts | 76 +-
test/unit/action/decorate/objects/summary.ts | 21 +-
test/unit/action/decorate/summary.test.ts | 2 +
5 files changed, 473 insertions(+), 445 deletions(-)
diff --git a/dist/index.js b/dist/index.js
index e9f7393c..1c5d48d2 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -201,6 +201,7 @@ const logger_1 = __nccwpck_require__(26440);
const url_1 = __nccwpck_require__(76259);
const markdown_1 = __nccwpck_require__(60517);
const config_1 = __nccwpck_require__(86444);
+const capitalize = (s) => s && String(s[0]).toUpperCase() + String(s).slice(1);
function createSummaryBody(analysisResult) {
logger_1.logger.header('Creating summary.');
core_1.summary.addHeading('TICS Quality Gate');
@@ -215,7 +216,7 @@ function createSummaryBody(analysisResult) {
if (condition.details && condition.details.items.length > 0) {
core_1.summary.addRaw(`${os_1.EOL}${statusMarkdown}${condition.message}
${os_1.EOL}`);
core_1.summary.addBreak();
- core_1.summary.addTable(createConditionTable(condition.details));
+ createConditionTables(condition.details).forEach(table => core_1.summary.addTable(table));
core_1.summary.addRaw(' ', true);
}
else {
@@ -330,41 +331,43 @@ function createFilesSummary(fileList) {
* @param conditions Conditions of the quality gate
* @returns Table containing a summary for all conditions
*/
-function createConditionTable(details) {
- const rows = [];
- const titleRow = [
- {
- data: 'File',
- header: true
- },
- {
- data: details.dataKeys.actualValue.title,
- header: true
- }
- ];
- if (details.dataKeys.blockingAfter) {
- titleRow.push({
- data: details.dataKeys.blockingAfter.title,
- header: true
- });
- }
- rows.push(titleRow);
- details.items
- .filter(item => item.itemType === 'file')
- .forEach(item => {
- const dataRow = [
- `${os_1.EOL}${os_1.EOL}[${item.name}](${(0, url_1.joinUrl)(config_1.ticsConfig.displayUrl, item.link)})${os_1.EOL}${os_1.EOL}`,
- item.data.actualValue.formattedValue
+function createConditionTables(details) {
+ return details.itemTypes.map(itemType => {
+ const rows = [];
+ const titleRow = [
+ {
+ data: capitalize(itemType),
+ header: true
+ },
+ {
+ data: details.dataKeys.actualValue.title,
+ header: true
+ }
];
- if (item.data.blockingAfter) {
- dataRow.push(item.data.blockingAfter.formattedValue);
- }
- else if (details.dataKeys.blockingAfter) {
- dataRow.push('0');
+ if (details.dataKeys.blockingAfter) {
+ titleRow.push({
+ data: details.dataKeys.blockingAfter.title,
+ header: true
+ });
}
- rows.push(dataRow);
+ rows.push(titleRow);
+ details.items
+ .filter(item => item.itemType === itemType)
+ .forEach(item => {
+ const dataRow = [
+ `${os_1.EOL}${os_1.EOL}[${item.name}](${(0, url_1.joinUrl)(config_1.ticsConfig.displayUrl, item.link)})${os_1.EOL}${os_1.EOL}`,
+ item.data.actualValue.formattedValue
+ ];
+ if (item.data.blockingAfter) {
+ dataRow.push(item.data.blockingAfter.formattedValue);
+ }
+ else if (details.dataKeys.blockingAfter) {
+ dataRow.push('0');
+ }
+ rows.push(dataRow);
+ });
+ return rows;
});
- return rows;
}
/**
* Groups the annotations and creates review comments for them.
@@ -41423,6 +41426,378 @@ function cleanEscapedString(input) {
}
+/***/ }),
+
+/***/ 93822:
+/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
+
+"use strict";
+
+exports.parseISO = parseISO;
+var _index = __nccwpck_require__(17818);
+
+/**
+ * The {@link parseISO} function options.
+ */
+
+/**
+ * @name parseISO
+ * @category Common Helpers
+ * @summary Parse ISO string
+ *
+ * @description
+ * Parse the given string in ISO 8601 format and return an instance of Date.
+ *
+ * Function accepts complete ISO 8601 formats as well as partial implementations.
+ * ISO 8601: http://en.wikipedia.org/wiki/ISO_8601
+ *
+ * If the argument isn't a string, the function cannot parse the string or
+ * the values are invalid, it returns Invalid Date.
+ *
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
+ *
+ * @param argument - The value to convert
+ * @param options - An object with options
+ *
+ * @returns The parsed date in the local time zone
+ *
+ * @example
+ * // Convert string '2014-02-11T11:30:30' to date:
+ * const result = parseISO('2014-02-11T11:30:30')
+ * //=> Tue Feb 11 2014 11:30:30
+ *
+ * @example
+ * // Convert string '+02014101' to date,
+ * // if the additional number of digits in the extended year format is 1:
+ * const result = parseISO('+02014101', { additionalDigits: 1 })
+ * //=> Fri Apr 11 2014 00:00:00
+ */
+function parseISO(argument, options) {
+ const additionalDigits = options?.additionalDigits ?? 2;
+ const dateStrings = splitDateString(argument);
+
+ let date;
+ if (dateStrings.date) {
+ const parseYearResult = parseYear(dateStrings.date, additionalDigits);
+ date = parseDate(parseYearResult.restDateString, parseYearResult.year);
+ }
+
+ if (!date || isNaN(date.getTime())) {
+ return new Date(NaN);
+ }
+
+ const timestamp = date.getTime();
+ let time = 0;
+ let offset;
+
+ if (dateStrings.time) {
+ time = parseTime(dateStrings.time);
+ if (isNaN(time)) {
+ return new Date(NaN);
+ }
+ }
+
+ if (dateStrings.timezone) {
+ offset = parseTimezone(dateStrings.timezone);
+ if (isNaN(offset)) {
+ return new Date(NaN);
+ }
+ } else {
+ const dirtyDate = new Date(timestamp + time);
+ // JS parsed string assuming it's in UTC timezone
+ // but we need it to be parsed in our timezone
+ // so we use utc values to build date in our timezone.
+ // Year values from 0 to 99 map to the years 1900 to 1999
+ // so set year explicitly with setFullYear.
+ const result = new Date(0);
+ result.setFullYear(
+ dirtyDate.getUTCFullYear(),
+ dirtyDate.getUTCMonth(),
+ dirtyDate.getUTCDate(),
+ );
+ result.setHours(
+ dirtyDate.getUTCHours(),
+ dirtyDate.getUTCMinutes(),
+ dirtyDate.getUTCSeconds(),
+ dirtyDate.getUTCMilliseconds(),
+ );
+ return result;
+ }
+
+ return new Date(timestamp + time + offset);
+}
+
+const patterns = {
+ dateTimeDelimiter: /[T ]/,
+ timeZoneDelimiter: /[Z ]/i,
+ timezone: /([Z+-].*)$/,
+};
+
+const dateRegex =
+ /^-?(?:(\d{3})|(\d{2})(?:-?(\d{2}))?|W(\d{2})(?:-?(\d{1}))?|)$/;
+const timeRegex =
+ /^(\d{2}(?:[.,]\d*)?)(?::?(\d{2}(?:[.,]\d*)?))?(?::?(\d{2}(?:[.,]\d*)?))?$/;
+const timezoneRegex = /^([+-])(\d{2})(?::?(\d{2}))?$/;
+
+function splitDateString(dateString) {
+ const dateStrings = {};
+ const array = dateString.split(patterns.dateTimeDelimiter);
+ let timeString;
+
+ // The regex match should only return at maximum two array elements.
+ // [date], [time], or [date, time].
+ if (array.length > 2) {
+ return dateStrings;
+ }
+
+ if (/:/.test(array[0])) {
+ timeString = array[0];
+ } else {
+ dateStrings.date = array[0];
+ timeString = array[1];
+ if (patterns.timeZoneDelimiter.test(dateStrings.date)) {
+ dateStrings.date = dateString.split(patterns.timeZoneDelimiter)[0];
+ timeString = dateString.substr(
+ dateStrings.date.length,
+ dateString.length,
+ );
+ }
+ }
+
+ if (timeString) {
+ const token = patterns.timezone.exec(timeString);
+ if (token) {
+ dateStrings.time = timeString.replace(token[1], "");
+ dateStrings.timezone = token[1];
+ } else {
+ dateStrings.time = timeString;
+ }
+ }
+
+ return dateStrings;
+}
+
+function parseYear(dateString, additionalDigits) {
+ const regex = new RegExp(
+ "^(?:(\\d{4}|[+-]\\d{" +
+ (4 + additionalDigits) +
+ "})|(\\d{2}|[+-]\\d{" +
+ (2 + additionalDigits) +
+ "})$)",
+ );
+
+ const captures = dateString.match(regex);
+ // Invalid ISO-formatted year
+ if (!captures) return { year: NaN, restDateString: "" };
+
+ const year = captures[1] ? parseInt(captures[1]) : null;
+ const century = captures[2] ? parseInt(captures[2]) : null;
+
+ // either year or century is null, not both
+ return {
+ year: century === null ? year : century * 100,
+ restDateString: dateString.slice((captures[1] || captures[2]).length),
+ };
+}
+
+function parseDate(dateString, year) {
+ // Invalid ISO-formatted year
+ if (year === null) return new Date(NaN);
+
+ const captures = dateString.match(dateRegex);
+ // Invalid ISO-formatted string
+ if (!captures) return new Date(NaN);
+
+ const isWeekDate = !!captures[4];
+ const dayOfYear = parseDateUnit(captures[1]);
+ const month = parseDateUnit(captures[2]) - 1;
+ const day = parseDateUnit(captures[3]);
+ const week = parseDateUnit(captures[4]);
+ const dayOfWeek = parseDateUnit(captures[5]) - 1;
+
+ if (isWeekDate) {
+ if (!validateWeekDate(year, week, dayOfWeek)) {
+ return new Date(NaN);
+ }
+ return dayOfISOWeekYear(year, week, dayOfWeek);
+ } else {
+ const date = new Date(0);
+ if (
+ !validateDate(year, month, day) ||
+ !validateDayOfYearDate(year, dayOfYear)
+ ) {
+ return new Date(NaN);
+ }
+ date.setUTCFullYear(year, month, Math.max(dayOfYear, day));
+ return date;
+ }
+}
+
+function parseDateUnit(value) {
+ return value ? parseInt(value) : 1;
+}
+
+function parseTime(timeString) {
+ const captures = timeString.match(timeRegex);
+ if (!captures) return NaN; // Invalid ISO-formatted time
+
+ const hours = parseTimeUnit(captures[1]);
+ const minutes = parseTimeUnit(captures[2]);
+ const seconds = parseTimeUnit(captures[3]);
+
+ if (!validateTime(hours, minutes, seconds)) {
+ return NaN;
+ }
+
+ return (
+ hours * _index.millisecondsInHour +
+ minutes * _index.millisecondsInMinute +
+ seconds * 1000
+ );
+}
+
+function parseTimeUnit(value) {
+ return (value && parseFloat(value.replace(",", "."))) || 0;
+}
+
+function parseTimezone(timezoneString) {
+ if (timezoneString === "Z") return 0;
+
+ const captures = timezoneString.match(timezoneRegex);
+ if (!captures) return 0;
+
+ const sign = captures[1] === "+" ? -1 : 1;
+ const hours = parseInt(captures[2]);
+ const minutes = (captures[3] && parseInt(captures[3])) || 0;
+
+ if (!validateTimezone(hours, minutes)) {
+ return NaN;
+ }
+
+ return (
+ sign *
+ (hours * _index.millisecondsInHour + minutes * _index.millisecondsInMinute)
+ );
+}
+
+function dayOfISOWeekYear(isoWeekYear, week, day) {
+ const date = new Date(0);
+ date.setUTCFullYear(isoWeekYear, 0, 4);
+ const fourthOfJanuaryDay = date.getUTCDay() || 7;
+ const diff = (week - 1) * 7 + day + 1 - fourthOfJanuaryDay;
+ date.setUTCDate(date.getUTCDate() + diff);
+ return date;
+}
+
+// Validation functions
+
+// February is null to handle the leap year (using ||)
+const daysInMonths = [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+
+function isLeapYearIndex(year) {
+ return year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0);
+}
+
+function validateDate(year, month, date) {
+ return (
+ month >= 0 &&
+ month <= 11 &&
+ date >= 1 &&
+ date <= (daysInMonths[month] || (isLeapYearIndex(year) ? 29 : 28))
+ );
+}
+
+function validateDayOfYearDate(year, dayOfYear) {
+ return dayOfYear >= 1 && dayOfYear <= (isLeapYearIndex(year) ? 366 : 365);
+}
+
+function validateWeekDate(_year, week, day) {
+ return week >= 1 && week <= 53 && day >= 0 && day <= 6;
+}
+
+function validateTime(hours, minutes, seconds) {
+ if (hours === 24) {
+ return minutes === 0 && seconds === 0;
+ }
+
+ return (
+ seconds >= 0 &&
+ seconds < 60 &&
+ minutes >= 0 &&
+ minutes < 60 &&
+ hours >= 0 &&
+ hours < 25
+ );
+}
+
+function validateTimezone(_hours, minutes) {
+ return minutes >= 0 && minutes <= 59;
+}
+
+
+/***/ }),
+
+/***/ 50135:
+/***/ ((__unused_webpack_module, exports) => {
+
+"use strict";
+
+exports.parseJSON = parseJSON; /**
+ * @name parseJSON
+ * @category Common Helpers
+ * @summary Parse a JSON date string
+ *
+ * @description
+ * Converts a complete ISO date string in UTC time, the typical format for transmitting
+ * a date in JSON, to a JavaScript `Date` instance.
+ *
+ * This is a minimal implementation for converting dates retrieved from a JSON API to
+ * a `Date` instance which can be used with other functions in the `date-fns` library.
+ * The following formats are supported:
+ *
+ * - `2000-03-15T05:20:10.123Z`: The output of `.toISOString()` and `JSON.stringify(new Date())`
+ * - `2000-03-15T05:20:10Z`: Without milliseconds
+ * - `2000-03-15T05:20:10+00:00`: With a zero offset, the default JSON encoded format in some other languages
+ * - `2000-03-15T05:20:10+05:45`: With a positive or negative offset, the default JSON encoded format in some other languages
+ * - `2000-03-15T05:20:10+0000`: With a zero offset without a colon
+ * - `2000-03-15T05:20:10`: Without a trailing 'Z' symbol
+ * - `2000-03-15T05:20:10.1234567`: Up to 7 digits in milliseconds field. Only first 3 are taken into account since JS does not allow fractional milliseconds
+ * - `2000-03-15 05:20:10`: With a space instead of a 'T' separator for APIs returning a SQL date without reformatting
+ *
+ * For convenience and ease of use these other input types are also supported
+ * via [toDate](https://date-fns.org/docs/toDate):
+ *
+ * - A `Date` instance will be cloned
+ * - A `number` will be treated as a timestamp
+ *
+ * Any other input type or invalid date strings will return an `Invalid Date`.
+ *
+ * @param dateStr - A fully formed ISO8601 date string to convert
+ *
+ * @returns The parsed date in the local time zone
+ */
+function parseJSON(dateStr) {
+ const parts = dateStr.match(
+ /(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2}):(\d{2})(?:\.(\d{0,7}))?(?:Z|(.)(\d{2}):?(\d{2})?)?/,
+ );
+ if (parts) {
+ // Group 8 matches the sign
+ return new Date(
+ Date.UTC(
+ +parts[1],
+ +parts[2] - 1,
+ +parts[3],
+ +parts[4] - (+parts[9] || 0) * (parts[8] == "-" ? -1 : 1),
+ +parts[5] - (+parts[10] || 0) * (parts[8] == "-" ? -1 : 1),
+ +parts[6],
+ +((parts[7] || "0") + "00").substring(0, 3),
+ ),
+ );
+ }
+ return new Date(NaN);
+}
+
+
/***/ }),
/***/ 5619:
@@ -43949,378 +44324,6 @@ function isLeapYearIndex(year) {
}
-/***/ }),
-
-/***/ 93822:
-/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
-
-"use strict";
-
-exports.parseISO = parseISO;
-var _index = __nccwpck_require__(17818);
-
-/**
- * The {@link parseISO} function options.
- */
-
-/**
- * @name parseISO
- * @category Common Helpers
- * @summary Parse ISO string
- *
- * @description
- * Parse the given string in ISO 8601 format and return an instance of Date.
- *
- * Function accepts complete ISO 8601 formats as well as partial implementations.
- * ISO 8601: http://en.wikipedia.org/wiki/ISO_8601
- *
- * If the argument isn't a string, the function cannot parse the string or
- * the values are invalid, it returns Invalid Date.
- *
- * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
- *
- * @param argument - The value to convert
- * @param options - An object with options
- *
- * @returns The parsed date in the local time zone
- *
- * @example
- * // Convert string '2014-02-11T11:30:30' to date:
- * const result = parseISO('2014-02-11T11:30:30')
- * //=> Tue Feb 11 2014 11:30:30
- *
- * @example
- * // Convert string '+02014101' to date,
- * // if the additional number of digits in the extended year format is 1:
- * const result = parseISO('+02014101', { additionalDigits: 1 })
- * //=> Fri Apr 11 2014 00:00:00
- */
-function parseISO(argument, options) {
- const additionalDigits = options?.additionalDigits ?? 2;
- const dateStrings = splitDateString(argument);
-
- let date;
- if (dateStrings.date) {
- const parseYearResult = parseYear(dateStrings.date, additionalDigits);
- date = parseDate(parseYearResult.restDateString, parseYearResult.year);
- }
-
- if (!date || isNaN(date.getTime())) {
- return new Date(NaN);
- }
-
- const timestamp = date.getTime();
- let time = 0;
- let offset;
-
- if (dateStrings.time) {
- time = parseTime(dateStrings.time);
- if (isNaN(time)) {
- return new Date(NaN);
- }
- }
-
- if (dateStrings.timezone) {
- offset = parseTimezone(dateStrings.timezone);
- if (isNaN(offset)) {
- return new Date(NaN);
- }
- } else {
- const dirtyDate = new Date(timestamp + time);
- // JS parsed string assuming it's in UTC timezone
- // but we need it to be parsed in our timezone
- // so we use utc values to build date in our timezone.
- // Year values from 0 to 99 map to the years 1900 to 1999
- // so set year explicitly with setFullYear.
- const result = new Date(0);
- result.setFullYear(
- dirtyDate.getUTCFullYear(),
- dirtyDate.getUTCMonth(),
- dirtyDate.getUTCDate(),
- );
- result.setHours(
- dirtyDate.getUTCHours(),
- dirtyDate.getUTCMinutes(),
- dirtyDate.getUTCSeconds(),
- dirtyDate.getUTCMilliseconds(),
- );
- return result;
- }
-
- return new Date(timestamp + time + offset);
-}
-
-const patterns = {
- dateTimeDelimiter: /[T ]/,
- timeZoneDelimiter: /[Z ]/i,
- timezone: /([Z+-].*)$/,
-};
-
-const dateRegex =
- /^-?(?:(\d{3})|(\d{2})(?:-?(\d{2}))?|W(\d{2})(?:-?(\d{1}))?|)$/;
-const timeRegex =
- /^(\d{2}(?:[.,]\d*)?)(?::?(\d{2}(?:[.,]\d*)?))?(?::?(\d{2}(?:[.,]\d*)?))?$/;
-const timezoneRegex = /^([+-])(\d{2})(?::?(\d{2}))?$/;
-
-function splitDateString(dateString) {
- const dateStrings = {};
- const array = dateString.split(patterns.dateTimeDelimiter);
- let timeString;
-
- // The regex match should only return at maximum two array elements.
- // [date], [time], or [date, time].
- if (array.length > 2) {
- return dateStrings;
- }
-
- if (/:/.test(array[0])) {
- timeString = array[0];
- } else {
- dateStrings.date = array[0];
- timeString = array[1];
- if (patterns.timeZoneDelimiter.test(dateStrings.date)) {
- dateStrings.date = dateString.split(patterns.timeZoneDelimiter)[0];
- timeString = dateString.substr(
- dateStrings.date.length,
- dateString.length,
- );
- }
- }
-
- if (timeString) {
- const token = patterns.timezone.exec(timeString);
- if (token) {
- dateStrings.time = timeString.replace(token[1], "");
- dateStrings.timezone = token[1];
- } else {
- dateStrings.time = timeString;
- }
- }
-
- return dateStrings;
-}
-
-function parseYear(dateString, additionalDigits) {
- const regex = new RegExp(
- "^(?:(\\d{4}|[+-]\\d{" +
- (4 + additionalDigits) +
- "})|(\\d{2}|[+-]\\d{" +
- (2 + additionalDigits) +
- "})$)",
- );
-
- const captures = dateString.match(regex);
- // Invalid ISO-formatted year
- if (!captures) return { year: NaN, restDateString: "" };
-
- const year = captures[1] ? parseInt(captures[1]) : null;
- const century = captures[2] ? parseInt(captures[2]) : null;
-
- // either year or century is null, not both
- return {
- year: century === null ? year : century * 100,
- restDateString: dateString.slice((captures[1] || captures[2]).length),
- };
-}
-
-function parseDate(dateString, year) {
- // Invalid ISO-formatted year
- if (year === null) return new Date(NaN);
-
- const captures = dateString.match(dateRegex);
- // Invalid ISO-formatted string
- if (!captures) return new Date(NaN);
-
- const isWeekDate = !!captures[4];
- const dayOfYear = parseDateUnit(captures[1]);
- const month = parseDateUnit(captures[2]) - 1;
- const day = parseDateUnit(captures[3]);
- const week = parseDateUnit(captures[4]);
- const dayOfWeek = parseDateUnit(captures[5]) - 1;
-
- if (isWeekDate) {
- if (!validateWeekDate(year, week, dayOfWeek)) {
- return new Date(NaN);
- }
- return dayOfISOWeekYear(year, week, dayOfWeek);
- } else {
- const date = new Date(0);
- if (
- !validateDate(year, month, day) ||
- !validateDayOfYearDate(year, dayOfYear)
- ) {
- return new Date(NaN);
- }
- date.setUTCFullYear(year, month, Math.max(dayOfYear, day));
- return date;
- }
-}
-
-function parseDateUnit(value) {
- return value ? parseInt(value) : 1;
-}
-
-function parseTime(timeString) {
- const captures = timeString.match(timeRegex);
- if (!captures) return NaN; // Invalid ISO-formatted time
-
- const hours = parseTimeUnit(captures[1]);
- const minutes = parseTimeUnit(captures[2]);
- const seconds = parseTimeUnit(captures[3]);
-
- if (!validateTime(hours, minutes, seconds)) {
- return NaN;
- }
-
- return (
- hours * _index.millisecondsInHour +
- minutes * _index.millisecondsInMinute +
- seconds * 1000
- );
-}
-
-function parseTimeUnit(value) {
- return (value && parseFloat(value.replace(",", "."))) || 0;
-}
-
-function parseTimezone(timezoneString) {
- if (timezoneString === "Z") return 0;
-
- const captures = timezoneString.match(timezoneRegex);
- if (!captures) return 0;
-
- const sign = captures[1] === "+" ? -1 : 1;
- const hours = parseInt(captures[2]);
- const minutes = (captures[3] && parseInt(captures[3])) || 0;
-
- if (!validateTimezone(hours, minutes)) {
- return NaN;
- }
-
- return (
- sign *
- (hours * _index.millisecondsInHour + minutes * _index.millisecondsInMinute)
- );
-}
-
-function dayOfISOWeekYear(isoWeekYear, week, day) {
- const date = new Date(0);
- date.setUTCFullYear(isoWeekYear, 0, 4);
- const fourthOfJanuaryDay = date.getUTCDay() || 7;
- const diff = (week - 1) * 7 + day + 1 - fourthOfJanuaryDay;
- date.setUTCDate(date.getUTCDate() + diff);
- return date;
-}
-
-// Validation functions
-
-// February is null to handle the leap year (using ||)
-const daysInMonths = [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
-
-function isLeapYearIndex(year) {
- return year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0);
-}
-
-function validateDate(year, month, date) {
- return (
- month >= 0 &&
- month <= 11 &&
- date >= 1 &&
- date <= (daysInMonths[month] || (isLeapYearIndex(year) ? 29 : 28))
- );
-}
-
-function validateDayOfYearDate(year, dayOfYear) {
- return dayOfYear >= 1 && dayOfYear <= (isLeapYearIndex(year) ? 366 : 365);
-}
-
-function validateWeekDate(_year, week, day) {
- return week >= 1 && week <= 53 && day >= 0 && day <= 6;
-}
-
-function validateTime(hours, minutes, seconds) {
- if (hours === 24) {
- return minutes === 0 && seconds === 0;
- }
-
- return (
- seconds >= 0 &&
- seconds < 60 &&
- minutes >= 0 &&
- minutes < 60 &&
- hours >= 0 &&
- hours < 25
- );
-}
-
-function validateTimezone(_hours, minutes) {
- return minutes >= 0 && minutes <= 59;
-}
-
-
-/***/ }),
-
-/***/ 50135:
-/***/ ((__unused_webpack_module, exports) => {
-
-"use strict";
-
-exports.parseJSON = parseJSON; /**
- * @name parseJSON
- * @category Common Helpers
- * @summary Parse a JSON date string
- *
- * @description
- * Converts a complete ISO date string in UTC time, the typical format for transmitting
- * a date in JSON, to a JavaScript `Date` instance.
- *
- * This is a minimal implementation for converting dates retrieved from a JSON API to
- * a `Date` instance which can be used with other functions in the `date-fns` library.
- * The following formats are supported:
- *
- * - `2000-03-15T05:20:10.123Z`: The output of `.toISOString()` and `JSON.stringify(new Date())`
- * - `2000-03-15T05:20:10Z`: Without milliseconds
- * - `2000-03-15T05:20:10+00:00`: With a zero offset, the default JSON encoded format in some other languages
- * - `2000-03-15T05:20:10+05:45`: With a positive or negative offset, the default JSON encoded format in some other languages
- * - `2000-03-15T05:20:10+0000`: With a zero offset without a colon
- * - `2000-03-15T05:20:10`: Without a trailing 'Z' symbol
- * - `2000-03-15T05:20:10.1234567`: Up to 7 digits in milliseconds field. Only first 3 are taken into account since JS does not allow fractional milliseconds
- * - `2000-03-15 05:20:10`: With a space instead of a 'T' separator for APIs returning a SQL date without reformatting
- *
- * For convenience and ease of use these other input types are also supported
- * via [toDate](https://date-fns.org/docs/toDate):
- *
- * - A `Date` instance will be cloned
- * - A `number` will be treated as a timestamp
- *
- * Any other input type or invalid date strings will return an `Invalid Date`.
- *
- * @param dateStr - A fully formed ISO8601 date string to convert
- *
- * @returns The parsed date in the local time zone
- */
-function parseJSON(dateStr) {
- const parts = dateStr.match(
- /(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2}):(\d{2})(?:\.(\d{0,7}))?(?:Z|(.)(\d{2}):?(\d{2})?)?/,
- );
- if (parts) {
- // Group 8 matches the sign
- return new Date(
- Date.UTC(
- +parts[1],
- +parts[2] - 1,
- +parts[3],
- +parts[4] - (+parts[9] || 0) * (parts[8] == "-" ? -1 : 1),
- +parts[5] - (+parts[10] || 0) * (parts[8] == "-" ? -1 : 1),
- +parts[6],
- +((parts[7] || "0") + "00").substring(0, 3),
- ),
- );
- }
- return new Date(NaN);
-}
-
-
/***/ }),
/***/ 456:
diff --git a/package-lock.json b/package-lock.json
index e84f57c6..995345e3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3122,9 +3122,9 @@
}
},
"node_modules/cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
"dependencies": {
"path-key": "^3.1.0",
diff --git a/src/action/decorate/summary.ts b/src/action/decorate/summary.ts
index 95ba7181..523e875b 100644
--- a/src/action/decorate/summary.ts
+++ b/src/action/decorate/summary.ts
@@ -20,6 +20,8 @@ import {
import { generateExpandableAreaMarkdown, generateStatusMarkdown } from './markdown';
import { githubConfig, ticsConfig } from '../../configuration/config';
+const capitalize = (s: string): string => s && String(s[0]).toUpperCase() + String(s).slice(1);
+
export function createSummaryBody(analysisResult: AnalysisResult): string {
logger.header('Creating summary.');
summary.addHeading('TICS Quality Gate');
@@ -37,7 +39,7 @@ export function createSummaryBody(analysisResult: AnalysisResult): string {
if (condition.details && condition.details.items.length > 0) {
summary.addRaw(`${EOL}${statusMarkdown}${condition.message}
${EOL}`);
summary.addBreak();
- summary.addTable(createConditionTable(condition.details));
+ createConditionTables(condition.details).forEach(table => summary.addTable(table));
summary.addRaw(' ', true);
} else {
summary.addRaw(`${EOL} ${statusMarkdown}${condition.message}`, true);
@@ -174,43 +176,45 @@ export function createFilesSummary(fileList: string[]): string {
* @param conditions Conditions of the quality gate
* @returns Table containing a summary for all conditions
*/
-function createConditionTable(details: ConditionDetails): SummaryTableRow[] {
- const rows: SummaryTableRow[] = [];
- const titleRow: SummaryTableRow = [
- {
- data: 'File',
- header: true
- },
- {
- data: details.dataKeys.actualValue.title,
- header: true
- }
- ];
- if (details.dataKeys.blockingAfter) {
- titleRow.push({
- data: details.dataKeys.blockingAfter.title,
- header: true
- });
- }
- rows.push(titleRow);
-
- details.items
- .filter(item => item.itemType === 'file')
- .forEach(item => {
- const dataRow: SummaryTableRow = [
- `${EOL}${EOL}[${item.name}](${joinUrl(ticsConfig.displayUrl, item.link)})${EOL}${EOL}`,
- item.data.actualValue.formattedValue
- ];
-
- if (item.data.blockingAfter) {
- dataRow.push(item.data.blockingAfter.formattedValue);
- } else if (details.dataKeys.blockingAfter) {
- dataRow.push('0');
+function createConditionTables(details: ConditionDetails): SummaryTableRow[][] {
+ return details.itemTypes.map(itemType => {
+ const rows: SummaryTableRow[] = [];
+ const titleRow: SummaryTableRow = [
+ {
+ data: capitalize(itemType),
+ header: true
+ },
+ {
+ data: details.dataKeys.actualValue.title,
+ header: true
}
+ ];
+ if (details.dataKeys.blockingAfter) {
+ titleRow.push({
+ data: details.dataKeys.blockingAfter.title,
+ header: true
+ });
+ }
+ rows.push(titleRow);
+
+ details.items
+ .filter(item => item.itemType === itemType)
+ .forEach(item => {
+ const dataRow: SummaryTableRow = [
+ `${EOL}${EOL}[${item.name}](${joinUrl(ticsConfig.displayUrl, item.link)})${EOL}${EOL}`,
+ item.data.actualValue.formattedValue
+ ];
+
+ if (item.data.blockingAfter) {
+ dataRow.push(item.data.blockingAfter.formattedValue);
+ } else if (details.dataKeys.blockingAfter) {
+ dataRow.push('0');
+ }
- rows.push(dataRow);
- });
- return rows;
+ rows.push(dataRow);
+ });
+ return rows;
+ });
}
/**
diff --git a/test/unit/action/decorate/objects/summary.ts b/test/unit/action/decorate/objects/summary.ts
index d9299b02..bbd1dd30 100644
--- a/test/unit/action/decorate/objects/summary.ts
+++ b/test/unit/action/decorate/objects/summary.ts
@@ -47,7 +47,7 @@ export const analysisResultsSoaked: AnalysisResult = {
message:
'No new Coding Standard Violations for levels 1, 2, 3 with respect to first analysis; failed for 145 files. There will be blocking issues in 138 files after the grace period ends.',
details: {
- itemTypes: ['file'],
+ itemTypes: ['file', 'function'],
dataKeys: {
actualValue: {
title: 'Blocking now',
@@ -119,6 +119,25 @@ export const analysisResultsSoaked: AnalysisResult = {
link: 'AnnotatedSource.html#axes\u003dSuppressions(no),Date(1516070506),Project(20065),Level(Set(1,2,3)),DeltaDate(Run(0)),DiffType(new),File(Path(HIE,20065,main,PADAnalysis,ApplicationNative,src,views,AboutBox.cpp)),Blocking(deferred)\u0026diff\u003dtrue\u0026metrics\u003dG(Diff(CS,DiffType(new)),Level(Set(1,2,3)))'
}
}
+ },
+ {
+ itemType: 'function',
+ name: 'PADAnalysis/ApplicationNative/src/views/AboutBoxs.cpp',
+ link: 'AnnotatedSource.html#axes\u003dSuppressions(no),Date(1516070506),Project(20065),Level(Set(1,2,3)),DeltaDate(Run(0)),DiffType(new),File(Path(HIE,20065,main,PADAnalysis,ApplicationNative,src,views,AboutBox.cpp))\u0026diff\u003dtrue\u0026metrics\u003dG(Diff(CS,DiffType(new)),Level(Set(1,2,3)))',
+ data: {
+ actualValue: {
+ formattedValue: '+25',
+ value: 24.0,
+ classes: ['delta-worse'],
+ link: 'AnnotatedSource.html#axes\u003dSuppressions(no),Date(1516070506),Project(20065),Level(Set(1,2,3)),DeltaDate(Run(0)),DiffType(new),File(Path(HIE,20065,main,PADAnalysis,ApplicationNative,src,views,AboutBox.cpp)),Blocking(Set(yes,no))\u0026diff\u003dtrue\u0026metrics\u003dG(Diff(CS,DiffType(new)),Level(Set(1,2,3)))'
+ },
+ blockingAfter: {
+ formattedValue: '0',
+ value: 0.0,
+ classes: [],
+ link: 'AnnotatedSource.html#axes\u003dSuppressions(no),Date(1516070506),Project(20065),Level(Set(1,2,3)),DeltaDate(Run(0)),DiffType(new),File(Path(HIE,20065,main,PADAnalysis,ApplicationNative,src,views,AboutBox.cpp)),Blocking(deferred)\u0026diff\u003dtrue\u0026metrics\u003dG(Diff(CS,DiffType(new)),Level(Set(1,2,3)))'
+ }
+ }
}
]
}
diff --git a/test/unit/action/decorate/summary.test.ts b/test/unit/action/decorate/summary.test.ts
index d5440bc8..cae9212a 100644
--- a/test/unit/action/decorate/summary.test.ts
+++ b/test/unit/action/decorate/summary.test.ts
@@ -36,6 +36,8 @@ describe('createSummaryBody', () => {
expect(string).toContain('
+39 | +3 | ');
expect(string).toContain(' | +30 | 0 |
');
expect(string).toContain(' | +24 | 0 |
');
+ expect(string).toContain('Function | Blocking now | Blocking after 2018-03-23 |
');
+ expect(string).toContain('+25 | 0 | ');
summary.clear();
});
From d5538c295a67d6c759a145e1a0daaece18afe107 Mon Sep 17 00:00:00 2001
From: janssen <118828444+janssen-tiobe@users.noreply.github.com>
Date: Wed, 4 Dec 2024 17:28:03 +0100
Subject: [PATCH 2/2] #35462: Do not post undefined items in unpostable
annotations
---
dist/index.js | 5 ++++-
src/action/decorate/summary.ts | 5 ++++-
test/unit/action/decorate/summary.test.ts | 12 +++++-------
3 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/dist/index.js b/dist/index.js
index 1c5d48d2..24c35c61 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -536,7 +536,10 @@ function createUnpostableAnnotationsDetails(unpostableReviewComments) {
else if (previousPath !== path) {
body += `${path} |
`;
}
- body += `${icon} | ${blocking} | Line: ${reviewComment.line.toString()} Level: ${reviewComment.level?.toString() ?? ''} Category: ${reviewComment.category ?? ''} | ${reviewComment.type} violation: ${reviewComment.rule ?? ''} ${displayCount} ${reviewComment.msg} |
`;
+ body += `${icon} | ${blocking} | Line: ${reviewComment.line.toString()}`;
+ body += reviewComment.level ? ` Level: ${reviewComment.level.toString()}` : '';
+ body += reviewComment.category ? ` Category: ${reviewComment.category}` : '';
+ body += ` | ${reviewComment.type} violation: ${reviewComment.rule ?? ''} ${displayCount} ${reviewComment.msg} |
`;
previousPath = reviewComment.path ? reviewComment.path : '';
});
body += '
';
diff --git a/src/action/decorate/summary.ts b/src/action/decorate/summary.ts
index 523e875b..1d62f523 100644
--- a/src/action/decorate/summary.ts
+++ b/src/action/decorate/summary.ts
@@ -397,7 +397,10 @@ export function createUnpostableAnnotationsDetails(unpostableReviewComments: Ext
} else if (previousPath !== path) {
body += `${path} |
`;
}
- body += `${icon} | ${blocking} | Line: ${reviewComment.line.toString()} Level: ${reviewComment.level?.toString() ?? ''} Category: ${reviewComment.category ?? ''} | ${reviewComment.type} violation: ${reviewComment.rule ?? ''} ${displayCount} ${reviewComment.msg} |
`;
+ body += `${icon} | ${blocking} | Line: ${reviewComment.line.toString()}`;
+ body += reviewComment.level ? ` Level: ${reviewComment.level.toString()}` : '';
+ body += reviewComment.category ? ` Category: ${reviewComment.category}` : '';
+ body += ` | ${reviewComment.type} violation: ${reviewComment.rule ?? ''} ${displayCount} ${reviewComment.msg} |
`;
previousPath = reviewComment.path ? reviewComment.path : '';
});
body += '
';
diff --git a/test/unit/action/decorate/summary.test.ts b/test/unit/action/decorate/summary.test.ts
index cae9212a..b94ebf08 100644
--- a/test/unit/action/decorate/summary.test.ts
+++ b/test/unit/action/decorate/summary.test.ts
@@ -583,7 +583,7 @@ describe('createUnpostableReviewCommentsSummary', () => {
const response = createUnpostableAnnotationsDetails(unpostable);
expect(response).toContain(`${unpostable[0].path} |
`);
expect(response).toContain(
- `:x: | Blocking | Line: ${unpostable[0].line} Level: ${unpostable[0].level} Category: ${unpostable[0].category} | ${unpostable[0].type} violation: ${unpostable[0].rule} ${unpostable[0].displayCount} ${unpostable[0].msg} |
`
+ `:x: | Blocking | Line: ${unpostable[0].line} Level: ${unpostable[0].level} Category: ${unpostable[0].category} | ${unpostable[0].type} violation: ${unpostable[0].rule} ${unpostable[0].displayCount} ${unpostable[0].msg} |
`
);
});
@@ -622,7 +622,7 @@ describe('createUnpostableReviewCommentsSummary', () => {
const response = createUnpostableAnnotationsDetails(unpostable);
expect(response).toContainTimes(`${unpostable[0].path} |
`, 1);
expect(response).toContainTimes(
- `:x: | Blocking | Line: ${unpostable[0].line} Level: ${unpostable[0].level} Category: ${unpostable[0].category} | ${unpostable[0].type} violation: ${unpostable[0].rule} ${unpostable[0].displayCount} ${unpostable[0].msg} |
`,
+ `:x: | Blocking | Line: ${unpostable[0].line} Level: ${unpostable[0].level} Category: ${unpostable[0].category} | ${unpostable[0].type} violation: ${unpostable[0].rule} ${unpostable[0].displayCount} ${unpostable[0].msg} |
`,
2
);
});
@@ -662,7 +662,7 @@ describe('createUnpostableReviewCommentsSummary', () => {
const response = createUnpostableAnnotationsDetails(unpostable);
expect(response).toContainTimes(`${unpostable[0].path} |
`, 1);
expect(response).toContainTimes(
- `:x: | Blocking | Line: ${unpostable[0].line} Level: ${unpostable[0].level} Category: ${unpostable[0].category} | ${unpostable[0].type} violation: ${unpostable[0].rule} ${unpostable[0].displayCount} ${unpostable[0].msg} |
`,
+ `:x: | Blocking | Line: ${unpostable[0].line} Level: ${unpostable[0].level} Category: ${unpostable[0].category} | ${unpostable[0].type} violation: ${unpostable[0].rule} ${unpostable[0].displayCount} ${unpostable[0].msg} |
`,
2
);
});
@@ -687,8 +687,6 @@ describe('createUnpostableReviewCommentsSummary', () => {
fullPath: '/home/src/test.js',
path: 'src/test.js',
line: 0,
- level: 1,
- category: 'test',
type: 'test',
rule: 'test',
displayCount: '',
@@ -707,11 +705,11 @@ describe('createUnpostableReviewCommentsSummary', () => {
expect(response).toContainTimes(`${unpostable[0].path} |
`, 1);
expect(response).toContainTimes(`${unpostable[1].path} |
`, 1);
expect(response).toContainTimes(
- `:x: | Blocking | Line: ${unpostable[0].line} Level: ${unpostable[0].level} Category: ${unpostable[0].category} | ${unpostable[0].type} violation: ${unpostable[0].rule} ${unpostable[0].displayCount} ${unpostable[0].msg} |
`,
+ `:x: | Blocking | Line: ${unpostable[0].line} Level: ${unpostable[0].level} Category: ${unpostable[0].category} | ${unpostable[0].type} violation: ${unpostable[0].rule} ${unpostable[0].displayCount} ${unpostable[0].msg} |
`,
1
);
expect(response).toContainTimes(
- `:warning: | Blocking after 2024-08-16 | Line: ${unpostable[0].line} Level: ${unpostable[0].level} Category: ${unpostable[0].category} | ${unpostable[0].type} violation: ${unpostable[0].rule} ${unpostable[0].displayCount} ${unpostable[0].msg} |
`,
+ `:warning: | Blocking after 2024-08-16 | Line: ${unpostable[1].line} | ${unpostable[1].type} violation: ${unpostable[1].rule} ${unpostable[1].displayCount} ${unpostable[1].msg} |
`,
1
);
});