From 01df1f101533032e2ab9f462ed4aa5cc82f1ab31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samy=20Pess=C3=A9?= Date: Wed, 2 Jul 2025 11:11:43 +0200 Subject: [PATCH] Remove GitHub conversations icon --- integrations/github-conversations/README.md | 9 ++ .../gitbook-manifest.yaml | 24 ++++ .../github-conversations/package.json | 20 +++ .../github-conversations/src/client.ts | 32 +++++ .../github-conversations/src/config.tsx | 100 +++++++++++++++ .../github-conversations/src/conversations.ts | 117 ++++++++++++++++++ .../github-conversations/src/index.ts | 62 ++++++++++ .../github-conversations/src/types.ts | 13 ++ .../github-conversations/tsconfig.json | 3 + 9 files changed, 380 insertions(+) create mode 100644 integrations/github-conversations/README.md create mode 100644 integrations/github-conversations/gitbook-manifest.yaml create mode 100644 integrations/github-conversations/package.json create mode 100644 integrations/github-conversations/src/client.ts create mode 100644 integrations/github-conversations/src/config.tsx create mode 100644 integrations/github-conversations/src/conversations.ts create mode 100644 integrations/github-conversations/src/index.ts create mode 100644 integrations/github-conversations/src/types.ts create mode 100644 integrations/github-conversations/tsconfig.json diff --git a/integrations/github-conversations/README.md b/integrations/github-conversations/README.md new file mode 100644 index 000000000..86a04cf6d --- /dev/null +++ b/integrations/github-conversations/README.md @@ -0,0 +1,9 @@ +# GitHub Conversations Integration + +This integration ingests resolved or closed GitHub Discussions into GitBook. + +## Setup Instructions for development + +1. Create a GitHub OAuth application. +2. Set `https:///v1/integrations/github-conversations/integration/oauth` as the redirect URL. +3. Configure a webhook on your repository for the `discussion` event with `https:///v1/integrations/github-conversations/integration/webhook` as the URL. diff --git a/integrations/github-conversations/gitbook-manifest.yaml b/integrations/github-conversations/gitbook-manifest.yaml new file mode 100644 index 000000000..8e3e029c7 --- /dev/null +++ b/integrations/github-conversations/gitbook-manifest.yaml @@ -0,0 +1,24 @@ +name: github-conversations +title: GitHub Discussions +description: Ingest resolved or closed GitHub Discussions into GitBook for auto-improvements. +visibility: public +script: ./src/index.ts +summary: | + # Overview + + Automatically get AI-suggested change requests for your docs based on GitHub community discussions. +scopes: + - conversations:ingest +organization: gitbook +configurations: + account: + componentId: config +secrets: + CLIENT_ID: ${{ env.GITHUB_CLIENT_ID }} + CLIENT_SECRET: ${{ env.GITHUB_CLIENT_SECRET }} +target: organization +envs: + staging: + secrets: + CLIENT_ID: ${{ "op://gitbook-integrations/GithubConversationsStaging/CLIENT_ID" }} + CLIENT_SECRET: ${{ "op://gitbook-integrations/GithubConversationsStaging/CLIENT_SECRET" }} diff --git a/integrations/github-conversations/package.json b/integrations/github-conversations/package.json new file mode 100644 index 000000000..0ee44c7c7 --- /dev/null +++ b/integrations/github-conversations/package.json @@ -0,0 +1,20 @@ +{ + "name": "@gitbook/integration-github-conversations", + "version": "0.0.1", + "private": true, + "dependencies": { + "@gitbook/runtime": "*", + "@gitbook/api": "*", + "octokit": "^4.0.2", + "p-map": "^7.0.3" + }, + "devDependencies": { + "@gitbook/cli": "workspace:*", + "@gitbook/tsconfig": "workspace:*" + }, + "scripts": { + "typecheck": "tsc --noEmit", + "check": "gitbook check", + "publish-integrations-staging": "gitbook publish . --env staging" + } +} diff --git a/integrations/github-conversations/src/client.ts b/integrations/github-conversations/src/client.ts new file mode 100644 index 000000000..482dd4cf0 --- /dev/null +++ b/integrations/github-conversations/src/client.ts @@ -0,0 +1,32 @@ +import { Octokit } from 'octokit'; +import { GitHubRuntimeContext } from './types'; +import { OAuthConfig, getOAuthToken } from '@gitbook/runtime'; + +/** Get OAuth configuration for GitHub */ +export function getGitHubOAuthConfig(context: GitHubRuntimeContext): OAuthConfig { + return { + redirectURL: `${context.environment.integration.urls.publicEndpoint}/oauth`, + clientId: context.environment.secrets.CLIENT_ID, + clientSecret: context.environment.secrets.CLIENT_SECRET, + authorizeURL: 'https://github.com/login/oauth/authorize', + accessTokenURL: 'https://github.com/login/oauth/access_token', + scopes: ['read:discussion'], + prompt: 'consent', + }; +} + +/** Initialize a GitHub API client */ +export async function getGitHubClient(context: GitHubRuntimeContext) { + const { installation } = context.environment; + if (!installation) { + throw new Error('Installation not found'); + } + const { oauth_credentials } = installation.configuration; + if (!oauth_credentials) { + throw new Error('GitHub OAuth credentials not found'); + } + + const token = await getOAuthToken(oauth_credentials, getGitHubOAuthConfig(context), context); + + return new Octokit({ auth: token }); +} diff --git a/integrations/github-conversations/src/config.tsx b/integrations/github-conversations/src/config.tsx new file mode 100644 index 000000000..786e0ee95 --- /dev/null +++ b/integrations/github-conversations/src/config.tsx @@ -0,0 +1,100 @@ +import { createComponent, InstallationConfigurationProps } from '@gitbook/runtime'; +import { GitHubRuntimeContext, GitHubRuntimeEnvironment } from './types'; + +export const configComponent = createComponent< + InstallationConfigurationProps, + { step: 'edit.repo' | 'authenticate' | 'initial'; repo?: string }, + { action: 'save.repo' | 'edit.repo' }, + GitHubRuntimeContext +>({ + componentId: 'config', + initialState: (props) => { + const { installation } = props; + if (installation.configuration?.repository && installation.configuration?.oauth_credentials) { + return { step: 'initial' as const }; + } + if (installation.configuration?.repository) { + return { step: 'authenticate' as const }; + } + return { step: 'edit.repo' as const, repo: '' }; + }, + action: async (element, action, context) => { + switch (action.action) { + case 'edit.repo': + return { + state: { + step: 'edit.repo', + repo: context.environment.installation?.configuration?.repository ?? '', + }, + }; + case 'save.repo': + await context.api.integrations.updateIntegrationInstallation( + context.environment.integration.name, + context.environment.installation!.id, + { + configuration: { + repository: action.repo, + }, + }, + ); + return { state: { step: 'authenticate' } }; + } + }, + render: async (element, context) => { + const { installation } = context.environment; + if (!installation) { + return null; + } + switch (element.state.step) { + case 'initial': + return ( + + The integration is configured with the following repository:} + element={} + /> + +