Skip to content

Commit

Permalink
Merge pull request #48 from deven-org/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
pixari authored Mar 17, 2023
2 parents 3fccce4 + 15140b5 commit f93a4bf
Show file tree
Hide file tree
Showing 21 changed files with 958 additions and 62 deletions.
2 changes: 1 addition & 1 deletion netlify/functions/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const handler: Handler = async (event: HandlerEvent) => {
try {
const eventSignature = event.headers["x-github-event"] || "unknown";
const body = getEventBody(event);
await collectMetricsHandler({ ...body, eventSignature });
await collectMetricsHandler({ eventSignature, ...body });
return {
statusCode: 200,
body: "success",
Expand Down
3 changes: 2 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

97 changes: 82 additions & 15 deletions src/__tests__/handler.test.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,99 @@
import * as moduleAddSignature from "../core/addSignature";
import * as moduleCollectMetrics from "../core/collectMetrics";
import * as moduleStoreData from "../core/storeData";
import { handler } from "../handler";
import mergedCompletedSuccessfully from "./fixtures/merged-completed-successful.json";
import { logger } from "../core/logger";
import { DataEventSignature } from "../interfaces";
import { LogErrors, LogWarnings } from "../shared/logMessages";

describe("Handler", () => {
beforeEach(() => {});
jest.mock("../core/logger", () => ({
__esModule: true,
logger: {
start: jest.fn(),
config: jest.fn(),
info: jest.fn(),
warning: jest.fn(),
error: jest.fn(),
complete: jest.fn(),
},
}));

afterEach(() => {});
const spyOnAddSignature = jest.spyOn(moduleAddSignature, "addSignature");
const spyOnCollectMetrics = jest.spyOn(moduleCollectMetrics, "collectMetrics");
const spyOnStoreData = jest.spyOn(moduleCollectMetrics, "collectMetrics");

it.only("returns the payload enhanced with relative matrix", async () => {
const data = {
signature: "packages",
describe("handler", () => {
it("calls addSignature passing the given event payload", async () => {
const event = {
foo: "foo",
bar: "bar",
eventSignature: "toolingUsage",
};
const output = await handler(data);
await handler(event);
expect(spyOnAddSignature).toBeCalledWith({
bar: "bar",
foo: "foo",
eventSignature: "toolingUsage",
});
});
it("calls collectMetrics passing a signed event, given that the event is known", async () => {
const event = {
foo: "foo",
bar: "bar",
eventSignature: "toolingUsage",
};

await handler(event);

expect(output).toMatchObject({
expect(spyOnCollectMetrics).toBeCalledWith({
created_at: expect.any(Number),
output: data,
dataEventSignature: "packages",
dataEventSignature: "deven-tooling-usage",
owner: "",
repo: "",
output: {},
payload: {
foo: "foo",
bar: "bar",
eventSignature: "toolingUsage",
},
});
});

it("...", async () => {
const output = await handler(mergedCompletedSuccessfully);
it("doesn't call collectMetrics if the event is unknown", async () => {
const event = {
foo: "foo",
bar: "bar",
eventSignature: "foo",
};

await handler(event);

expect(spyOnCollectMetrics).not.toBeCalled();
expect(logger.warning).toBeCalledWith(
LogWarnings.signingEventSignatureNotRecognized
);
});

it("calls storeData passing an enhanced data event, given that the metrics can be collects", async () => {
const event = {
foo: "foo",
bar: "bar",
eventSignature: "toolingUsage",
};

await handler(event);

expect(output).toMatchObject({
expect(spyOnStoreData).toBeCalledWith({
created_at: expect.any(Number),
dataEventSignature: "merged-pr",
dataEventSignature: "deven-tooling-usage",
output: {},
owner: "",
payload: {
bar: "bar",
eventSignature: "toolingUsage",
foo: "foo",
},
repo: "",
});
});
});
4 changes: 2 additions & 2 deletions src/__tests__/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ const dotenv = require("dotenv");

global.console = {
...console,
//log: jest.fn(),
// log: jest.fn(),
debug: jest.fn(),
info: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
// error: jest.fn(),
};

dotenv.config({ path: ".test.env" });
28 changes: 15 additions & 13 deletions src/core/addSignature.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { createDataEvent, Errors, getRejectionReason, logger } from ".";
import { cond, T, always, pipe, clone } from "ramda";
import { isWorkflowJobCompleted } from "./signingConditions";
import { LogInfos } from "../shared/logMessages";
import { createDataEvent, getRejectionReason, logger } from ".";
import { cond, pipe, clone, T, always } from "ramda";
import { LogInfos, LogWarnings } from "../shared/logMessages";
import { DataEventSignature, DataEvent } from "../interfaces";
import { isPullRequestClosed } from "../metrics/pull_requests/signatureConditions";
import signatureConditions from "../signatureConditions";

const createSignedDataEvent =
Expand All @@ -14,25 +12,29 @@ const createSignedDataEvent =
dataEventSignature: signature,
output: {},
payload: data,
owner: "",
repo: "",
});
};

const signDataEvent = cond(
signatureConditions.map((cond) => [
cond[0],
createSignedDataEvent(cond[1] as DataEventSignature),
])
);
const signDataEvent = cond([
...signatureConditions.map((item) => [
item[0],
createSignedDataEvent(item[1]),
]),
[T, always(false)],
]);

export const addSignature = (data: any): Promise<DataEvent> => {
return new Promise((res, rej) => {
const signedDataEvent = pipe(clone, signDataEvent)(data);

signedDataEvent
? res(signedDataEvent)
: rej(
getRejectionReason({
level: "warn",
message: Errors.signingEventSignatureNotRecognized,
level: "warning",
message: LogWarnings.signingEventSignatureNotRecognized,
})
);
});
Expand Down
9 changes: 5 additions & 4 deletions src/metrics/collectMetrics.ts → src/core/collectMetrics.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { getRejectionReason } from "../core";
import { logger } from "../core/logger";
import { cond, clone, pipe, omit } from "ramda";
import { getRejectionReason } from ".";
import { logger } from "./logger";
import { cond, clone, pipe, omit, T, always } from "ramda";
import metricsConditions from "../metricsConditions";

import { LogErrors, LogInfos } from "../shared/logMessages";
import { DataEvent, EnhancedDataEvent } from "../interfaces";

const collectMetricsBySignature = cond(
metricsConditions.map((cond) => [cond[0], cond[1]])
[metricsConditions.map((cond) => [cond[0], cond[1]])],
[T, always(false)]
);

export const collectMetrics = async (
Expand Down
7 changes: 1 addition & 6 deletions src/core/errorCatcher.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import { logger } from "./logger";

export enum Errors {
collectMetricsSignatureNotRecognized = "The signature of the data event is not recognized.",
signingEventSignatureNotRecognized = "Can't identify the signature of the data event. Skipping.",
}

export interface ErrorForCatcher {
level: "error" | "warn";
level: "error" | "warning";
message: string;
}

Expand Down
2 changes: 1 addition & 1 deletion src/handler.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { collectMetrics } from "./metrics/collectMetrics";
import { collectMetrics } from "./core/collectMetrics";
import { storeData, errorCatcher } from "./core";
import { logger } from "./core/logger";
import { pipeWith, tap } from "ramda";
Expand Down
14 changes: 12 additions & 2 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,32 @@ import {
PullRequestClosedPayload,
PullRequestClosedOutput,
} from "./metrics/pull_requests/interfaces";
import {
ToolingUsageOutput,
ToolingUsagePayload,
} from "./metrics/tooling_usage/interfaces";

import { WorkflowJobCompletedPayload } from "./metrics/workflows/interfaces";
import {
WorkflowJobCompletedOutput,
WorkflowJobCompletedPayload,
} from "./metrics/workflows/interfaces";

export enum DataEventSignature {
PullRequestClosed = "pull_request-completed",
WorkflowJobCompleted = "workflow-job-completed",
ToolingUsage = "deven-tooling-usage",
}

interface DataEventPayloadMap {
[DataEventSignature.PullRequestClosed]: PullRequestClosedPayload;
[DataEventSignature.WorkflowJobCompleted]: WorkflowJobCompletedPayload;
[DataEventSignature.ToolingUsage]: ToolingUsagePayload;
}

interface DataEventOutputMap {
[DataEventSignature.PullRequestClosed]: PullRequestClosedOutput;
[DataEventSignature.WorkflowJobCompleted]: WorkflowJobCompletedPayload;
[DataEventSignature.WorkflowJobCompleted]: WorkflowJobCompletedOutput;
[DataEventSignature.ToolingUsage]: ToolingUsageOutput;
}

export type EnhancedDataEvent = Omit<DataEvent, "payload">;
Expand Down
9 changes: 0 additions & 9 deletions src/metrics/packages/index.ts

This file was deleted.

9 changes: 4 additions & 5 deletions src/metrics/pull_requests/signatureConditions.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { allPass, propEq } from "ramda";
import { DataEventSignature } from "../../interfaces";

export const isPullRequestClosed = () =>
allPass([
propEq("eventSignature", "pull_request"),
propEq("action", "closed"),
]);
export const isPullRequestClosed = allPass([
propEq("eventSignature", "pull_request"),
propEq("action", "closed"),
]);

export default [[isPullRequestClosed, DataEventSignature.PullRequestClosed]];
Loading

0 comments on commit f93a4bf

Please sign in to comment.