Skip to content

Commit

Permalink
feat: SDK and command interface
Browse files Browse the repository at this point in the history
  • Loading branch information
whilefoo committed Nov 20, 2024
1 parent e7040d2 commit ab95741
Show file tree
Hide file tree
Showing 17 changed files with 748 additions and 714 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/compute.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ on:
description: "Ref"
signature:
description: "The kernel signature"
command:
description: "Command"

jobs:
compute:
Expand Down
10 changes: 0 additions & 10 deletions jest.config.json

This file was deleted.

27 changes: 27 additions & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { Config } from "jest";

const cfg: Config = {
transform: {
"^.+\\.tsx?$": [
"ts-jest",
{
useESM: true,
},
],
},
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
coveragePathIgnorePatterns: ["node_modules", "mocks"],
collectCoverage: true,
coverageReporters: ["json", "lcov", "text", "clover", "json-summary"],
reporters: ["default", "jest-junit", "jest-md-dashboard"],
coverageDirectory: "coverage",
testTimeout: 20000,
roots: ["<rootDir>", "tests"],
extensionsToTreatAsEsm: [".ts"],
moduleNameMapper: {
"^(\\.{1,2}/.*)\\.js$": "$1",
},
setupFilesAfterEnv: ["dotenv/config"],
};

export default cfg;
41 changes: 18 additions & 23 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Conditionally merge pull requests after a timeout.",
"author": "Ubiquity DAO",
"license": "MIT",
"main": "src/index.ts",
"main": "src/action.ts",
"engines": {
"node": ">=20.10.0"
},
Expand All @@ -16,8 +16,8 @@
"knip": "knip --config .github/knip.ts",
"knip-ci": "knip --no-exit-code --reporter json --config .github/knip.ts",
"prepare": "husky install",
"start": "tsx src/index.ts",
"test": "jest --setupFiles dotenv/config --coverage"
"start": "tsx src/action.ts",
"test": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest --setupFiles dotenv/config --coverage"
},
"keywords": [
"typescript",
Expand All @@ -27,33 +27,26 @@
"open-source"
],
"dependencies": {
"@actions/core": "1.10.1",
"@actions/github": "6.0.0",
"@octokit/plugin-paginate-rest": "11.3.1",
"@octokit/rest": "20.1.1",
"@octokit/webhooks": "13.2.7",
"@sinclair/typebox": "0.32.33",
"@ubiquity-dao/ubiquibot-logger": "1.3.1",
"@sinclair/typebox": "0.34.3",
"@ubiquity-os/ubiquity-os-logger": "1.3.2",
"@ubiquity-os/plugin-sdk": "^1.0.11",
"dotenv": "16.4.5",
"ms": "2.1.3",
"reflect-metadata": "0.2.2",
"ts-retry": "4.2.5",
"tsx": "4.16.2",
"typebox-validators": "0.3.5"
"ts-retry": "4.2.5"
},
"devDependencies": {
"@commitlint/cli": "19.3.0",
"@commitlint/config-conventional": "19.2.2",
"@cspell/dict-node": "5.0.1",
"@cspell/dict-software-terms": "3.4.6",
"@cspell/dict-typescript": "3.1.5",
"@eslint/js": "9.5.0",
"@commitlint/cli": "^19.5.0",
"@commitlint/config-conventional": "^19.5.0",
"@cspell/dict-node": "^5.0.5",
"@cspell/dict-software-terms": "^4.1.15",
"@cspell/dict-typescript": "^3.1.2",
"@eslint/js": "9.14.0",
"@jest/globals": "29.7.0",
"@mswjs/data": "0.16.1",
"@types/ms": "0.7.34",
"@types/node": "20.14.5",
"cspell": "8.9.0",
"eslint": "9.5.0",
"eslint": "9.14.0",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-check-file": "2.8.0",
"eslint-plugin-prettier": "5.1.3",
Expand All @@ -68,8 +61,10 @@
"npm-run-all": "4.1.5",
"prettier": "3.3.2",
"ts-jest": "29.1.5",
"ts-node": "10.9.2",
"tsx": "4.16.2",
"typescript": "5.6.2",
"typescript-eslint": "8.8.0"
"typescript-eslint": "8.14.0"
},
"lint-staged": {
"*.ts": [
Expand All @@ -86,4 +81,4 @@
]
},
"packageManager": "yarn@1.22.22"
}
}
55 changes: 17 additions & 38 deletions src/action.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,19 @@
import * as github from "@actions/github";
import { Octokit } from "@octokit/rest";
import { validateAndDecodeSchemas } from "./helpers/validator";
import { createActionsPlugin } from "@ubiquity-os/plugin-sdk";
import { SupportedEvents } from "./types/context";
import { Env, envSchema } from "./types/env";
import { PluginSettings, pluginSettingsSchema } from "./types/plugin-inputs";
import { plugin } from "./plugin";
import { PluginInputs } from "./types";
import { LogLevel } from "@ubiquity-os/ubiquity-os-logger";

/**
* How a GitHub action executes the plugin.
*/
export async function run() {
const payload = github.context.payload.inputs;

payload.env = { ...(payload.env || {}), workflowName: github.context.workflow };
const { decodedSettings, decodedEnv } = validateAndDecodeSchemas(payload.env, JSON.parse(payload.settings));
const inputs: PluginInputs = {
stateId: payload.stateId,
eventName: payload.eventName,
eventPayload: JSON.parse(payload.eventPayload),
settings: decodedSettings,
authToken: payload.authToken,
ref: payload.ref,
};

await plugin(inputs, decodedEnv);

return returnDataToKernel(process.env.GITHUB_TOKEN, inputs.stateId, {});
}

export async function returnDataToKernel(repoToken: string, stateId: string, output: object, eventType = "return-data-to-ubiquity-os-kernel") {
const octokit = new Octokit({ auth: repoToken });
return octokit.repos.createDispatchEvent({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
event_type: eventType,
client_payload: {
state_id: stateId,
output: JSON.stringify(output),
},
});
}
createActionsPlugin<PluginSettings, Env, null, SupportedEvents>(
(context) => {
return plugin(context);
},
{
envSchema: envSchema,
postCommentOnError: true,
settingsSchema: pluginSettingsSchema,
logLevel: (process.env.LOG_LEVEL as LogLevel) ?? "info",
kernelPublicKey: process.env.KERNEL_PUBLIC_KEY,
}
).catch(console.error);
1 change: 1 addition & 0 deletions src/helpers/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ export async function getOpenPullRequests(context: Context, targets: ReposWatchS
}

export async function mergePullRequest(context: Context, { repo, owner, issue_number: pullNumber }: IssueParams) {
console.log("merging PR");
await context.octokit.rest.pulls.merge({
owner,
repo,
Expand Down
6 changes: 4 additions & 2 deletions src/helpers/update-pull-requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,15 @@ export async function updatePullRequests(context: Context) {
if (owner) {
logger.info(`No organizations or repo have been specified, will default to the organization owner: ${owner.login}.`);
} else {
return logger.error("Could not set a default organization to watch, skipping.");
throw logger.error("Could not set a default organization to watch, skipping.");
}
}

const pullRequests = await getOpenPullRequests(context, context.config.repos as ReposWatchSettings);

if (!pullRequests?.length) {
return logger.info("Nothing to do.");
logger.info("Nothing to do.");
return;
}

for (const { html_url } of pullRequests) {
Expand All @@ -56,6 +57,7 @@ export async function updatePullRequests(context: Context) {
continue;
}
const activity = await getAllTimelineEvents(context, parseGitHubUrl(html_url));
console.log(activity);
const eventDates: Date[] = activity.reduce<Date[]>((acc, event) => {
if (isIssueEvent(event)) {
const date = new Date(event.created_at || event.updated_at || event.timestamp || event.commented_at || "");
Expand Down
35 changes: 0 additions & 35 deletions src/helpers/validator.ts

This file was deleted.

12 changes: 0 additions & 12 deletions src/index.ts

This file was deleted.

19 changes: 2 additions & 17 deletions src/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,10 @@
import { paginateRest } from "@octokit/plugin-paginate-rest";
import { Octokit } from "@octokit/rest";
import { Logs } from "@ubiquity-dao/ubiquibot-logger";
import { updatePullRequests } from "./helpers/update-pull-requests";
import { Context, Env, PluginInputs } from "./types";
import { Context } from "./types";

/**
* How a worker executes the plugin.
*/
export async function plugin(inputs: PluginInputs, env: Env) {
const octokitWithPlugin = Octokit.plugin(paginateRest);
const octokit = new octokitWithPlugin({ auth: inputs.authToken });

const context: Context = {
eventName: inputs.eventName,
payload: inputs.eventPayload,
config: inputs.settings,
octokit,
env,
logger: new Logs("debug"),
};

export async function plugin(context: Context) {
context.logger.info("Will check the following repos", { ...context.config.repos });
return await updatePullRequests(context);
}
19 changes: 3 additions & 16 deletions src/types/context.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,7 @@
import { Octokit } from "@octokit/rest";
import { EmitterWebhookEvent as WebhookEvent, EmitterWebhookEventName as WebhookEventName } from "@octokit/webhooks";
import { Logs } from "@ubiquity-dao/ubiquibot-logger";
import { Context as PluginContext } from "@ubiquity-os/plugin-sdk";
import { Env } from "./env";
import { PluginSettings } from "./plugin-inputs";

export type SupportedEventsU = "push" | "issue_comment.created";
export type SupportedEvents = "push" | "issue_comment.created";

export type SupportedEvents = {
[K in SupportedEventsU]: K extends WebhookEventName ? WebhookEvent<K> : never;
};

export interface Context<T extends SupportedEventsU = SupportedEventsU, TU extends SupportedEvents[T] = SupportedEvents[T]> {
eventName: T;
payload: TU["payload"];
octokit: InstanceType<typeof Octokit>;
config: PluginSettings;
env: Env;
logger: Logs;
}
export type Context<TEvents extends SupportedEvents = SupportedEvents> = PluginContext<PluginSettings, Env, null, TEvents>;
3 changes: 0 additions & 3 deletions src/types/env.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { Type as T } from "@sinclair/typebox";
import { StaticDecode } from "@sinclair/typebox";
import "dotenv/config";
import { StandardValidator } from "typebox-validators";

export const envSchema = T.Object({
workflowName: T.String(),
});

export const envValidator = new StandardValidator(envSchema);

export type Env = StaticDecode<typeof envSchema>;
13 changes: 0 additions & 13 deletions src/types/plugin-inputs.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,4 @@
import { SupportedEvents, SupportedEventsU } from "./context";
import { StaticDecode, Type as T } from "@sinclair/typebox";
import { StandardValidator } from "typebox-validators";

export interface PluginInputs<T extends SupportedEventsU = SupportedEventsU, TU extends SupportedEvents[T] = SupportedEvents[T]> {
stateId: string;
eventName: T;
eventPayload: TU["payload"];
settings: PluginSettings;
authToken: string;
ref: string;
}

export const approvalsRequiredSchema = T.Object(
{
Expand Down Expand Up @@ -71,7 +60,5 @@ export const pluginSettingsSchema = T.Object({
),
});

export const pluginSettingsValidator = new StandardValidator(pluginSettingsSchema);

export type PluginSettings = StaticDecode<typeof pluginSettingsSchema>;
export type ReposWatchSettings = StaticDecode<typeof reposSchema>;
Loading

0 comments on commit ab95741

Please sign in to comment.