Skip to content

Commit

Permalink
feat: command interface
Browse files Browse the repository at this point in the history
  • Loading branch information
whilefoo committed Nov 16, 2024
1 parent 142b6e6 commit bc98157
Show file tree
Hide file tree
Showing 15 changed files with 728 additions and 644 deletions.
2 changes: 1 addition & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"ignorePaths": ["**/*.json", "**/*.css", "node_modules", "**/*.log", "**/*.http", "**/*.toml", "src/types/database.ts"],
"useGitignore": true,
"language": "en",
"words": ["Nektos", "dataurl", "devpool", "outdir", "servedir", "Supabase", "SUPABASE", "typebox", "ubiquibot", "Smee", "Rpcs"],
"words": ["Nektos", "dataurl", "devpool", "outdir", "servedir", "Supabase", "SUPABASE", "typebox", "ubiquibot", "Smee", "Rpcs", "hono"],
"dictionaries": ["typescript", "node", "software-terms"],
"import": ["@cspell/dict-typescript/cspell-ext.json", "@cspell/dict-node/cspell-ext.json", "@cspell/dict-software-terms"],
"ignoreRegExpList": ["[0-9a-fA-F]{6}"]
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/compute.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ on:
description: "Auth Token"
ref:
description: "Ref"
command:
required: true

jobs:
compute:
Expand Down
29 changes: 18 additions & 11 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
{
"name": "Wallet",
"description": "Allows users to register their wallets to collect rewards.",
"ubiquity:listeners": [
"issue_comment.created"
],
"commands": {
"wallet": {
"ubiquity:listeners": ["issue_comment.created"],
"skipBotEvents": true,
"commands": [
{
"name": "wallet",
"ubiquity:example": "/wallet ubq.eth",
"description": "Register your wallet address for payments."
"description": "Register your wallet address for payments.",
"parameters": {
"type": "object",
"properties": {
"walletAddress": {
"description": "Ethereum address or Ethereum Name Service",
"type": "string"
}
}
}
}
},
],
"configuration": {
"type": "object",
"properties": {
Expand All @@ -18,8 +27,6 @@
"type": "boolean"
}
},
"required": [
"registerWalletWithVerification"
]
"required": ["registerWalletWithVerification"]
}
}
}
29 changes: 13 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"knip-ci": "knip --no-exit-code --reporter json --config .github/knip.ts",
"prepare": "husky install",
"test": "jest --setupFiles dotenv/config --coverage",
"worker": "wrangler dev --env dev --port 4000",
"worker": "wrangler dev --env dev --port 4002",
"supabase:generate:local": "supabase gen types typescript --local > src/types/database.ts",
"supabase:generate:remote": "cross-env-shell \"supabase gen types typescript --project-id $SUPABASE_PROJECT_ID --schema public > src/types/database.ts\""
},
Expand All @@ -30,33 +30,30 @@
"open-source"
],
"dependencies": {
"@actions/core": "1.10.1",
"@actions/github": "6.0.0",
"@octokit/rest": "20.1.1",
"@octokit/webhooks": "13.2.7",
"@sinclair/typebox": "0.32.33",
"@sinclair/typebox": "^0.33.0",
"@supabase/supabase-js": "2.43.5",
"@ubiquity-dao/rpc-handler": "1.3.0",
"@ubiquity-os/plugin-sdk": "^1.0.11",
"@ubiquity-os/ubiquity-os-logger": "^1.3.2",
"commander": "12.1.0",
"dotenv": "16.4.5",
"ethers": "6.13.1",
"typebox-validators": "0.3.5"
"ethers": "6.13.1"
},
"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/node": "20.14.5",
"cross-env": "7.0.3",
"cspell": "8.9.0",
"dotenv-cli": "7.4.2",
"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 @@ -74,8 +71,8 @@
"ts-node": "10.9.2",
"tsx": "4.15.6",
"typescript": "5.6.2",
"typescript-eslint": "7.13.1",
"wrangler": "3.79.0"
"typescript-eslint": "8.14.0",
"wrangler": "^3.87.0"
},
"lint-staged": {
"*.ts": [
Expand Down
9 changes: 9 additions & 0 deletions src/handlers/query-wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ function extractEnsName(text: string) {
}
}

export async function handleCommand(context: Context) {
const { command } = context;
if (!command) {
throw new Error("Command is undefined");
}
const { walletAddress } = command.parameters;
await registerWallet(context, walletAddress);
}

export async function registerWallet(context: Context, body: string) {
const { payload, config, logger, adapters } = context;
const sender = payload.sender.login;
Expand Down
36 changes: 0 additions & 36 deletions src/handlers/validator.ts

This file was deleted.

75 changes: 22 additions & 53 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,55 +1,24 @@
import * as core from "@actions/core";
import * as github from "@actions/github";
import { Octokit } from "@octokit/rest";
import { Value } from "@sinclair/typebox/build/cjs/value";
import { envSchema, pluginSettingsSchema, PluginInputs, pluginSettingsValidator } from "./types";
import { createActionsPlugin } from "@ubiquity-os/plugin-sdk";
import { createAdapters } from "./adapters";
import { SupportedEvents } from "./types/context";
import { Env, envSchema } from "./types/env";
import { PluginSettings, pluginSettingsSchema } from "./types/plugin-inputs";
import { Command } from "./types/command";
import { plugin } from "./plugin";

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

const env = Value.Decode(envSchema, payload.env);
const settings = Value.Decode(pluginSettingsSchema, Value.Default(pluginSettingsSchema, JSON.parse(payload.settings)));

if (!pluginSettingsValidator.test(settings)) {
throw new Error("Invalid settings provided");
import { LogLevel } from "@ubiquity-os/ubiquity-os-logger";

createActionsPlugin<PluginSettings, Env, Command, SupportedEvents>(
(context) => {
return plugin({
...context,
adapters: {} as ReturnType<typeof createAdapters>,
});
},
{
envSchema: envSchema,
postCommentOnError: true,
settingsSchema: pluginSettingsSchema,
logLevel: (process.env.LOG_LEVEL as LogLevel) ?? "info",
kernelPublicKey: process.env.KERNEL_PUBLIC_KEY,
}

const inputs: PluginInputs = {
stateId: payload.stateId,
eventName: payload.eventName,
eventPayload: JSON.parse(payload.eventPayload),
settings,
authToken: payload.authToken,
ref: payload.ref,
};

await plugin(inputs, env);

return returnDataToKernel(inputs.authToken, inputs.stateId, {});
}

async function returnDataToKernel(repoToken: string, stateId: string, output: object) {
const octokit = new Octokit({ auth: repoToken });
await octokit.repos.createDispatchEvent({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
event_type: "return_data_to_ubiquibot_kernel",
client_payload: {
state_id: stateId,
output: JSON.stringify(output),
},
});
}

run()
.then((result) => {
core.setOutput("result", result);
})
.catch((error) => {
console.error(error);
core.setFailed(error);
});
).catch(console.error);
27 changes: 9 additions & 18 deletions src/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,27 @@
import { Octokit } from "@octokit/rest";
import { createClient } from "@supabase/supabase-js";
import { Logs } from "@ubiquity-os/ubiquity-os-logger";
import { CommanderError } from "commander";
import { createAdapters } from "./adapters";
import { CommandParser } from "./handlers/command-parser";
import { Env, PluginInputs } from "./types";
import { Context } from "./types";
import { addCommentToIssue } from "./utils";
import { handleCommand } from "./handlers/query-wallet";

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

const context: Context = {
eventName: inputs.eventName,
payload: inputs.eventPayload,
config: inputs.settings,
octokit,
env,
logger: new Logs("info"),
adapters: {} as ReturnType<typeof createAdapters>,
};

export async function plugin(context: Context) {
const supabase = createClient(context.env.SUPABASE_URL, context.env.SUPABASE_KEY);
context.adapters = createAdapters(supabase, context);

if (context.command) {
await handleCommand(context);
return;
}

if (context.eventName === "issue_comment.created") {
const commandParser = new CommandParser(context);
try {
const args = inputs.eventPayload.comment.body.trim().split(/\s+/);
const args = context.payload.comment.body.trim().split(/\s+/);
await commandParser.parse(args);
} catch (err) {
if (err instanceof CommanderError) {
Expand Down
10 changes: 10 additions & 0 deletions src/types/command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { StaticDecode, Type as T } from "@sinclair/typebox";

export const commandSchema = T.Object({
name: T.Literal("wallet"),
parameters: T.Object({
walletAddress: T.String(),
}),
});

export type Command = StaticDecode<typeof commandSchema>;
21 changes: 5 additions & 16 deletions src/types/context.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
import { Octokit } from "@octokit/rest";
import { EmitterWebhookEvent as WebhookEvent, EmitterWebhookEventName as WebhookEventName } from "@octokit/webhooks";
import { Logs } from "@ubiquity-os/ubiquity-os-logger";
import { createAdapters } from "../adapters";
import { Env } from "./env";
import { PluginSettings } from "./plugin-inputs";
import { Context as PluginContext } from "@ubiquity-os/plugin-sdk";
import { Command } from "./command";

export type SupportedEventsU = "issue_comment.created";
export type SupportedEvents = "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>;
export type Context<TEvents extends SupportedEvents = SupportedEvents> = PluginContext<PluginSettings, Env, Command, TEvents> & {
adapters: ReturnType<typeof createAdapters>;
config: PluginSettings;
env: Env;
logger: Logs;
}
};
6 changes: 2 additions & 4 deletions src/types/env.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
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({
SUPABASE_URL: T.String(),
SUPABASE_KEY: T.String(),
KERNEL_PUBLIC_KEY: T.Optional(T.String()),
LOG_LEVEL: T.Optional(T.String()),
});

export const envValidator = new StandardValidator(envSchema);

export type Env = StaticDecode<typeof envSchema>;
12 changes: 0 additions & 12 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;
}

/**
* This should contain the properties of the bot config
Expand All @@ -21,6 +10,5 @@ export interface PluginInputs<T extends SupportedEventsU = SupportedEventsU, TU
export const pluginSettingsSchema = T.Object({
registerWalletWithVerification: T.Boolean({ default: false }),
});
export const pluginSettingsValidator = new StandardValidator(pluginSettingsSchema);

export type PluginSettings = StaticDecode<typeof pluginSettingsSchema>;
Loading

0 comments on commit bc98157

Please sign in to comment.