From acd8567fa0366dcb0c81dbd98deb210a9b029c94 Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Tue, 27 Aug 2024 03:37:42 -0700 Subject: [PATCH] Add issue labeler --- .github/workflows/labeled.yml | 37 ++++ scripts/label-issue.ts | 351 ++++++++++++++++++++++++++++++++++ 2 files changed, 388 insertions(+) create mode 100644 scripts/label-issue.ts diff --git a/.github/workflows/labeled.yml b/.github/workflows/labeled.yml index 961ae7926f..532c7078be 100644 --- a/.github/workflows/labeled.yml +++ b/.github/workflows/labeled.yml @@ -7,6 +7,43 @@ on: types: [labeled] jobs: + on-bug: + runs-on: ubuntu-latest + if: github.event.label.name == 'bug' + permissions: + issues: write + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + sparse-checkout: | + scripts + .github + CMakeLists.txt + - name: Setup Bun + uses: ./.github/actions/setup-bun + with: + bun-version: "1.1.26" + - name: "categorize bug" + id: add-labels + if: github.event.label.name == 'bug' + env: + GITHUB_ISSUE_BODY: ${{ github.event.issue.body }} + GITHUB_ISSUE_TITLE: ${{ github.event.issue.title }} + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + shell: bash + run: | + echo '{"dependencies": { "@anthropic-ai/sdk": "latest" }}' > scripts/package.json && bun install --cwd=./scripts + LABELS=$(bun scripts/label-issue.ts) + echo "labels=$LABELS" >> $GITHUB_OUTPUT + - name: Add labels + uses: actions-cool/issues-helper@v3 + if: steps.add-labels.outputs.labels != '' + with: + actions: "add-labels" + token: ${{ secrets.GITHUB_TOKEN }} + issue-number: ${{ github.event.issue.number }} + labels: ${{ steps.add-labels.outputs.labels }} on-labeled: runs-on: ubuntu-latest if: github.event.label.name == 'crash' || github.event.label.name == 'needs repro' diff --git a/scripts/label-issue.ts b/scripts/label-issue.ts new file mode 100644 index 0000000000..9dfa84fb59 --- /dev/null +++ b/scripts/label-issue.ts @@ -0,0 +1,351 @@ +const labels = [ + { + name: "build", + description: "An issue related to building or compiling Bun (not bun build)", + }, + { + name: "bun:crypto", + description: "", + }, + { + name: "bun:dns", + description: "Bun's DNS resolver", + }, + { + name: "bun:ffi", + description: "Something related with FFI in Bun", + }, + { + name: "bun:fs", + description: "", + }, + { + name: "bun:glob", + description: "Related to Bun.Glob", + }, + { + name: "bun:http", + description: "", + }, + { + name: "bun:jsc", + description: "", + }, + { + name: "bun:semver", + description: "", + }, + { + name: "bun:serve", + description: "Bun.serve and HTTP server", + }, + { + name: "bun:spawn", + description: "", + }, + { + name: "bun:sqlite", + description: "Something to do with bun:sqlite", + }, + { + name: "bun:tcp", + description: "", + }, + { + name: "bun:udp", + description: "", + }, + { + name: "bun.js", + description: "Something to do with a Bun-specific API", + }, + { + name: "bundler", + description: "Something to do with the bundler", + }, + { + name: "bunx", + description: "Something that has to do with `bunx`", + }, + { + name: "chore", + description: "Task to improve the repository", + }, + { + name: "cjs", + description: "", + }, + { + name: "cli", + description: "Something to do with CLI arguments", + }, + { + name: "crash reporter bug", + description: "the stack trace given does not seem to be valid", + }, + { + name: "debugger", + description: "Something to do with `bun --inspect` or the debugger", + }, + { + name: "docker", + description: "An issue that occurs when running in Docker", + }, + { + name: "docs", + description: "Improvements or additions to documentation", + }, + { + name: "ecosystem", + description: "Something that relates to package or framework compatibility", + }, + { + name: "enhancement", + description: "New feature or request", + }, + { + name: "idea", + description: "", + }, + { + name: "infrastructure", + description: "", + }, + { + name: "jest", + description: "Something related to the `bun test` runner", + }, + { + name: "jsc", + description: "Something related to JavaScriptCore, bun's JS engine", + }, + { + name: "lambda", + description: "An issue related to the AWS Lambda layer", + }, + { + name: "linux", + description: "An issue that only occurs on Linux", + }, + { + name: "macOS", + description: "An issue that only occurs on macOS", + }, + { + name: "minifier", + description: "bun's javascript minifier", + }, + { + name: "napi", + description: "Compatibility with the native layer of Node.js", + }, + { + name: "node:crypto", + description: "the node:crypto module", + }, + { + name: "node:dgram", + description: "the node:dgram module", + }, + { + name: "node:dns", + description: "the node:dns module", + }, + { + name: "node:fs", + description: "the node:fs module", + }, + { + name: "node:http", + description: "the node:http module", + }, + { + name: "node:http2", + description: "the node:http2 module", + }, + { + name: "node:net", + description: "the node:net module", + }, + { + name: "node:os", + description: "the node:os module", + }, + { + name: "node:path", + description: "the node:path module", + }, + { + name: "node:process", + description: "the node:process module", + }, + { + name: "node:stream", + description: "the node:stream module", + }, + { + name: "node:tty", + description: "the node:tty module", + }, + { + name: "node:util", + description: "the node:util module", + }, + { + name: "node:v8", + description: "the node:v8 module", + }, + { + name: "node.js", + description: "Compatibility with Node.js APIs", + }, + { + name: "npm", + description: "Something that relates to the npm-compatible client", + }, + { + name: "npm:patch", + description: "bun patch subcommand", + }, + { + name: "performance", + description: "An issue with performance", + }, + { + name: "repl", + description: "An issue with `bun repl`", + }, + { + name: "runtime", + description: "Related to the JavaScript runtime", + }, + { + name: "shell", + description: "Something to do with Bun as a shell", + }, + { + name: "sourcemaps", + description: "Source maps", + }, + { + name: "transpiler", + description: "parser || printer", + }, + { + name: "types", + description: "An issue with TypeScript types", + }, + { + name: "typescript", + description: "Something for TypeScript", + }, + { + name: "vscode", + description: "Something to do with the VSCode extension", + }, + { + name: "wasm", + description: "Something that related to WASM or WASI support", + }, + { + name: "web-api", + description: "Something that relates to a standard Web API", + }, + { + name: "web:blob", + description: "Blob", + }, + { + name: "web:crypto", + description: "Related to crypto, SubtleCrypto", + }, + { + name: "web:encoding", + description: "TextEncoder, TextDecoder, etc.", + }, + { + name: "web:fetch", + description: "fetch api", + }, + { + name: "web:js", + description: "", + }, + { + name: "web:performance", + description: "Performance object", + }, + { + name: "web:stream", + description: "Related to ReadableStream, WritableStream, etc.", + }, + { + name: "web:url", + description: "Related to URL", + }, + { + name: "web:websocket", + description: "Related to WebSocket client API", + }, + { + name: "windows", + description: "An issue that only occurs on Windows", + }, + { + name: "wintercg", + description: "Web-interoperable Runtimes Community Group compatiblity", + }, +]; + +import { Anthropic } from "@anthropic-ai/sdk"; + +const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }); + +async function categorizeLabelsByClaudeAI( + issueDetails: { title: string; body: string }, + labels: Array<{ name: string; description: string }>, +) { + const response = await anthropic.messages.create({ + model: "claude-3-5-sonnet-20240620", + max_tokens: 2048, + system: `Given this list of labels: + ${labels.map(label => `- ${label.name}: ${label.description}`).join("\n")} + + Please analyze the bug report and return a JSON array of label names that are most relevant to this issue. Only include labels that are highly relevant. + + Only output VALID JSON. It's okay if there are no relevant labels. +`, + messages: [ + { + role: "user", + content: JSON.stringify({ title: issueDetails.title, body: issueDetails.body }, null, 2), + }, + ], + }); + + return JSON.parse(response.content[0].text); +} + +const issue = { + title: process.env.GITHUB_ISSUE_TITLE!, + body: process.env.GITHUB_ISSUE_BODY!, +}; +let relevantLabels = await categorizeLabelsByClaudeAI(issue, labels); +if (!relevantLabels?.length) { + console.error("No relevant labels found"); + process.exit(0); +} + +for (let i = 0; i < relevantLabels.length; i++) { + if (!labels.find(label => label.name === relevantLabels[i])) { + relevantLabels.splice(i, 1); + i--; + } +} + +if (relevantLabels.length === 0) { + console.error("No relevant labels found"); + process.exit(0); +} + +console.write(relevantLabels.join(","));