diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3dd238375..0dc0fc7e8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,11 +48,13 @@ jobs: - uses: actions/checkout@v3 - uses: ./.github/actions/install-deps - uses: ./.github/actions/build-cache - - uses: 8BitJonny/gh-get-current-pr@2.2.0 - id: PR + - name: Get PR number + uses: jwalton/gh-find-current-pr@v1 + id: find-pr - run: yarn auto pr-check --pr $PR --url "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" env: - PR: ${{ steps.PR.outputs.number }} + PR: ${{ steps.find-pr.outputs.pr || github.event.number }} + PROTECTED_BRANCH_REVIEWER_TOKEN: ${{ secrets.GH_TOKEN }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/auto.config.ts b/auto.config.ts index e5d7cf265..470c0b7c2 100644 --- a/auto.config.ts +++ b/auto.config.ts @@ -48,6 +48,7 @@ export default function rc(): AutoRc { "./scripts/auto-update-curl-version.js", ["all-contributors", allContributorsOptions], ["brew", brewOptions], + "ai-release-notes", ], labels: [ { diff --git a/plugins/ai-release-notes/README.md b/plugins/ai-release-notes/README.md new file mode 100644 index 000000000..804bd0546 --- /dev/null +++ b/plugins/ai-release-notes/README.md @@ -0,0 +1,24 @@ +# Ai-Release-Notes Plugin + + + +## Installation + +This plugin is not included with the `auto` CLI installed via NPM. To install: + +```bash +npm i --save-dev @auto-it/ai-release-notes +# or +yarn add -D @auto-it/ai-release-notes +``` + +## Usage + +```json +{ + "plugins": [ + "ai-release-notes" + // other plugins + ] +} +``` diff --git a/plugins/ai-release-notes/__tests__/ai-release-notes.test.ts b/plugins/ai-release-notes/__tests__/ai-release-notes.test.ts new file mode 100644 index 000000000..b9ef8c56c --- /dev/null +++ b/plugins/ai-release-notes/__tests__/ai-release-notes.test.ts @@ -0,0 +1,7 @@ +import Auto from '@auto-it/core'; +import AiReleaseNotes from '../src'; + +describe('Ai-Release-Notes Plugin', () => { + test('should do something', async () => { + }); +}); diff --git a/plugins/ai-release-notes/package.json b/plugins/ai-release-notes/package.json new file mode 100644 index 000000000..1eb7ca8f1 --- /dev/null +++ b/plugins/ai-release-notes/package.json @@ -0,0 +1,46 @@ +{ + "name": "@auto-it/ai-release-notes", + "version": "10.46.0", + "main": "dist/index.js", + "description": "", + "license": "MIT", + "author": { + "name": "Andrew Lisowski", + "email": "lisowski54@gmail.com" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org/", + "access": "public" + }, + "repository": { + "type": "git", + "url": "https://github.com/intuit/auto" + }, + "files": [ + "dist" + ], + "keywords": [ + "automation", + "semantic", + "release", + "github", + "labels", + "automated", + "continuos integration", + "changelog" + ], + "scripts": { + "build": "tsc -b", + "start": "npm run build -- -w", + "lint": "eslint src --ext .ts", + "test": "jest --maxWorkers=2 --config ../../package.json" + }, + "dependencies": { + "@auto-it/core": "link:../../packages/core", + "node-fetch": "2.6.7", + "fp-ts": "^2.5.3", + "io-ts": "^2.1.2", + "openai": "^3.2.1", + "tslib": "1.10.0" + } +} diff --git a/plugins/ai-release-notes/src/index.ts b/plugins/ai-release-notes/src/index.ts new file mode 100644 index 000000000..742e41845 --- /dev/null +++ b/plugins/ai-release-notes/src/index.ts @@ -0,0 +1,84 @@ +import { Auto, IPlugin, validatePluginConfiguration } from "@auto-it/core"; +import * as t from "io-ts"; +import { Configuration, OpenAIApi } from "openai"; +import fetch from "node-fetch"; +import endent from "endent"; + +const configuration = new Configuration({ + apiKey: process.env.OPENAI_API_KEY, +}); +const openai = new OpenAIApi(configuration); + +const prompt = [ + "Take the role of an experienced engineer with excellent ability to communicate technical concepts to a non-technical audience.", + "Your job is to read the diffs, pull request descriptions, and commit descriptions I provide and produce a summary of the changes.", + "Your summaries should be at max 6 sentences long and contain no references to coding.", + "Try to also sell the feature like a marketer.", + "Reply only with the summaries.", +]; + +const pluginOptions = t.partial({}); + +export type IAiReleaseNotesPluginOptions = t.TypeOf; + +/** */ +export default class AiReleaseNotesPlugin implements IPlugin { + /** The name of the plugin */ + name = "ai-release-notes"; + + /** The options of the plugin */ + readonly options: IAiReleaseNotesPluginOptions; + + /** Initialize the plugin with it's options */ + constructor(options: IAiReleaseNotesPluginOptions) { + this.options = options; + } + + /** Tap into auto plugin points. */ + apply(auto: Auto) { + auto.hooks.validateConfig.tapPromise(this.name, async (name, options) => { + // If it's a string thats valid config + if (name === this.name && typeof options !== "string") { + return validatePluginConfiguration(this.name, pluginOptions, options); + } + }); + + auto.hooks.prCheck.tapPromise(this.name, async ({ pr, dryRun }) => { + try { + const diff = await fetch(pr.diff_url).then((res) => res.text()); + const body = pr.body?.split("