Merge pull request #4514 from ebarriosjr/added-githubapp-authentication-to-scaffolder

Added githubapp authentication to scaffolder
This commit is contained in:
Ben Lambert
2021-02-17 13:35:33 +01:00
committed by GitHub
3 changed files with 54 additions and 22 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend': patch
---
Added githubApp authentication to the scaffolder-backend plugin
@@ -18,14 +18,20 @@ import path from 'path';
import { Git } from '@backstage/backend-common';
import { PreparerBase, PreparerOptions } from './types';
import parseGitUrl from 'git-url-parse';
import { GitHubIntegrationConfig } from '@backstage/integration';
import {
GitHubIntegrationConfig,
GithubCredentialsProvider,
} from '@backstage/integration';
export class GithubPreparer implements PreparerBase {
static fromConfig(config: GitHubIntegrationConfig) {
return new GithubPreparer({ token: config.token });
const credentialsProvider = GithubCredentialsProvider.create(config);
return new GithubPreparer({ credentialsProvider });
}
constructor(private readonly config: { token?: string }) {}
constructor(
private readonly config: { credentialsProvider: GithubCredentialsProvider },
) {}
async prepare({ url, workspacePath, logger }: PreparerOptions) {
const parsedGitUrl = parseGitUrl(url);
@@ -36,10 +42,14 @@ export class GithubPreparer implements PreparerBase {
parsedGitUrl.filepath ?? '',
);
const git = this.config.token
const { token } = await this.config.credentialsProvider.getCredentials({
url,
});
const git = token
? Git.fromAuth({
username: 'x-access-token',
password: this.config.token,
password: token,
logger,
})
: Git.fromAuth({ logger });
@@ -16,7 +16,10 @@
import { PublisherBase, PublisherOptions, PublisherResult } from './types';
import { initRepoAndPush } from './helpers';
import { GitHubIntegrationConfig } from '@backstage/integration';
import {
GitHubIntegrationConfig,
GithubCredentialsProvider,
} from '@backstage/integration';
import parseGitUrl from 'git-url-parse';
import { Octokit } from '@octokit/rest';
import path from 'path';
@@ -28,27 +31,24 @@ export class GithubPublisher implements PublisherBase {
config: GitHubIntegrationConfig,
{ repoVisibility }: { repoVisibility: RepoVisibilityOptions },
) {
if (!config.token) {
if (!config.token && !config.apps) {
return undefined;
}
const githubClient = new Octokit({
auth: config.token,
baseUrl: config.apiBaseUrl,
});
const credentialsProvider = GithubCredentialsProvider.create(config);
return new GithubPublisher({
token: config.token,
client: githubClient,
credentialsProvider,
repoVisibility,
apiBaseUrl: config.apiBaseUrl,
});
}
constructor(
private readonly config: {
token: string;
client: Octokit;
credentialsProvider: GithubCredentialsProvider;
repoVisibility: RepoVisibilityOptions;
apiBaseUrl: string | undefined;
},
) {}
@@ -59,9 +59,25 @@ export class GithubPublisher implements PublisherBase {
}: PublisherOptions): Promise<PublisherResult> {
const { owner, name } = parseGitUrl(values.storePath);
const { token } = await this.config.credentialsProvider.getCredentials({
url: values.storePath,
});
if (!token) {
throw new Error(
`No token could be acquired for URL: ${values.storePath}`,
);
}
const client = new Octokit({
auth: token,
baseUrl: this.config.apiBaseUrl,
});
const description = values.description as string;
const access = values.access as string;
const remoteUrl = await this.createRemote({
client,
description,
access,
name,
@@ -73,7 +89,7 @@ export class GithubPublisher implements PublisherBase {
remoteUrl,
auth: {
username: 'x-access-token',
password: this.config.token,
password: token,
},
logger,
});
@@ -86,27 +102,28 @@ export class GithubPublisher implements PublisherBase {
}
private async createRemote(opts: {
client: Octokit;
access: string;
name: string;
owner: string;
description: string;
}) {
const { access, description, owner, name } = opts;
const { client, access, description, owner, name } = opts;
const user = await this.config.client.users.getByUsername({
const user = await client.users.getByUsername({
username: owner,
});
const repoCreationPromise =
user.data.type === 'Organization'
? this.config.client.repos.createInOrg({
? client.repos.createInOrg({
name,
org: owner,
private: this.config.repoVisibility !== 'public',
visibility: this.config.repoVisibility,
description,
})
: this.config.client.repos.createForAuthenticatedUser({
: client.repos.createForAuthenticatedUser({
name,
private: this.config.repoVisibility === 'private',
description,
@@ -116,7 +133,7 @@ export class GithubPublisher implements PublisherBase {
if (access?.startsWith(`${owner}/`)) {
const [, team] = access.split('/');
await this.config.client.teams.addOrUpdateRepoPermissionsInOrg({
await client.teams.addOrUpdateRepoPermissionsInOrg({
org: owner,
team_slug: team,
owner,
@@ -125,7 +142,7 @@ export class GithubPublisher implements PublisherBase {
});
// no need to add access if it's the person who own's the personal account
} else if (access && access !== owner) {
await this.config.client.repos.addCollaborator({
await client.repos.addCollaborator({
owner,
repo: name,
username: access,