Merge pull request #9701 from backstage/blam/deprecations/octokit
deprecations: Deprecate the `OctokitProvider` export from `scaffolder-backend`
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
---
|
||||
|
||||
- **DEPRECATED** - `OctokitProvider` has been deprecated and will be removed in upcoming versions
|
||||
This helper doesn't make sense to be export from the `plugin-scaffolder-backend` and possibly will be moved into the `integrations` package at a later date.
|
||||
All implementations have been moved over to a private implementation called `getOctokitOptions` which is then passed to the `Octokit` constructor. If you're using this API you should consider duplicating the logic that lives in `getOctokitOptions` and move away from the deprecated export.
|
||||
@@ -392,13 +392,15 @@ export function fetchContents({
|
||||
|
||||
// Warning: (ae-missing-release-tag) "OctokitProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public
|
||||
// @public @deprecated
|
||||
export class OctokitProvider {
|
||||
constructor(
|
||||
integrations: ScmIntegrationRegistry,
|
||||
githubCredentialsProvider?: GithubCredentialsProvider,
|
||||
);
|
||||
// Warning: (ae-forgotten-export) The symbol "OctokitIntegration" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// @deprecated
|
||||
getOctokit(
|
||||
repoUrl: string,
|
||||
options?: {
|
||||
|
||||
@@ -32,6 +32,9 @@ export type OctokitIntegration = {
|
||||
/**
|
||||
* OctokitProvider provides Octokit client based on ScmIntegrationsRegistry configuration.
|
||||
* OctokitProvider supports GitHub credentials caching out of the box.
|
||||
*
|
||||
* @deprecated we are no longer providing a way from the scaffolder to generate octokit instances.
|
||||
* Implement your own if you're using this method from an external package, or use the internal `getOctokitOptions` function instead
|
||||
*/
|
||||
export class OctokitProvider {
|
||||
private readonly integrations: ScmIntegrationRegistry;
|
||||
@@ -51,6 +54,9 @@ export class OctokitProvider {
|
||||
* gets standard Octokit client based on repository URL.
|
||||
*
|
||||
* @param repoUrl - Repository URL
|
||||
*
|
||||
* @deprecated we are no longer providing a way from the scaffolder to generate octokit instances.
|
||||
* Implement your own if you're using this method from an external package, or use the internal `getOctokitOptions` function instead
|
||||
*/
|
||||
async getOctokit(
|
||||
repoUrl: string,
|
||||
|
||||
+17
-10
@@ -13,24 +13,21 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { InputError } from '@backstage/errors';
|
||||
import {
|
||||
DefaultGithubCredentialsProvider,
|
||||
GithubCredentialsProvider,
|
||||
ScmIntegrations,
|
||||
} from '@backstage/integration';
|
||||
import { Octokit } from 'octokit';
|
||||
import { createTemplateAction } from '../../createTemplateAction';
|
||||
import { OctokitProvider } from './OctokitProvider';
|
||||
import { parseRepoUrl } from '../publish/util';
|
||||
import { getOctokitOptions } from './helpers';
|
||||
|
||||
export function createGithubActionsDispatchAction(options: {
|
||||
integrations: ScmIntegrations;
|
||||
githubCredentialsProvider?: GithubCredentialsProvider;
|
||||
}) {
|
||||
const { integrations, githubCredentialsProvider } = options;
|
||||
const octokitProvider = new OctokitProvider(
|
||||
integrations,
|
||||
githubCredentialsProvider ||
|
||||
DefaultGithubCredentialsProvider.fromIntegrations(integrations),
|
||||
);
|
||||
|
||||
return createTemplateAction<{
|
||||
repoUrl: string;
|
||||
@@ -90,9 +87,19 @@ export function createGithubActionsDispatchAction(options: {
|
||||
`Dispatching workflow ${workflowId} for repo ${repoUrl} on ${branchOrTagName}`,
|
||||
);
|
||||
|
||||
const { client, owner, repo } = await octokitProvider.getOctokit(
|
||||
repoUrl,
|
||||
{ token: providedToken },
|
||||
const { owner, repo } = parseRepoUrl(repoUrl, integrations);
|
||||
|
||||
if (!owner) {
|
||||
throw new InputError('Invalid repository owner provided in repoUrl');
|
||||
}
|
||||
|
||||
const client = new Octokit(
|
||||
await getOctokitOptions({
|
||||
integrations,
|
||||
repoUrl,
|
||||
credentialsProvider: githubCredentialsProvider,
|
||||
token: providedToken,
|
||||
}),
|
||||
);
|
||||
|
||||
await client.rest.actions.createWorkflowDispatch({
|
||||
|
||||
@@ -14,14 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import {
|
||||
DefaultGithubCredentialsProvider,
|
||||
GithubCredentialsProvider,
|
||||
ScmIntegrationRegistry,
|
||||
} from '@backstage/integration';
|
||||
import { createTemplateAction } from '../../createTemplateAction';
|
||||
import { OctokitProvider } from './OctokitProvider';
|
||||
import { emitterEventNames } from '@octokit/webhooks';
|
||||
import { assertError } from '@backstage/errors';
|
||||
import { assertError, InputError } from '@backstage/errors';
|
||||
import { Octokit } from 'octokit';
|
||||
import { getOctokitOptions } from './helpers';
|
||||
import { parseRepoUrl } from '../publish/util';
|
||||
|
||||
export function createGithubWebhookAction(options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
@@ -30,11 +31,7 @@ export function createGithubWebhookAction(options: {
|
||||
}) {
|
||||
const { integrations, defaultWebhookSecret, githubCredentialsProvider } =
|
||||
options;
|
||||
const octokitProvider = new OctokitProvider(
|
||||
integrations,
|
||||
githubCredentialsProvider ??
|
||||
DefaultGithubCredentialsProvider.fromIntegrations(integrations),
|
||||
);
|
||||
|
||||
const eventNames = emitterEventNames.filter(event => !event.includes('.'));
|
||||
|
||||
return createTemplateAction<{
|
||||
@@ -127,10 +124,19 @@ export function createGithubWebhookAction(options: {
|
||||
} = ctx.input;
|
||||
|
||||
ctx.logger.info(`Creating webhook ${webhookUrl} for repo ${repoUrl}`);
|
||||
const { owner, repo } = parseRepoUrl(repoUrl, integrations);
|
||||
|
||||
const { client, owner, repo } = await octokitProvider.getOctokit(
|
||||
repoUrl,
|
||||
{ token: providedToken },
|
||||
if (!owner) {
|
||||
throw new InputError('Invalid repository owner provided in repoUrl');
|
||||
}
|
||||
|
||||
const client = new Octokit(
|
||||
await getOctokitOptions({
|
||||
integrations,
|
||||
credentialsProvider: githubCredentialsProvider,
|
||||
repoUrl: repoUrl,
|
||||
token: providedToken,
|
||||
}),
|
||||
);
|
||||
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { InputError } from '@backstage/errors';
|
||||
import {
|
||||
DefaultGithubCredentialsProvider,
|
||||
GithubCredentialsProvider,
|
||||
ScmIntegrationRegistry,
|
||||
} from '@backstage/integration';
|
||||
import { OctokitOptions } from '@octokit/core/dist-types/types';
|
||||
import { parseRepoUrl } from '../publish/util';
|
||||
|
||||
export async function getOctokitOptions(options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
credentialsProvider?: GithubCredentialsProvider;
|
||||
token?: string;
|
||||
repoUrl: string;
|
||||
}): Promise<OctokitOptions> {
|
||||
const { integrations, credentialsProvider, repoUrl, token } = options;
|
||||
const { owner, repo, host } = parseRepoUrl(repoUrl, integrations);
|
||||
|
||||
if (!owner) {
|
||||
throw new InputError(`No owner provided for repo ${repoUrl}`);
|
||||
}
|
||||
|
||||
const integrationConfig = integrations.github.byHost(host)?.config;
|
||||
|
||||
if (!integrationConfig) {
|
||||
throw new InputError(`No integration for host ${host}`);
|
||||
}
|
||||
|
||||
// short circuit the `githubCredentialsProvider` if there is a token provided by the caller already
|
||||
if (token) {
|
||||
return {
|
||||
auth: token,
|
||||
baseUrl: integrationConfig.apiBaseUrl,
|
||||
previews: ['nebula-preview'],
|
||||
};
|
||||
}
|
||||
|
||||
const githubCredentialsProvider =
|
||||
credentialsProvider ??
|
||||
DefaultGithubCredentialsProvider.fromIntegrations(integrations);
|
||||
|
||||
// TODO(blam): Consider changing this API to take host and repo instead of repoUrl, as we end up parsing in this function
|
||||
// and then parsing in the `getCredentials` function too the other side
|
||||
const { token: credentialProviderToken } =
|
||||
await githubCredentialsProvider.getCredentials({
|
||||
url: `https://${host}/${encodeURIComponent(owner)}/${encodeURIComponent(
|
||||
repo,
|
||||
)}`,
|
||||
});
|
||||
|
||||
if (!credentialProviderToken) {
|
||||
throw new InputError(
|
||||
`No token available for host: ${host}, with owner ${owner}, and repo ${repo}`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
auth: credentialProviderToken,
|
||||
baseUrl: integrationConfig.apiBaseUrl,
|
||||
previews: ['nebula-preview'],
|
||||
};
|
||||
}
|
||||
@@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import {
|
||||
DefaultGithubCredentialsProvider,
|
||||
GithubCredentialsProvider,
|
||||
ScmIntegrationRegistry,
|
||||
} from '@backstage/integration';
|
||||
@@ -22,11 +21,12 @@ import {
|
||||
enableBranchProtectionOnDefaultRepoBranch,
|
||||
initRepoAndPush,
|
||||
} from '../helpers';
|
||||
import { getRepoSourceDirectory } from './util';
|
||||
import { getRepoSourceDirectory, parseRepoUrl } from './util';
|
||||
import { createTemplateAction } from '../../createTemplateAction';
|
||||
import { Config } from '@backstage/config';
|
||||
import { OctokitProvider } from '../github/OctokitProvider';
|
||||
import { assertError } from '@backstage/errors';
|
||||
import { assertError, InputError } from '@backstage/errors';
|
||||
import { getOctokitOptions } from '../github/helpers';
|
||||
import { Octokit } from 'octokit';
|
||||
|
||||
export function createPublishGithubAction(options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
@@ -34,11 +34,6 @@ export function createPublishGithubAction(options: {
|
||||
githubCredentialsProvider?: GithubCredentialsProvider;
|
||||
}) {
|
||||
const { integrations, config, githubCredentialsProvider } = options;
|
||||
const octokitProvider = new OctokitProvider(
|
||||
integrations,
|
||||
githubCredentialsProvider ||
|
||||
DefaultGithubCredentialsProvider.fromIntegrations(integrations),
|
||||
);
|
||||
|
||||
return createTemplateAction<{
|
||||
repoUrl: string;
|
||||
@@ -160,10 +155,20 @@ export function createPublishGithubAction(options: {
|
||||
token: providedToken,
|
||||
} = ctx.input;
|
||||
|
||||
const { client, token, owner, repo } = await octokitProvider.getOctokit(
|
||||
const { owner, repo } = parseRepoUrl(repoUrl, integrations);
|
||||
|
||||
if (!owner) {
|
||||
throw new InputError('Invalid repository owner provided in repoUrl');
|
||||
}
|
||||
|
||||
const octokitOptions = await getOctokitOptions({
|
||||
integrations,
|
||||
credentialsProvider: githubCredentialsProvider,
|
||||
token: providedToken,
|
||||
repoUrl,
|
||||
{ token: providedToken },
|
||||
);
|
||||
});
|
||||
|
||||
const client = new Octokit(octokitOptions);
|
||||
|
||||
const user = await client.rest.users.getByUsername({
|
||||
username: owner,
|
||||
@@ -253,7 +258,7 @@ export function createPublishGithubAction(options: {
|
||||
defaultBranch,
|
||||
auth: {
|
||||
username: 'x-access-token',
|
||||
password: token,
|
||||
password: octokitOptions.auth,
|
||||
},
|
||||
logger: ctx.logger,
|
||||
commitMessage: config.getOptionalString(
|
||||
|
||||
+13
-34
@@ -20,7 +20,6 @@ import { parseRepoUrl, isExecutable } from './util';
|
||||
import {
|
||||
GithubCredentialsProvider,
|
||||
ScmIntegrationRegistry,
|
||||
SingleInstanceGithubCredentialsProvider,
|
||||
} from '@backstage/integration';
|
||||
import { zipObject } from 'lodash';
|
||||
import { createTemplateAction } from '../../createTemplateAction';
|
||||
@@ -29,6 +28,7 @@ import { InputError, CustomErrorBase } from '@backstage/errors';
|
||||
import { createPullRequest } from 'octokit-plugin-create-pull-request';
|
||||
import globby from 'globby';
|
||||
import { resolveSafeChildPath } from '@backstage/backend-common';
|
||||
import { getOctokitOptions } from '../github/helpers';
|
||||
|
||||
export type Encoding = 'utf-8' | 'base64';
|
||||
|
||||
@@ -65,40 +65,19 @@ export const defaultClientFactory = async ({
|
||||
host = 'github.com',
|
||||
token: providedToken,
|
||||
}: ClientFactoryInput): Promise<PullRequestCreator> => {
|
||||
const integrationConfig = integrations.github.byHost(host)?.config;
|
||||
const [encodedHost, encodedOwner, encodedRepo] = [host, owner, repo].map(
|
||||
encodeURIComponent,
|
||||
);
|
||||
|
||||
const octokitOptions = await getOctokitOptions({
|
||||
integrations,
|
||||
credentialsProvider: githubCredentialsProvider,
|
||||
repoUrl: `https://${encodedHost}/${encodedOwner}/${encodedRepo}`,
|
||||
token: providedToken,
|
||||
});
|
||||
|
||||
const OctokitPR = Octokit.plugin(createPullRequest);
|
||||
|
||||
if (!integrationConfig) {
|
||||
throw new InputError(`No integration for host ${host}`);
|
||||
}
|
||||
|
||||
if (providedToken) {
|
||||
return new OctokitPR({
|
||||
auth: providedToken,
|
||||
baseUrl: integrationConfig.apiBaseUrl,
|
||||
});
|
||||
}
|
||||
|
||||
const credentialsProvider =
|
||||
githubCredentialsProvider ||
|
||||
SingleInstanceGithubCredentialsProvider.create(integrationConfig);
|
||||
|
||||
const { token } = await credentialsProvider.getCredentials({
|
||||
url: `https://${host}/${encodeURIComponent(owner)}/${encodeURIComponent(
|
||||
repo,
|
||||
)}`,
|
||||
});
|
||||
|
||||
if (!token) {
|
||||
throw new InputError(
|
||||
`No token available for host: ${host}, with owner ${owner}, and repo ${repo}`,
|
||||
);
|
||||
}
|
||||
|
||||
return new OctokitPR({
|
||||
auth: token,
|
||||
baseUrl: integrationConfig.apiBaseUrl,
|
||||
});
|
||||
return new OctokitPR(octokitOptions);
|
||||
};
|
||||
|
||||
interface CreateGithubPullRequestActionOptions {
|
||||
|
||||
Reference in New Issue
Block a user