mirror of
https://github.com/outline/outline.git
synced 2025-12-20 10:09:43 -06:00
Cache issueSources for embed integrations (#8952)
* Cache `issueSources` for embed integrations * lock model before update
This commit is contained in:
40
plugins/github/server/GitHubIssueProvider.ts
Normal file
40
plugins/github/server/GitHubIssueProvider.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { Endpoints } from "@octokit/types";
|
||||
import { IssueSource } from "@shared/schema";
|
||||
import { IntegrationService, IntegrationType } from "@shared/types";
|
||||
import { Integration } from "@server/models";
|
||||
import { BaseIssueProvider } from "@server/utils/BaseIssueProvider";
|
||||
import { GitHub } from "./github";
|
||||
|
||||
// This is needed to handle Octokit paginate response type mismatch.
|
||||
type ReposForInstallation =
|
||||
Endpoints["GET /installation/repositories"]["response"]["data"]["repositories"];
|
||||
|
||||
export class GitHubIssueProvider extends BaseIssueProvider {
|
||||
constructor() {
|
||||
super(IntegrationService.GitHub);
|
||||
}
|
||||
|
||||
async fetchSources(
|
||||
integration: Integration<IntegrationType.Embed>
|
||||
): Promise<IssueSource[]> {
|
||||
const client = await GitHub.authenticateAsInstallation(
|
||||
integration.settings.github!.installation.id
|
||||
);
|
||||
|
||||
const sources: IssueSource[] = [];
|
||||
|
||||
for await (const response of client.requestRepos()) {
|
||||
const repos = response.data as unknown as ReposForInstallation;
|
||||
sources.push(
|
||||
...repos.map<IssueSource>((repo) => ({
|
||||
id: String(repo.id),
|
||||
name: repo.name,
|
||||
owner: { id: String(repo.owner.id), name: repo.owner.login },
|
||||
service: IntegrationService.GitHub,
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
return sources;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import Router from "koa-router";
|
||||
import find from "lodash/find";
|
||||
import { IntegrationService, IntegrationType } from "@shared/types";
|
||||
import { parseDomain } from "@shared/utils/domains";
|
||||
import { createContext } from "@server/context";
|
||||
import Logger from "@server/logging/Logger";
|
||||
import auth from "@server/middlewares/authentication";
|
||||
import { transaction } from "@server/middlewares/transaction";
|
||||
@@ -88,30 +89,27 @@ router.get(
|
||||
},
|
||||
{ transaction }
|
||||
);
|
||||
await Integration.create(
|
||||
{
|
||||
service: IntegrationService.GitHub,
|
||||
type: IntegrationType.Embed,
|
||||
userId: user.id,
|
||||
teamId: user.teamId,
|
||||
authenticationId: authentication.id,
|
||||
settings: {
|
||||
github: {
|
||||
installation: {
|
||||
id: installationId!,
|
||||
account: {
|
||||
id: installation.account?.id,
|
||||
name:
|
||||
// @ts-expect-error Property 'login' does not exist on type
|
||||
installation.account?.login,
|
||||
avatarUrl: installation.account?.avatar_url,
|
||||
},
|
||||
await Integration.createWithCtx(createContext({ user, transaction }), {
|
||||
service: IntegrationService.GitHub,
|
||||
type: IntegrationType.Embed,
|
||||
userId: user.id,
|
||||
teamId: user.teamId,
|
||||
authenticationId: authentication.id,
|
||||
settings: {
|
||||
github: {
|
||||
installation: {
|
||||
id: installationId!,
|
||||
account: {
|
||||
id: installation.account?.id,
|
||||
name:
|
||||
// @ts-expect-error Property 'login' does not exist on type
|
||||
installation.account?.login,
|
||||
avatarUrl: installation.account?.avatar_url,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{ transaction }
|
||||
);
|
||||
});
|
||||
ctx.redirect(GitHubUtils.url);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -24,6 +24,17 @@ type Issue =
|
||||
Endpoints["GET /repos/{owner}/{repo}/issues/{issue_number}"]["response"]["data"];
|
||||
|
||||
const requestPlugin = (octokit: Octokit) => ({
|
||||
requestRepos: () =>
|
||||
octokit.paginate.iterator(
|
||||
octokit.rest.apps.listReposAccessibleToInstallation,
|
||||
{
|
||||
headers: {
|
||||
Accept: "application/vnd.github+json",
|
||||
"X-GitHub-Api-Version": "2022-11-28",
|
||||
},
|
||||
}
|
||||
),
|
||||
|
||||
requestPR: async (params: NonNullable<ReturnType<typeof GitHub.parseUrl>>) =>
|
||||
octokit.request(`GET /repos/{owner}/{repo}/pulls/{pull_number}`, {
|
||||
owner: params.owner,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Minute } from "@shared/utils/time";
|
||||
import { PluginManager, Hook } from "@server/utils/PluginManager";
|
||||
import config from "../plugin.json";
|
||||
import { GitHubIssueProvider } from "./GitHubIssueProvider";
|
||||
import router from "./api/github";
|
||||
import env from "./env";
|
||||
import { GitHub } from "./github";
|
||||
@@ -20,6 +21,10 @@ if (enabled) {
|
||||
type: Hook.API,
|
||||
value: router,
|
||||
},
|
||||
{
|
||||
type: Hook.IssueProvider,
|
||||
value: new GitHubIssueProvider(),
|
||||
},
|
||||
{
|
||||
type: Hook.UnfurlProvider,
|
||||
value: { unfurl: GitHub.unfurl, cacheExpiry: Minute.seconds },
|
||||
|
||||
Reference in New Issue
Block a user