@s-ui/lint-reporters
Version:
Send lint errors and golden path metrics to DataDog
369 lines (361 loc) • 14.2 kB
JavaScript
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
// src/sui-lint-repository-reporter.ts
var sui_lint_repository_reporter_exports = {};
__export(sui_lint_repository_reporter_exports, {
RepositoryReporter: () => RepositoryReporter
});
module.exports = __toCommonJS(sui_lint_repository_reporter_exports);
// src/Reporter.ts
var import_child_process = require("child_process");
var import_util = require("util");
// src/Sender/HTTPSender.ts
var import_node_https = __toESM(require("https"));
// ../../node_modules/ts-pattern/dist/index.js
var t = Symbol.for("@ts-pattern/matcher");
var e = Symbol.for("@ts-pattern/isVariadic");
var n = "@ts-pattern/anonymous-select-key";
var r = (t2) => Boolean(t2 && "object" == typeof t2);
var i = (e2) => e2 && !!e2[t];
var o = (n2, s2, c2) => {
if (i(n2)) {
const e2 = n2[t](), { matched: r2, selections: i2 } = e2.match(s2);
return r2 && i2 && Object.keys(i2).forEach((t2) => c2(t2, i2[t2])), r2;
}
if (r(n2)) {
if (!r(s2))
return false;
if (Array.isArray(n2)) {
if (!Array.isArray(s2))
return false;
let t2 = [], r2 = [], a = [];
for (const o2 of n2.keys()) {
const s3 = n2[o2];
i(s3) && s3[e] ? a.push(s3) : a.length ? r2.push(s3) : t2.push(s3);
}
if (a.length) {
if (a.length > 1)
throw new Error("Pattern error: Using `...P.array(...)` several times in a single pattern is not allowed.");
if (s2.length < t2.length + r2.length)
return false;
const e2 = s2.slice(0, t2.length), n3 = 0 === r2.length ? [] : s2.slice(-r2.length), i2 = s2.slice(t2.length, 0 === r2.length ? Infinity : -r2.length);
return t2.every((t3, n4) => o(t3, e2[n4], c2)) && r2.every((t3, e3) => o(t3, n3[e3], c2)) && (0 === a.length || o(a[0], i2, c2));
}
return n2.length === s2.length && n2.every((t3, e2) => o(t3, s2[e2], c2));
}
return Object.keys(n2).every((e2) => {
const r2 = n2[e2];
return (e2 in s2 || i(a = r2) && "optional" === a[t]().matcherType) && o(r2, s2[e2], c2);
var a;
});
}
return Object.is(s2, n2);
};
var s = (e2) => {
var n2, o2, a;
return r(e2) ? i(e2) ? null != (n2 = null == (o2 = (a = e2[t]()).getSelectionKeys) ? void 0 : o2.call(a)) ? n2 : [] : Array.isArray(e2) ? c(e2, s) : c(Object.values(e2), s) : [];
};
var c = (t2, e2) => t2.reduce((t3, n2) => t3.concat(e2(n2)), []);
function u(t2) {
return Object.assign(t2, { optional: () => l(t2), and: (e2) => m(t2, e2), or: (e2) => d(t2, e2), select: (e2) => void 0 === e2 ? p(t2) : p(e2, t2) });
}
function l(e2) {
return u({ [t]: () => ({ match: (t2) => {
let n2 = {};
const r2 = (t3, e3) => {
n2[t3] = e3;
};
return void 0 === t2 ? (s(e2).forEach((t3) => r2(t3, void 0)), { matched: true, selections: n2 }) : { matched: o(e2, t2, r2), selections: n2 };
}, getSelectionKeys: () => s(e2), matcherType: "optional" }) });
}
function m(...e2) {
return u({ [t]: () => ({ match: (t2) => {
let n2 = {};
const r2 = (t3, e3) => {
n2[t3] = e3;
};
return { matched: e2.every((e3) => o(e3, t2, r2)), selections: n2 };
}, getSelectionKeys: () => c(e2, s), matcherType: "and" }) });
}
function d(...e2) {
return u({ [t]: () => ({ match: (t2) => {
let n2 = {};
const r2 = (t3, e3) => {
n2[t3] = e3;
};
return c(e2, s).forEach((t3) => r2(t3, void 0)), { matched: e2.some((e3) => o(e3, t2, r2)), selections: n2 };
}, getSelectionKeys: () => c(e2, s), matcherType: "or" }) });
}
function y(e2) {
return { [t]: () => ({ match: (t2) => ({ matched: Boolean(e2(t2)) }) }) };
}
function p(...e2) {
const r2 = "string" == typeof e2[0] ? e2[0] : void 0, i2 = 2 === e2.length ? e2[1] : "string" == typeof e2[0] ? void 0 : e2[0];
return u({ [t]: () => ({ match: (t2) => {
let e3 = { [null != r2 ? r2 : n]: t2 };
return { matched: void 0 === i2 || o(i2, t2, (t3, n2) => {
e3[t3] = n2;
}), selections: e3 };
}, getSelectionKeys: () => [null != r2 ? r2 : n].concat(void 0 === i2 ? [] : s(i2)) }) });
}
function v(t2) {
return "number" == typeof t2;
}
function b(t2) {
return "string" == typeof t2;
}
function w(t2) {
return "bigint" == typeof t2;
}
var S = u(y(function(t2) {
return true;
}));
var j = (t2) => Object.assign(u(t2), { startsWith: (e2) => {
return j(m(t2, (n2 = e2, y((t3) => b(t3) && t3.startsWith(n2)))));
var n2;
}, endsWith: (e2) => {
return j(m(t2, (n2 = e2, y((t3) => b(t3) && t3.endsWith(n2)))));
var n2;
}, minLength: (e2) => j(m(t2, ((t3) => y((e3) => b(e3) && e3.length >= t3))(e2))), maxLength: (e2) => j(m(t2, ((t3) => y((e3) => b(e3) && e3.length <= t3))(e2))), includes: (e2) => {
return j(m(t2, (n2 = e2, y((t3) => b(t3) && t3.includes(n2)))));
var n2;
}, regex: (e2) => {
return j(m(t2, (n2 = e2, y((t3) => b(t3) && Boolean(t3.match(n2))))));
var n2;
} });
var E = j(y(b));
var K = (t2) => Object.assign(u(t2), { between: (e2, n2) => K(m(t2, ((t3, e3) => y((n3) => v(n3) && t3 <= n3 && e3 >= n3))(e2, n2))), lt: (e2) => K(m(t2, ((t3) => y((e3) => v(e3) && e3 < t3))(e2))), gt: (e2) => K(m(t2, ((t3) => y((e3) => v(e3) && e3 > t3))(e2))), lte: (e2) => K(m(t2, ((t3) => y((e3) => v(e3) && e3 <= t3))(e2))), gte: (e2) => K(m(t2, ((t3) => y((e3) => v(e3) && e3 >= t3))(e2))), int: () => K(m(t2, y((t3) => v(t3) && Number.isInteger(t3)))), finite: () => K(m(t2, y((t3) => v(t3) && Number.isFinite(t3)))), positive: () => K(m(t2, y((t3) => v(t3) && t3 > 0))), negative: () => K(m(t2, y((t3) => v(t3) && t3 < 0))) });
var x = K(y(v));
var A = (t2) => Object.assign(u(t2), { between: (e2, n2) => A(m(t2, ((t3, e3) => y((n3) => w(n3) && t3 <= n3 && e3 >= n3))(e2, n2))), lt: (e2) => A(m(t2, ((t3) => y((e3) => w(e3) && e3 < t3))(e2))), gt: (e2) => A(m(t2, ((t3) => y((e3) => w(e3) && e3 > t3))(e2))), lte: (e2) => A(m(t2, ((t3) => y((e3) => w(e3) && e3 <= t3))(e2))), gte: (e2) => A(m(t2, ((t3) => y((e3) => w(e3) && e3 >= t3))(e2))), positive: () => A(m(t2, y((t3) => w(t3) && t3 > 0))), negative: () => A(m(t2, y((t3) => w(t3) && t3 < 0))) });
var P = A(y(w));
var T = u(y(function(t2) {
return "boolean" == typeof t2;
}));
var k = u(y(function(t2) {
return "symbol" == typeof t2;
}));
var B = u(y(function(t2) {
return null == t2;
}));
var _ = u(y(function(t2) {
return null != t2;
}));
var W = { matched: false, value: void 0 };
function $(t2) {
return new z(t2, W);
}
var z = class {
constructor(t2, e2) {
this.input = void 0, this.state = void 0, this.input = t2, this.state = e2;
}
with(...t2) {
if (this.state.matched)
return this;
const e2 = t2[t2.length - 1], r2 = [t2[0]];
let i2;
3 === t2.length && "function" == typeof t2[1] ? i2 = t2[1] : t2.length > 2 && r2.push(...t2.slice(1, t2.length - 1));
let s2 = false, c2 = {};
const a = (t3, e3) => {
s2 = true, c2[t3] = e3;
}, u2 = !r2.some((t3) => o(t3, this.input, a)) || i2 && !Boolean(i2(this.input)) ? W : { matched: true, value: e2(s2 ? n in c2 ? c2[n] : c2 : this.input, this.input) };
return new z(this.input, u2);
}
when(t2, e2) {
if (this.state.matched)
return this;
const n2 = Boolean(t2(this.input));
return new z(this.input, n2 ? { matched: true, value: e2(this.input, this.input) } : W);
}
otherwise(t2) {
return this.state.matched ? this.state.value : t2(this.input);
}
exhaustive() {
if (this.state.matched)
return this.state.value;
let t2;
try {
t2 = JSON.stringify(this.input);
} catch (e2) {
t2 = this.input;
}
throw new Error(`Pattern matching error: no pattern matches value ${t2}`);
}
run() {
return this.exhaustive();
}
returnType() {
return this;
}
};
// src/Sender/HTTPSender.ts
var ONE_SECOND = 1e3;
var delay = async (ms) => new Promise((resolve) => setTimeout(resolve, ms));
var { MS_URL = "ms-common--metrics.es-global-pro.schip.io", BASIC_AUTH } = process.env;
var HTTPSender = class {
static create() {
return new HTTPSender();
}
async send(signals) {
if (!signals || signals.length === 0)
return this.log("\u{1F621} Sorry but there are not signals to send");
const body = signals.map(
(signal) => $(signal).with({ type: "repository" }, (p2) => ({ rule: p2.rule, value: p2.value, type: p2.type })).with({ type: "js" }, (p2) => ({ rule: p2.ruleName, value: p2.numberOfFails, type: p2.type })).exhaustive()
);
this.log("\u{1F680} Sending the metric to the microservice.");
const ok = await this.request(body);
if (ok)
this.log("\u{1F913} The metric has been successfully sent to the microservice.");
if (!ok) {
this.log("\u{1F605} The initial attempt to send the metric has failed. We will retry in 1 second.");
await delay(ONE_SECOND);
$(await this.request(body)).with(true, () => this.log("\u{1F60F} The retry attempt to send the metric has worked successfully.")).with(
false,
() => this.log(
"\u{1F621} Sorry, but the second retry attempt to send the metric has also failed. We will not attempt again, and the metric will be lost forever."
)
);
}
return void 0;
}
log(...msg) {
console.log.apply(console, msg);
}
async request(body) {
if (BASIC_AUTH === void 0) {
this.log("\u274C BASIC_AUTH env var shouldnt be undefined");
process.exit(1);
}
const bodyReq = {
metrics: [
{
name: "metrics.frontend.discipline",
organisationName: process.env.GITHUB_REPOSITORY_OWNER,
repositoryId: process.env.GITHUB_REPOSITORY_ID,
tags: body.map((bodyJSON) => ({
tagSetId: $(bodyJSON.type).with("repository", (p2) => "global.metrics.frontend.repository").with("js", (p2) => "global.metrics.frontend.code").exhaustive(),
key: bodyJSON.rule,
value: bodyJSON.value
}))
}
]
};
return new Promise((resolve, _reject) => {
const options = {
hostname: MS_URL,
port: 443,
path: "/v2/ci-metrics",
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(JSON.stringify(bodyReq)),
Authorization: "Basic " + BASIC_AUTH
}
};
const req = import_node_https.default.request(options, (res) => {
this.log(`STATUS: ${res.statusCode}`);
this.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding("utf8");
res.on("data", (chunk) => {
this.log(`BODY: ${chunk}`);
});
res.on("end", () => {
this.log("No more data in response.");
const isSuccess = res.statusCode && res.statusCode >= 200 && res.statusCode < 300;
resolve(Boolean(isSuccess));
});
});
req.on("error", (e2) => {
this.log(`problem with request: ${e2.message}`);
resolve(false);
});
this.log("Body:\n\n", JSON.stringify(bodyReq, null, 2), "\n\n");
req.write(JSON.stringify(bodyReq));
req.end();
});
}
};
// src/Reporter.ts
var exec = (0, import_util.promisify)(import_child_process.exec);
var Reporter = class {
constructor() {
__publicField(this, "sender", HTTPSender.create());
}
async _isMaster() {
let branch = await exec("git rev-parse --abbrev-ref HEAD").catch(() => "UNKNOW_BRANCH");
if (typeof branch !== "string") {
branch = branch.stdout;
}
return branch.trim() === "master" || branch.trim() === "main";
}
async _getRepository() {
var _a;
let url = await exec("git config --get remote.origin.url").catch(() => "git@github.com:sui/remote-url.git");
if (typeof url !== "string") {
url = url.stdout;
}
const cleanUrl = url.trim().replace("\n", "");
const isHttp = cleanUrl.startsWith("https://");
if (isHttp) {
return (_a = cleanUrl.split("/")[4]) == null ? void 0 : _a.replace(".git", "");
} else {
const [, address] = cleanUrl.split("@");
return address.split("/")[1].replace(".git", "");
}
}
};
// src/sui-lint-repository-reporter.ts
var RepositoryReporter = class extends Reporter {
constructor() {
super(...arguments);
__publicField(this, "data");
}
static create() {
return new RepositoryReporter();
}
map(results) {
this.data = results.monitorings;
return this;
}
async send() {
if (this.data === void 0) {
throw new Error("[sui-lint] No data to send. Maybe you must call to map before");
}
if (!await this._isMaster()) {
return console.log("[sui-lint] Reporters only will happen in MASTER branch.");
}
const signals = this.data.map((signal) => {
return { ...signal, type: "repository" };
});
await this.sender.send(signals);
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
RepositoryReporter
});