Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dist
node_modules
.paperclip-sdk
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Plugin Github Webhook Dispatcher

A Paperclip plugin

## Development

```bash
pnpm install
pnpm dev # watch builds
pnpm dev:ui # local dev server with hot-reload events
pnpm test
```



## Install Into Paperclip

```bash
curl -X POST http://127.0.0.1:3100/api/plugins/install \
-H "Content-Type: application/json" \
-d '{"packageName":"/home/ubuntu/paperclip-data/trial/paperclip-ten-334-github-webhook-dispatcher/packages/plugins/examples/plugin-github-webhook-dispatcher","isLocalPath":true}'
```

## Build Options

- `pnpm build` uses esbuild presets from `@paperclipai/plugin-sdk/bundlers`.
- `pnpm build:rollup` uses rollup presets from the same SDK.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import esbuild from "esbuild";
import { createPluginBundlerPresets } from "@paperclipai/plugin-sdk/bundlers";

const presets = createPluginBundlerPresets({});
const watch = process.argv.includes("--watch");

const workerCtx = await esbuild.context(presets.esbuild.worker);
const manifestCtx = await esbuild.context(presets.esbuild.manifest);

if (watch) {
await Promise.all([workerCtx.watch(), manifestCtx.watch()]);
console.log("esbuild watch mode enabled for worker and manifest");
} else {
await Promise.all([workerCtx.rebuild(), manifestCtx.rebuild()]);
await Promise.all([workerCtx.dispose(), manifestCtx.dispose()]);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "@tensorleap/plugin-github-webhook-dispatcher",
"version": "0.1.0",
"type": "module",
"private": true,
"description": "GitHub webhook dispatcher that routes PR, issue, and CI events to matching TEN issues across tensorleap repos",
"scripts": {
"prebuild": "pnpm --filter @paperclipai/plugin-sdk ensure-build-deps",
"build": "node ./esbuild.config.mjs",
"dev": "node ./esbuild.config.mjs --watch",
"test": "vitest run --config ./vitest.config.ts",
"typecheck": "pnpm --filter @paperclipai/plugin-sdk ensure-build-deps && tsc --noEmit"
},
"paperclipPlugin": {
"manifest": "./dist/manifest.js",
"worker": "./dist/worker.js"
},
"keywords": [
"paperclip",
"plugin",
"github",
"webhook"
],
"author": "Tensorleap",
"license": "MIT",
"dependencies": {
"@paperclipai/plugin-sdk": "workspace:*"
},
"devDependencies": {
"@paperclipai/shared": "workspace:*",
"@types/node": "^24.6.0",
"esbuild": "^0.27.3",
"typescript": "^5.7.3",
"vitest": "^3.2.4"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { nodeResolve } from "@rollup/plugin-node-resolve";
import typescript from "@rollup/plugin-typescript";
import { createPluginBundlerPresets } from "@paperclipai/plugin-sdk/bundlers";

const presets = createPluginBundlerPresets({ uiEntry: "src/ui/index.tsx" });

function withPlugins(config) {
if (!config) return null;
return {
...config,
plugins: [
nodeResolve({
extensions: [".ts", ".tsx", ".js", ".jsx", ".mjs"],
}),
typescript({
tsconfig: "./tsconfig.json",
declaration: false,
declarationMap: false,
}),
],
};
}

export default [
withPlugins(presets.rollup.manifest),
withPlugins(presets.rollup.worker),
withPlugins(presets.rollup.ui),
].filter(Boolean);
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import type { PaperclipPluginManifestV1 } from "@paperclipai/plugin-sdk";

const manifest: PaperclipPluginManifestV1 = {
id: "tensorleap.plugin-github-webhook-dispatcher",
apiVersion: 1,
version: "0.1.0",
displayName: "GitHub Webhook Dispatcher",
description: "Receives GitHub webhook events and dispatches wake comments to matching TEN issues. Handles pull_request, pull_request_review, issues, issue_comment, and check_suite events across tensorleap repos.",
author: "Tensorleap",
categories: ["connector", "automation"],
capabilities: [
"webhooks.receive",
"issues.read",
"issues.create",
"issue.comments.create",
"plugin.state.read",
"plugin.state.write",
"secrets.read-ref",
],
instanceConfigSchema: {
type: "object",
required: ["companyId", "webhookSecretRef"],
properties: {
companyId: {
type: "string",
title: "Company ID",
description: "Paperclip company whose issues should receive GitHub event comments.",
default: "",
},
webhookSecretRef: {
type: "string",
title: "Webhook Secret Ref",
description: "Company secret UUID used to verify GitHub's X-Hub-Signature-256 header.",
format: "secret-ref",
default: "",
},
},
},
entrypoints: {
worker: "./dist/worker.js",
},
webhooks: [
{
endpointKey: "github",
displayName: "GitHub Events",
description: "Receives PR, issue, and CI events from tensorleap GitHub repos",
},
],
};

export default manifest;
Loading
Loading