feat: added support for overriding the token used for publish actions.
Signed-off-by: blam <ben@blam.sh>
This commit is contained in:
+11
@@ -74,4 +74,15 @@ describe('getOctokit', () => {
|
||||
expect(owner).toBe('owner');
|
||||
expect(repo).toBe('bob');
|
||||
});
|
||||
|
||||
it('should return an octokit client with the passed in token if it is provided', async () => {
|
||||
const { client, token, owner, repo } = await octokitProvider.getOctokit(
|
||||
'github.com?repo=bob&owner=owner',
|
||||
{ token: 'tokenlols2' },
|
||||
);
|
||||
expect(client).toBeDefined();
|
||||
expect(token).toBe('tokenlols2');
|
||||
expect(owner).toBe('owner');
|
||||
expect(repo).toBe('bob');
|
||||
});
|
||||
});
|
||||
|
||||
+17
-2
@@ -52,7 +52,10 @@ export class OctokitProvider {
|
||||
*
|
||||
* @param repoUrl - Repository URL
|
||||
*/
|
||||
async getOctokit(repoUrl: string): Promise<OctokitIntegration> {
|
||||
async getOctokit(
|
||||
repoUrl: string,
|
||||
options?: { token?: string },
|
||||
): Promise<OctokitIntegration> {
|
||||
const { owner, repo, host } = parseRepoUrl(repoUrl, this.integrations);
|
||||
|
||||
if (!owner) {
|
||||
@@ -65,7 +68,19 @@ export class OctokitProvider {
|
||||
throw new InputError(`No integration for host ${host}`);
|
||||
}
|
||||
|
||||
// TODO(blam): Consider changing this API to have owner, repo interface instead of URL as the it's
|
||||
// Short circuit the internal Github Token provider the token provided
|
||||
// by the action or the caller.
|
||||
if (options?.token) {
|
||||
const client = new Octokit({
|
||||
auth: options.token,
|
||||
baseUrl: integrationConfig.apiBaseUrl,
|
||||
previews: ['nebula-preview'],
|
||||
});
|
||||
|
||||
return { client, token: options.token, owner, repo };
|
||||
}
|
||||
|
||||
// TODO(blam): Consider changing this API to have owner, repoo interface instead of URL as the it's
|
||||
// needless to create URL and then parse again the other side.
|
||||
const { token } = await this.githubCredentialsProvider.getCredentials({
|
||||
url: `https://${host}/${encodeURIComponent(owner)}/${encodeURIComponent(
|
||||
|
||||
+17
-3
@@ -37,6 +37,7 @@ export function createGithubActionsDispatchAction(options: {
|
||||
workflowId: string;
|
||||
branchOrTagName: string;
|
||||
workflowInputs?: { [key: string]: string };
|
||||
token?: string;
|
||||
}>({
|
||||
id: 'github:actions:dispatch',
|
||||
description:
|
||||
@@ -68,18 +69,31 @@ export function createGithubActionsDispatchAction(options: {
|
||||
'Inputs keys and values to send to GitHub Action configured on the workflow file. The maximum number of properties is 10. ',
|
||||
type: 'object',
|
||||
},
|
||||
token: {
|
||||
title: 'Authentication Token',
|
||||
type: 'string',
|
||||
description: 'The GITHUB_TOKEN to use for authorization to GitHub',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
async handler(ctx) {
|
||||
const { repoUrl, workflowId, branchOrTagName, workflowInputs } =
|
||||
ctx.input;
|
||||
const {
|
||||
repoUrl,
|
||||
workflowId,
|
||||
branchOrTagName,
|
||||
workflowInputs,
|
||||
token: providedToken,
|
||||
} = ctx.input;
|
||||
|
||||
ctx.logger.info(
|
||||
`Dispatching workflow ${workflowId} for repo ${repoUrl} on ${branchOrTagName}`,
|
||||
);
|
||||
|
||||
const { client, owner, repo } = await octokitProvider.getOctokit(repoUrl);
|
||||
const { client, owner, repo } = await octokitProvider.getOctokit(
|
||||
repoUrl,
|
||||
{ token: providedToken },
|
||||
);
|
||||
|
||||
await client.rest.actions.createWorkflowDispatch({
|
||||
owner,
|
||||
|
||||
@@ -47,6 +47,7 @@ export function createGithubWebhookAction(options: {
|
||||
active?: boolean;
|
||||
contentType?: ContentType;
|
||||
insecureSsl?: boolean;
|
||||
token?: string;
|
||||
}>({
|
||||
id: 'github:webhook',
|
||||
description: 'Creates webhook for a repository on GitHub.',
|
||||
@@ -107,6 +108,11 @@ export function createGithubWebhookAction(options: {
|
||||
type: 'boolean',
|
||||
description: `Determines whether the SSL certificate of the host for url will be verified when delivering payloads. Default 'false'`,
|
||||
},
|
||||
token: {
|
||||
title: 'Authentication Token',
|
||||
type: 'string',
|
||||
description: 'The GITHUB_TOKEN to use for authorization to GitHub',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -119,11 +125,15 @@ export function createGithubWebhookAction(options: {
|
||||
active = true,
|
||||
contentType = 'form',
|
||||
insecureSsl = false,
|
||||
token: providedToken,
|
||||
} = ctx.input;
|
||||
|
||||
ctx.logger.info(`Creating webhook ${webhookUrl} for repo ${repoUrl}`);
|
||||
|
||||
const { client, owner, repo } = await octokitProvider.getOctokit(repoUrl);
|
||||
const { client, owner, repo } = await octokitProvider.getOctokit(
|
||||
repoUrl,
|
||||
{ token: providedToken },
|
||||
);
|
||||
|
||||
try {
|
||||
const insecure_ssl = insecureSsl ? '1' : '0';
|
||||
|
||||
@@ -34,6 +34,7 @@ export function createPublishAzureAction(options: {
|
||||
description?: string;
|
||||
defaultBranch?: string;
|
||||
sourcePath?: string;
|
||||
token?: string;
|
||||
}>({
|
||||
id: 'publish:azure',
|
||||
description:
|
||||
@@ -57,10 +58,16 @@ export function createPublishAzureAction(options: {
|
||||
description: `Sets the default branch on the repository. The default value is 'master'`,
|
||||
},
|
||||
sourcePath: {
|
||||
title:
|
||||
title: 'Source Path',
|
||||
description:
|
||||
'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.',
|
||||
type: 'string',
|
||||
},
|
||||
token: {
|
||||
title: 'Authentication Token',
|
||||
type: 'string',
|
||||
description: 'The AZURE_TOKEN to use for authorization to Azure',
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
@@ -98,12 +105,13 @@ export function createPublishAzureAction(options: {
|
||||
`No matching integration configuration for host ${host}, please check your integrations config`,
|
||||
);
|
||||
}
|
||||
if (!integrationConfig.config.token) {
|
||||
|
||||
if (!integrationConfig.config.token && !ctx.input.token) {
|
||||
throw new InputError(`No token provided for Azure Integration ${host}`);
|
||||
}
|
||||
const authHandler = getPersonalAccessTokenHandler(
|
||||
integrationConfig.config.token,
|
||||
);
|
||||
|
||||
const token = ctx.input.token ?? integrationConfig.config.token!;
|
||||
const authHandler = getPersonalAccessTokenHandler(token);
|
||||
|
||||
const webApi = new WebApi(`https://${host}/${organization}`, authHandler);
|
||||
const client = await webApi.getGitApi();
|
||||
@@ -139,7 +147,7 @@ export function createPublishAzureAction(options: {
|
||||
defaultBranch,
|
||||
auth: {
|
||||
username: 'notempty',
|
||||
password: integrationConfig.config.token,
|
||||
password: token,
|
||||
},
|
||||
logger: ctx.logger,
|
||||
commitMessage: config.getOptionalString(
|
||||
|
||||
@@ -205,6 +205,7 @@ export function createPublishBitbucketAction(options: {
|
||||
repoVisibility: 'private' | 'public';
|
||||
sourcePath?: string;
|
||||
enableLFS: boolean;
|
||||
token?: string;
|
||||
}>({
|
||||
id: 'publish:bitbucket',
|
||||
description:
|
||||
@@ -233,15 +234,23 @@ export function createPublishBitbucketAction(options: {
|
||||
description: `Sets the default branch on the repository. The default value is 'master'`,
|
||||
},
|
||||
sourcePath: {
|
||||
title:
|
||||
title: 'Source Path',
|
||||
description:
|
||||
'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.',
|
||||
type: 'string',
|
||||
},
|
||||
enableLFS: {
|
||||
title:
|
||||
title: 'Enable LFS?',
|
||||
description:
|
||||
'Enable LFS for the repository. Only available for hosted Bitbucket.',
|
||||
type: 'boolean',
|
||||
},
|
||||
token: {
|
||||
title: 'Authentication Token',
|
||||
type: 'string',
|
||||
description:
|
||||
'The BITBUCKET_TOKEN to use for authorization to BitBucket',
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
@@ -296,7 +305,12 @@ export function createPublishBitbucketAction(options: {
|
||||
);
|
||||
}
|
||||
|
||||
const authorization = getAuthorizationHeader(integrationConfig.config);
|
||||
const authorization = getAuthorizationHeader(
|
||||
ctx.input.token
|
||||
? { host: integrationConfig.config.host, token: ctx.input.token }
|
||||
: integrationConfig.config,
|
||||
);
|
||||
|
||||
const apiBaseUrl = integrationConfig.config.apiBaseUrl;
|
||||
|
||||
const createMethod =
|
||||
@@ -320,17 +334,28 @@ export function createPublishBitbucketAction(options: {
|
||||
email: config.getOptionalString('scaffolder.defaultAuthor.email'),
|
||||
};
|
||||
|
||||
await initRepoAndPush({
|
||||
dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath),
|
||||
remoteUrl,
|
||||
auth: {
|
||||
let auth;
|
||||
|
||||
if (ctx.input.token) {
|
||||
auth = {
|
||||
username: 'x-token-auth',
|
||||
password: ctx.input.token,
|
||||
};
|
||||
} else {
|
||||
auth = {
|
||||
username: integrationConfig.config.username
|
||||
? integrationConfig.config.username
|
||||
: 'x-token-auth',
|
||||
password: integrationConfig.config.appPassword
|
||||
? integrationConfig.config.appPassword
|
||||
: integrationConfig.config.token ?? '',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
await initRepoAndPush({
|
||||
dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath),
|
||||
remoteUrl,
|
||||
auth,
|
||||
defaultBranch,
|
||||
logger: ctx.logger,
|
||||
commitMessage: config.getOptionalString(
|
||||
|
||||
@@ -52,6 +52,7 @@ export function createPublishGithubAction(options: {
|
||||
requireCodeOwnerReviews?: boolean;
|
||||
repoVisibility: 'private' | 'internal' | 'public';
|
||||
collaborators: Collaborator[];
|
||||
token?: string;
|
||||
topics?: string[];
|
||||
}>({
|
||||
id: 'publish:github',
|
||||
@@ -77,7 +78,8 @@ export function createPublishGithubAction(options: {
|
||||
type: 'string',
|
||||
},
|
||||
requireCodeOwnerReviews: {
|
||||
title:
|
||||
title: 'Require CODEOWNER Reviews?',
|
||||
description:
|
||||
'Require an approved review in PR including files with a designated Code Owner',
|
||||
type: 'boolean',
|
||||
},
|
||||
@@ -92,7 +94,8 @@ export function createPublishGithubAction(options: {
|
||||
description: `Sets the default branch on the repository. The default value is 'master'`,
|
||||
},
|
||||
sourcePath: {
|
||||
title:
|
||||
title: 'Source Path',
|
||||
description:
|
||||
'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.',
|
||||
type: 'string',
|
||||
},
|
||||
@@ -116,6 +119,11 @@ export function createPublishGithubAction(options: {
|
||||
},
|
||||
},
|
||||
},
|
||||
token: {
|
||||
title: 'Authentication Token',
|
||||
type: 'string',
|
||||
description: 'The GITHUB_TOKEN to use for authorization to GitHub',
|
||||
},
|
||||
topics: {
|
||||
title: 'Topics',
|
||||
type: 'array',
|
||||
@@ -149,10 +157,12 @@ export function createPublishGithubAction(options: {
|
||||
defaultBranch = 'master',
|
||||
collaborators,
|
||||
topics,
|
||||
token: providedToken,
|
||||
} = ctx.input;
|
||||
|
||||
const { client, token, owner, repo } = await octokitProvider.getOctokit(
|
||||
repoUrl,
|
||||
{ token: providedToken },
|
||||
);
|
||||
|
||||
const user = await client.rest.users.getByUsername({
|
||||
|
||||
+19
-2
@@ -55,6 +55,7 @@ export type GithubPullRequestActionInput = {
|
||||
repoUrl: string;
|
||||
targetPath?: string;
|
||||
sourcePath?: string;
|
||||
token?: string;
|
||||
};
|
||||
|
||||
export type ClientFactoryInput = {
|
||||
@@ -63,6 +64,7 @@ export type ClientFactoryInput = {
|
||||
host: string;
|
||||
owner: string;
|
||||
repo: string;
|
||||
token?: string;
|
||||
};
|
||||
|
||||
export const defaultClientFactory = async ({
|
||||
@@ -71,13 +73,22 @@ export const defaultClientFactory = async ({
|
||||
owner,
|
||||
repo,
|
||||
host = 'github.com',
|
||||
token: providedToken,
|
||||
}: ClientFactoryInput): Promise<PullRequestCreator> => {
|
||||
const integrationConfig = integrations.github.byHost(host)?.config;
|
||||
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);
|
||||
@@ -94,8 +105,6 @@ export const defaultClientFactory = async ({
|
||||
);
|
||||
}
|
||||
|
||||
const OctokitPR = Octokit.plugin(createPullRequest);
|
||||
|
||||
return new OctokitPR({
|
||||
auth: token,
|
||||
baseUrl: integrationConfig.apiBaseUrl,
|
||||
@@ -151,6 +160,11 @@ export const createPublishGithubPullRequestAction = ({
|
||||
title: 'Repository Subdirectory',
|
||||
description: 'Subdirectory of repository to apply changes to',
|
||||
},
|
||||
token: {
|
||||
title: 'Authentication Token',
|
||||
type: 'string',
|
||||
description: 'The GITHUB_TOKEN to use for authorization to GitHub',
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
@@ -173,6 +187,7 @@ export const createPublishGithubPullRequestAction = ({
|
||||
description,
|
||||
targetPath,
|
||||
sourcePath,
|
||||
token: providedToken,
|
||||
} = ctx.input;
|
||||
|
||||
const { owner, repo, host } = parseRepoUrl(repoUrl, integrations);
|
||||
@@ -189,7 +204,9 @@ export const createPublishGithubPullRequestAction = ({
|
||||
host,
|
||||
owner,
|
||||
repo,
|
||||
token: providedToken,
|
||||
});
|
||||
|
||||
const fileRoot = sourcePath
|
||||
? resolveSafeChildPath(ctx.workspacePath, sourcePath)
|
||||
: ctx.workspacePath;
|
||||
|
||||
@@ -33,6 +33,7 @@ export function createPublishGitlabAction(options: {
|
||||
defaultBranch?: string;
|
||||
repoVisibility: 'private' | 'internal' | 'public';
|
||||
sourcePath?: string;
|
||||
token?: string;
|
||||
}>({
|
||||
id: 'publish:gitlab',
|
||||
description:
|
||||
@@ -57,10 +58,16 @@ export function createPublishGitlabAction(options: {
|
||||
description: `Sets the default branch on the repository. The default value is 'master'`,
|
||||
},
|
||||
sourcePath: {
|
||||
title:
|
||||
title: 'Source Path',
|
||||
description:
|
||||
'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.',
|
||||
type: 'string',
|
||||
},
|
||||
token: {
|
||||
title: 'Authentication Token',
|
||||
type: 'string',
|
||||
description: 'The GITLAB_TOKEN to use for authorization to GitLab',
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
@@ -100,13 +107,15 @@ export function createPublishGitlabAction(options: {
|
||||
);
|
||||
}
|
||||
|
||||
if (!integrationConfig.config.token) {
|
||||
if (!integrationConfig.config.token && !ctx.input.token) {
|
||||
throw new InputError(`No token available for host ${host}`);
|
||||
}
|
||||
|
||||
const token = ctx.input.token || integrationConfig.config.token!;
|
||||
|
||||
const client = new Gitlab({
|
||||
host: integrationConfig.config.baseUrl,
|
||||
token: integrationConfig.config.token,
|
||||
token,
|
||||
});
|
||||
|
||||
let { id: targetNamespace } = (await client.Namespaces.show(owner)) as {
|
||||
@@ -140,7 +149,7 @@ export function createPublishGitlabAction(options: {
|
||||
defaultBranch,
|
||||
auth: {
|
||||
username: 'oauth2',
|
||||
password: integrationConfig.config.token,
|
||||
password: token,
|
||||
},
|
||||
logger: ctx.logger,
|
||||
commitMessage: config.getOptionalString(
|
||||
|
||||
+10
-2
@@ -31,6 +31,7 @@ export type GitlabMergeRequestActionInput = {
|
||||
description: string;
|
||||
branchName: string;
|
||||
targetPath: string;
|
||||
token?: string;
|
||||
};
|
||||
|
||||
export const createPublishGitlabMergeRequestAction = (options: {
|
||||
@@ -75,6 +76,11 @@ export const createPublishGitlabMergeRequestAction = (options: {
|
||||
title: 'Repository Subdirectory',
|
||||
description: 'Subdirectory of repository to apply changes to',
|
||||
},
|
||||
token: {
|
||||
title: 'Authentication Token',
|
||||
type: 'string',
|
||||
description: 'The GITLAB_TOKEN to use for authorization to GitLab',
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
@@ -107,13 +113,15 @@ export const createPublishGitlabMergeRequestAction = (options: {
|
||||
);
|
||||
}
|
||||
|
||||
if (!integrationConfig.config.token) {
|
||||
if (!integrationConfig.config.token && !ctx.input.token) {
|
||||
throw new InputError(`No token available for host ${host}`);
|
||||
}
|
||||
|
||||
const token = ctx.input.token ?? integrationConfig.config.token!;
|
||||
|
||||
const api = new Gitlab({
|
||||
host: integrationConfig.config.baseUrl,
|
||||
token: integrationConfig.config.token,
|
||||
token,
|
||||
});
|
||||
|
||||
const fileRoot = ctx.workspacePath;
|
||||
|
||||
Reference in New Issue
Block a user