feat: allow signing git commits from scaffolder
adds support to sign git commits with configured PGP key in scaffolder actions. configuration can be done either by integration or by using the default signing key in the scaffolder config. note that this pgp-plugin is used for signing and that it is limited to using RSA keys and signatures made with SHA1 hashing algorithm. this change does not support github commit signing as it cannot be done the same way due to GitHub app and REST API being used. closes #25934 refers to #26333 Signed-off-by: Heikki Hellgren <heikki.hellgren@op.fi>
This commit is contained in:
committed by
Hellgren Heikki
parent
37416e06d6
commit
4f8b5b66a1
@@ -0,0 +1,14 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend-module-bitbucket-server': patch
|
||||
'@backstage/plugin-scaffolder-backend-module-bitbucket-cloud': patch
|
||||
'@backstage/plugin-scaffolder-backend-module-bitbucket': patch
|
||||
'@backstage/plugin-scaffolder-backend-module-gerrit': patch
|
||||
'@backstage/plugin-scaffolder-backend-module-gitlab': patch
|
||||
'@backstage/plugin-scaffolder-backend-module-azure': patch
|
||||
'@backstage/plugin-scaffolder-backend-module-gitea': patch
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
'@backstage/plugin-scaffolder-node': patch
|
||||
'@backstage/integration': patch
|
||||
---
|
||||
|
||||
Allow signing git commits using configured private PGP key in scaffolder
|
||||
Vendored
+32
@@ -62,6 +62,10 @@ export interface Config {
|
||||
tenantId?: string;
|
||||
personalAccessToken?: string;
|
||||
}[];
|
||||
/**
|
||||
* PGP signing key for signing commits.
|
||||
*/
|
||||
commitSigningKey?: string;
|
||||
}>;
|
||||
|
||||
/**
|
||||
@@ -94,6 +98,10 @@ export interface Config {
|
||||
* @visibility secret
|
||||
*/
|
||||
appPassword?: string;
|
||||
/**
|
||||
* PGP signing key for signing commits.
|
||||
*/
|
||||
commitSigningKey?: string;
|
||||
}>;
|
||||
|
||||
/** Integration configuration for Bitbucket Cloud */
|
||||
@@ -108,6 +116,10 @@ export interface Config {
|
||||
* @visibility secret
|
||||
*/
|
||||
appPassword: string;
|
||||
/**
|
||||
* PGP signing key for signing commits.
|
||||
*/
|
||||
commitSigningKey?: string;
|
||||
}>;
|
||||
|
||||
/** Integration configuration for Bitbucket Server */
|
||||
@@ -137,6 +149,10 @@ export interface Config {
|
||||
* @visibility frontend
|
||||
*/
|
||||
apiBaseUrl?: string;
|
||||
/**
|
||||
* PGP signing key for signing commits.
|
||||
*/
|
||||
commitSigningKey?: string;
|
||||
}>;
|
||||
|
||||
/** Integration configuration for Gerrit */
|
||||
@@ -172,6 +188,10 @@ export interface Config {
|
||||
* @visibility secret
|
||||
*/
|
||||
password?: string;
|
||||
/**
|
||||
* PGP signing key for signing commits.
|
||||
*/
|
||||
commitSigningKey?: string;
|
||||
}>;
|
||||
|
||||
/** Integration configuration for GitHub */
|
||||
@@ -233,6 +253,10 @@ export interface Config {
|
||||
*/
|
||||
allowedInstallationOwners?: string[];
|
||||
}>;
|
||||
/**
|
||||
* PGP signing key for signing commits.
|
||||
*/
|
||||
commitSigningKey?: string;
|
||||
}>;
|
||||
|
||||
/** Integration configuration for GitLab */
|
||||
@@ -269,6 +293,10 @@ export interface Config {
|
||||
* @visibility frontend
|
||||
*/
|
||||
baseUrl?: string;
|
||||
/**
|
||||
* PGP signing key for signing commits.
|
||||
*/
|
||||
commitSigningKey?: string;
|
||||
}>;
|
||||
|
||||
/** Integration configuration for Google Cloud Storage */
|
||||
@@ -349,6 +377,10 @@ export interface Config {
|
||||
* @visibility secret
|
||||
*/
|
||||
password?: string;
|
||||
/**
|
||||
* PGP signing key for signing commits.
|
||||
*/
|
||||
commitSigningKey?: string;
|
||||
}>;
|
||||
/** Integration configuration for Harness Code */
|
||||
harness?: Array<{
|
||||
|
||||
@@ -201,6 +201,7 @@ export type AzureIntegrationConfig = {
|
||||
token?: string;
|
||||
credential?: AzureDevOpsCredential;
|
||||
credentials?: AzureDevOpsCredential[];
|
||||
commitSigningKey?: string;
|
||||
};
|
||||
|
||||
// @public
|
||||
@@ -237,6 +238,7 @@ export type BitbucketCloudIntegrationConfig = {
|
||||
username?: string;
|
||||
appPassword?: string;
|
||||
token?: string;
|
||||
commitSigningKey?: string;
|
||||
};
|
||||
|
||||
// @public @deprecated
|
||||
@@ -267,6 +269,7 @@ export type BitbucketIntegrationConfig = {
|
||||
token?: string;
|
||||
username?: string;
|
||||
appPassword?: string;
|
||||
signingKey?: string;
|
||||
};
|
||||
|
||||
// @public
|
||||
@@ -297,6 +300,7 @@ export type BitbucketServerIntegrationConfig = {
|
||||
token?: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
commitSigningKey?: string;
|
||||
};
|
||||
|
||||
// @public @deprecated
|
||||
@@ -395,6 +399,7 @@ export type GerritIntegrationConfig = {
|
||||
gitilesBaseUrl: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
commitSigningKey?: string;
|
||||
};
|
||||
|
||||
// @public
|
||||
@@ -630,6 +635,7 @@ export type GiteaIntegrationConfig = {
|
||||
baseUrl?: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
commitSigningKey?: string;
|
||||
};
|
||||
|
||||
// @public
|
||||
@@ -744,6 +750,7 @@ export type GitLabIntegrationConfig = {
|
||||
apiBaseUrl: string;
|
||||
token?: string;
|
||||
baseUrl: string;
|
||||
commitSigningKey?: string;
|
||||
};
|
||||
|
||||
// @public
|
||||
|
||||
@@ -57,6 +57,11 @@ export type AzureIntegrationConfig = {
|
||||
* If no credentials are specified at all, either a default credential (for Azure DevOps) or anonymous access (for Azure DevOps Server) is used.
|
||||
*/
|
||||
credentials?: AzureDevOpsCredential[];
|
||||
|
||||
/**
|
||||
* Signing key for commits
|
||||
*/
|
||||
commitSigningKey?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -349,6 +354,7 @@ export function readAzureIntegrationConfig(
|
||||
return {
|
||||
host,
|
||||
credentials,
|
||||
commitSigningKey: config.getOptionalString('commitSigningKey'),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,11 @@ export type BitbucketIntegrationConfig = {
|
||||
* See https://support.atlassian.com/bitbucket-cloud/docs/app-passwords/
|
||||
*/
|
||||
appPassword?: string;
|
||||
|
||||
/**
|
||||
* Signing key for commits
|
||||
*/
|
||||
signingKey?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -100,6 +105,7 @@ export function readBitbucketIntegrationConfig(
|
||||
token,
|
||||
username,
|
||||
appPassword,
|
||||
signingKey: config.getOptionalString('signingKey'),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,9 @@ export type BitbucketCloudIntegrationConfig = {
|
||||
* The access token to use for requests to Bitbucket Cloud (bitbucket.org).
|
||||
*/
|
||||
token?: string;
|
||||
|
||||
/** PGP private key for signing commits. */
|
||||
commitSigningKey?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -74,6 +77,7 @@ export function readBitbucketCloudIntegrationConfig(
|
||||
apiBaseUrl,
|
||||
username,
|
||||
appPassword,
|
||||
commitSigningKey: config.getOptionalString('commitSigningKey'),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,11 @@ export type BitbucketServerIntegrationConfig = {
|
||||
* See https://developer.atlassian.com/server/bitbucket/how-tos/command-line-rest/#authentication
|
||||
*/
|
||||
password?: string;
|
||||
|
||||
/**
|
||||
* Signing key for commits
|
||||
*/
|
||||
commitSigningKey?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -99,6 +104,7 @@ export function readBitbucketServerIntegrationConfig(
|
||||
token,
|
||||
username,
|
||||
password,
|
||||
commitSigningKey: config.getOptionalString('commitSigningKey'),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,11 @@ export type GerritIntegrationConfig = {
|
||||
* The password or http token to use for authentication.
|
||||
*/
|
||||
password?: string;
|
||||
|
||||
/**
|
||||
* The signing key to use for signing commits.
|
||||
*/
|
||||
commitSigningKey?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -119,6 +124,7 @@ export function readGerritIntegrationConfig(
|
||||
gitilesBaseUrl,
|
||||
username,
|
||||
password,
|
||||
commitSigningKey: config.getOptionalString('commitSigningKey'),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,11 @@ export type GiteaIntegrationConfig = {
|
||||
* The password or http token to use for authentication.
|
||||
*/
|
||||
password?: string;
|
||||
|
||||
/**
|
||||
* Signing key to to sign commits
|
||||
*/
|
||||
commitSigningKey?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -79,5 +84,6 @@ export function readGiteaConfig(config: Config): GiteaIntegrationConfig {
|
||||
baseUrl,
|
||||
username,
|
||||
password,
|
||||
commitSigningKey: config.getOptionalString('commitSigningKey'),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -54,6 +54,11 @@ export type GitLabIntegrationConfig = {
|
||||
* If no baseUrl is provided, it will default to `https://${host}`
|
||||
*/
|
||||
baseUrl: string;
|
||||
|
||||
/**
|
||||
* Signing key to sign commits
|
||||
*/
|
||||
commitSigningKey?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -95,7 +100,13 @@ export function readGitLabIntegrationConfig(
|
||||
);
|
||||
}
|
||||
|
||||
return { host, token, apiBaseUrl, baseUrl };
|
||||
return {
|
||||
host,
|
||||
token,
|
||||
apiBaseUrl,
|
||||
baseUrl,
|
||||
commitSigningKey: config.getOptionalString('commitSigningKey'),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,6 +27,7 @@ export function createPublishAzureAction(options: {
|
||||
gitCommitMessage?: string;
|
||||
gitAuthorName?: string;
|
||||
gitAuthorEmail?: string;
|
||||
signCommit?: boolean;
|
||||
},
|
||||
JsonObject
|
||||
>;
|
||||
|
||||
@@ -20,10 +20,10 @@ import {
|
||||
ScmIntegrationRegistry,
|
||||
} from '@backstage/integration';
|
||||
import {
|
||||
initRepoAndPush,
|
||||
getRepoSourceDirectory,
|
||||
parseRepoUrl,
|
||||
createTemplateAction,
|
||||
getRepoSourceDirectory,
|
||||
initRepoAndPush,
|
||||
parseRepoUrl,
|
||||
} from '@backstage/plugin-scaffolder-node';
|
||||
import { GitRepositoryCreateOptions } from 'azure-devops-node-api/interfaces/GitInterfaces';
|
||||
import {
|
||||
@@ -54,6 +54,7 @@ export function createPublishAzureAction(options: {
|
||||
gitCommitMessage?: string;
|
||||
gitAuthorName?: string;
|
||||
gitAuthorEmail?: string;
|
||||
signCommit?: boolean;
|
||||
}>({
|
||||
id: 'publish:azure',
|
||||
examples,
|
||||
@@ -103,6 +104,11 @@ export function createPublishAzureAction(options: {
|
||||
type: 'string',
|
||||
description: 'The token to use for authorization to Azure',
|
||||
},
|
||||
signCommit: {
|
||||
title: 'Sign commit',
|
||||
type: 'boolean',
|
||||
description: 'Sign commit with configured PGP private key',
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
@@ -134,6 +140,7 @@ export function createPublishAzureAction(options: {
|
||||
gitCommitMessage = 'initial commit',
|
||||
gitAuthorName,
|
||||
gitAuthorEmail,
|
||||
signCommit,
|
||||
} = ctx.input;
|
||||
|
||||
const { project, repo, host, organization } = parseRepoUrl(
|
||||
@@ -151,6 +158,7 @@ export function createPublishAzureAction(options: {
|
||||
const credentialProvider =
|
||||
DefaultAzureDevOpsCredentialsProvider.fromIntegrations(integrations);
|
||||
const credentials = await credentialProvider.getCredentials({ url: url });
|
||||
const integrationConfig = integrations.azure.byHost(host);
|
||||
|
||||
if (credentials === undefined && ctx.input.token === undefined) {
|
||||
throw new InputError(
|
||||
@@ -212,6 +220,15 @@ export function createPublishAzureAction(options: {
|
||||
password: ctx.input.token ?? credentials!.token,
|
||||
};
|
||||
|
||||
const signingKey =
|
||||
integrationConfig?.config.commitSigningKey ??
|
||||
config.getOptionalString('scaffolder.defaultCommitSigningKey');
|
||||
if (signCommit && !signingKey) {
|
||||
throw new Error(
|
||||
'Signing commits is enabled but no signing key is provided in the configuration',
|
||||
);
|
||||
}
|
||||
|
||||
const commitResult = await initRepoAndPush({
|
||||
dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath),
|
||||
remoteUrl,
|
||||
@@ -222,6 +239,7 @@ export function createPublishAzureAction(options: {
|
||||
? gitCommitMessage
|
||||
: config.getOptionalString('scaffolder.defaultCommitMessage'),
|
||||
gitAuthorInfo,
|
||||
signingKey: signCommit ? signingKey : undefined,
|
||||
});
|
||||
|
||||
ctx.output('commitHash', commitResult?.commitHash);
|
||||
|
||||
@@ -39,6 +39,7 @@ export function createPublishBitbucketCloudAction(options: {
|
||||
gitCommitMessage?: string;
|
||||
sourcePath?: string;
|
||||
token?: string;
|
||||
signCommit?: boolean;
|
||||
},
|
||||
JsonObject
|
||||
>;
|
||||
|
||||
@@ -18,8 +18,8 @@ import { InputError } from '@backstage/errors';
|
||||
import { ScmIntegrationRegistry } from '@backstage/integration';
|
||||
import {
|
||||
createTemplateAction,
|
||||
initRepoAndPush,
|
||||
getRepoSourceDirectory,
|
||||
initRepoAndPush,
|
||||
parseRepoUrl,
|
||||
} from '@backstage/plugin-scaffolder-node';
|
||||
|
||||
@@ -113,6 +113,7 @@ export function createPublishBitbucketCloudAction(options: {
|
||||
gitCommitMessage?: string;
|
||||
sourcePath?: string;
|
||||
token?: string;
|
||||
signCommit?: boolean;
|
||||
}>({
|
||||
id: 'publish:bitbucketCloud',
|
||||
examples,
|
||||
@@ -158,6 +159,11 @@ export function createPublishBitbucketCloudAction(options: {
|
||||
description:
|
||||
'The token to use for authorization to BitBucket Cloud',
|
||||
},
|
||||
signCommit: {
|
||||
title: 'Sign commit',
|
||||
type: 'boolean',
|
||||
description: 'Sign commit with configured PGP private key',
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
@@ -185,6 +191,7 @@ export function createPublishBitbucketCloudAction(options: {
|
||||
defaultBranch = 'master',
|
||||
gitCommitMessage,
|
||||
repoVisibility = 'private',
|
||||
signCommit,
|
||||
} = ctx.input;
|
||||
|
||||
const { workspace, project, repo, host } = parseRepoUrl(
|
||||
@@ -256,6 +263,15 @@ export function createPublishBitbucketCloudAction(options: {
|
||||
};
|
||||
}
|
||||
|
||||
const signingKey =
|
||||
integrationConfig.config.commitSigningKey ??
|
||||
config.getOptionalString('scaffolder.defaultCommitSigningKey');
|
||||
if (signCommit && !signingKey) {
|
||||
throw new Error(
|
||||
'Signing commits is enabled but no signing key is provided in the configuration',
|
||||
);
|
||||
}
|
||||
|
||||
const commitResult = await initRepoAndPush({
|
||||
dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath),
|
||||
remoteUrl,
|
||||
@@ -266,6 +282,7 @@ export function createPublishBitbucketCloudAction(options: {
|
||||
gitCommitMessage ||
|
||||
config.getOptionalString('scaffolder.defaultCommitMessage'),
|
||||
gitAuthorInfo,
|
||||
signingKey: signCommit ? signingKey : undefined,
|
||||
});
|
||||
|
||||
ctx.output('commitHash', commitResult?.commitHash);
|
||||
|
||||
@@ -29,6 +29,7 @@ export function createPublishBitbucketServerAction(options: {
|
||||
gitCommitMessage?: string;
|
||||
gitAuthorName?: string;
|
||||
gitAuthorEmail?: string;
|
||||
signCommit?: boolean;
|
||||
},
|
||||
JsonObject
|
||||
>;
|
||||
|
||||
@@ -21,8 +21,8 @@ import {
|
||||
} from '@backstage/integration';
|
||||
import {
|
||||
createTemplateAction,
|
||||
initRepoAndPush,
|
||||
getRepoSourceDirectory,
|
||||
initRepoAndPush,
|
||||
parseRepoUrl,
|
||||
} from '@backstage/plugin-scaffolder-node';
|
||||
|
||||
@@ -137,6 +137,7 @@ export function createPublishBitbucketServerAction(options: {
|
||||
gitCommitMessage?: string;
|
||||
gitAuthorName?: string;
|
||||
gitAuthorEmail?: string;
|
||||
signCommit?: boolean;
|
||||
}>({
|
||||
id: 'publish:bitbucketServer',
|
||||
description:
|
||||
@@ -197,6 +198,11 @@ export function createPublishBitbucketServerAction(options: {
|
||||
type: 'string',
|
||||
description: `Sets the author email for the commit.`,
|
||||
},
|
||||
signCommit: {
|
||||
title: 'Sign commit',
|
||||
type: 'boolean',
|
||||
description: 'Sign commit with configured PGP private key',
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
@@ -227,6 +233,7 @@ export function createPublishBitbucketServerAction(options: {
|
||||
gitCommitMessage = 'initial commit',
|
||||
gitAuthorName,
|
||||
gitAuthorEmail,
|
||||
signCommit,
|
||||
} = ctx.input;
|
||||
|
||||
const { project, repo, host } = parseRepoUrl(repoUrl, integrations);
|
||||
@@ -279,6 +286,15 @@ export function createPublishBitbucketServerAction(options: {
|
||||
: config.getOptionalString('scaffolder.defaultAuthor.email'),
|
||||
};
|
||||
|
||||
const signingKey =
|
||||
integrationConfig.config.commitSigningKey ??
|
||||
config.getOptionalString('scaffolder.defaultCommitSigningKey');
|
||||
if (signCommit && !signingKey) {
|
||||
throw new Error(
|
||||
'Signing commits is enabled but no signing key is provided in the configuration',
|
||||
);
|
||||
}
|
||||
|
||||
const auth = authConfig.token
|
||||
? {
|
||||
token: token!,
|
||||
@@ -298,6 +314,7 @@ export function createPublishBitbucketServerAction(options: {
|
||||
? gitCommitMessage
|
||||
: config.getOptionalString('scaffolder.defaultCommitMessage'),
|
||||
gitAuthorInfo,
|
||||
signingKey: signCommit ? signingKey : undefined,
|
||||
});
|
||||
|
||||
if (enableLFS) {
|
||||
|
||||
@@ -44,6 +44,7 @@ export function createPublishBitbucketAction(options: {
|
||||
gitCommitMessage?: string;
|
||||
gitAuthorName?: string;
|
||||
gitAuthorEmail?: string;
|
||||
signCommit?: boolean;
|
||||
},
|
||||
JsonObject
|
||||
>;
|
||||
|
||||
@@ -21,8 +21,8 @@ import {
|
||||
} from '@backstage/integration';
|
||||
import {
|
||||
createTemplateAction,
|
||||
initRepoAndPush,
|
||||
getRepoSourceDirectory,
|
||||
initRepoAndPush,
|
||||
parseRepoUrl,
|
||||
} from '@backstage/plugin-scaffolder-node';
|
||||
import { Config } from '@backstage/config';
|
||||
@@ -220,6 +220,7 @@ export function createPublishBitbucketAction(options: {
|
||||
gitCommitMessage?: string;
|
||||
gitAuthorName?: string;
|
||||
gitAuthorEmail?: string;
|
||||
signCommit?: boolean;
|
||||
}>({
|
||||
id: 'publish:bitbucket',
|
||||
description:
|
||||
@@ -280,6 +281,11 @@ export function createPublishBitbucketAction(options: {
|
||||
type: 'string',
|
||||
description: `Sets the default author email for the commit.`,
|
||||
},
|
||||
signCommit: {
|
||||
title: 'Sign commit',
|
||||
type: 'boolean',
|
||||
description: 'Sign commit with configured PGP private key',
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
@@ -313,6 +319,7 @@ export function createPublishBitbucketAction(options: {
|
||||
gitCommitMessage = 'initial commit',
|
||||
gitAuthorName,
|
||||
gitAuthorEmail,
|
||||
signCommit,
|
||||
} = ctx.input;
|
||||
|
||||
const { workspace, project, repo, host } = parseRepoUrl(
|
||||
@@ -380,6 +387,14 @@ export function createPublishBitbucketAction(options: {
|
||||
? gitAuthorEmail
|
||||
: config.getOptionalString('scaffolder.defaultAuthor.email'),
|
||||
};
|
||||
const signingKey =
|
||||
integrationConfig.config.signingKey ??
|
||||
config.getOptionalString('scaffolder.defaultSigningKey');
|
||||
if (signCommit && !signingKey) {
|
||||
throw new Error(
|
||||
'Signing commits is enabled but no signing key is provided in the configuration',
|
||||
);
|
||||
}
|
||||
|
||||
let auth;
|
||||
|
||||
@@ -409,6 +424,7 @@ export function createPublishBitbucketAction(options: {
|
||||
? gitCommitMessage
|
||||
: config.getOptionalString('scaffolder.defaultCommitMessage'),
|
||||
gitAuthorInfo,
|
||||
signingKey: signCommit ? signingKey : undefined,
|
||||
});
|
||||
|
||||
if (enableLFS && host !== 'bitbucket.org') {
|
||||
|
||||
@@ -22,6 +22,7 @@ export function createPublishGerritAction(options: {
|
||||
gitAuthorName?: string;
|
||||
gitAuthorEmail?: string;
|
||||
sourcePath?: string;
|
||||
signCommit?: boolean;
|
||||
},
|
||||
JsonObject
|
||||
>;
|
||||
@@ -38,6 +39,7 @@ export function createPublishGerritReviewAction(options: {
|
||||
gitCommitMessage?: string;
|
||||
gitAuthorName?: string;
|
||||
gitAuthorEmail?: string;
|
||||
signCommit?: boolean;
|
||||
},
|
||||
JsonObject
|
||||
>;
|
||||
|
||||
@@ -24,8 +24,8 @@ import {
|
||||
} from '@backstage/integration';
|
||||
import {
|
||||
createTemplateAction,
|
||||
initRepoAndPush,
|
||||
getRepoSourceDirectory,
|
||||
initRepoAndPush,
|
||||
parseRepoUrl,
|
||||
} from '@backstage/plugin-scaffolder-node';
|
||||
import { examples } from './gerrit.examples';
|
||||
@@ -99,6 +99,7 @@ export function createPublishGerritAction(options: {
|
||||
gitAuthorName?: string;
|
||||
gitAuthorEmail?: string;
|
||||
sourcePath?: string;
|
||||
signCommit?: boolean;
|
||||
}>({
|
||||
id: 'publish:gerrit',
|
||||
supportsDryRun: true,
|
||||
@@ -143,6 +144,11 @@ export function createPublishGerritAction(options: {
|
||||
type: 'string',
|
||||
description: `Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.`,
|
||||
},
|
||||
signCommit: {
|
||||
title: 'Sign commit',
|
||||
type: 'boolean',
|
||||
description: 'Sign commit with configured PGP private key',
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
@@ -172,6 +178,7 @@ export function createPublishGerritAction(options: {
|
||||
gitAuthorEmail,
|
||||
gitCommitMessage = 'initial commit',
|
||||
sourcePath,
|
||||
signCommit,
|
||||
} = ctx.input;
|
||||
const { repo, host, owner, workspace } = parseRepoUrl(
|
||||
repoUrl,
|
||||
@@ -233,6 +240,15 @@ export function createPublishGerritAction(options: {
|
||||
email: gitEmail,
|
||||
};
|
||||
|
||||
const signingKey =
|
||||
integrationConfig.config.commitSigningKey ??
|
||||
config.getOptionalString('scaffolder.defaultCommitSigningKey');
|
||||
if (signCommit && !signingKey) {
|
||||
throw new Error(
|
||||
'Signing commits is enabled but no signing key is provided in the configuration',
|
||||
);
|
||||
}
|
||||
|
||||
const commitResult = await initRepoAndPush({
|
||||
dir: getRepoSourceDirectory(ctx.workspacePath, sourcePath),
|
||||
remoteUrl,
|
||||
@@ -241,6 +257,7 @@ export function createPublishGerritAction(options: {
|
||||
logger: ctx.logger,
|
||||
commitMessage: generateCommitMessage(config, gitCommitMessage),
|
||||
gitAuthorInfo,
|
||||
signingKey: signCommit ? signingKey : undefined,
|
||||
});
|
||||
|
||||
ctx.output('remoteUrl', remoteUrl);
|
||||
|
||||
@@ -19,8 +19,8 @@ import { InputError } from '@backstage/errors';
|
||||
import { Config } from '@backstage/config';
|
||||
import { ScmIntegrationRegistry } from '@backstage/integration';
|
||||
import {
|
||||
createTemplateAction,
|
||||
commitAndPushRepo,
|
||||
createTemplateAction,
|
||||
getRepoSourceDirectory,
|
||||
parseRepoUrl,
|
||||
} from '@backstage/plugin-scaffolder-node';
|
||||
@@ -48,6 +48,7 @@ export function createPublishGerritReviewAction(options: {
|
||||
gitCommitMessage?: string;
|
||||
gitAuthorName?: string;
|
||||
gitAuthorEmail?: string;
|
||||
signCommit?: boolean;
|
||||
}>({
|
||||
id: 'publish:gerrit:review',
|
||||
description: 'Creates a new Gerrit review.',
|
||||
@@ -88,6 +89,11 @@ export function createPublishGerritReviewAction(options: {
|
||||
type: 'string',
|
||||
description: `Sets the default author email for the commit.`,
|
||||
},
|
||||
signCommit: {
|
||||
title: 'Sign commit',
|
||||
type: 'boolean',
|
||||
description: 'Sign commit with configured PGP private key',
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
@@ -112,6 +118,7 @@ export function createPublishGerritReviewAction(options: {
|
||||
gitAuthorName,
|
||||
gitAuthorEmail,
|
||||
gitCommitMessage,
|
||||
signCommit,
|
||||
} = ctx.input;
|
||||
const { host, repo } = parseRepoUrl(repoUrl, integrations);
|
||||
|
||||
@@ -139,6 +146,14 @@ export function createPublishGerritReviewAction(options: {
|
||||
? gitAuthorEmail
|
||||
: config.getOptionalString('scaffolder.defaultAuthor.email'),
|
||||
};
|
||||
const signingKey =
|
||||
integrationConfig.config.commitSigningKey ??
|
||||
config.getOptionalString('scaffolder.defaultCommitSigningKey');
|
||||
if (signCommit && !signingKey) {
|
||||
throw new Error(
|
||||
'Signing commits is enabled but no signing key is provided in the configuration',
|
||||
);
|
||||
}
|
||||
const changeId = generateGerritChangeId();
|
||||
const commitMessage = `${gitCommitMessage}\n\nChange-Id: ${changeId}`;
|
||||
|
||||
@@ -150,6 +165,7 @@ export function createPublishGerritReviewAction(options: {
|
||||
gitAuthorInfo,
|
||||
branch,
|
||||
remoteRef: `refs/for/${branch}`,
|
||||
signingKey: signCommit ? signingKey : undefined,
|
||||
});
|
||||
|
||||
const repoContentsUrl = `${integrationConfig.config.gitilesBaseUrl}/${repo}/+/refs/heads/${branch}`;
|
||||
|
||||
@@ -23,6 +23,7 @@ export function createPublishGiteaAction(options: {
|
||||
gitAuthorName?: string;
|
||||
gitAuthorEmail?: string;
|
||||
sourcePath?: string;
|
||||
signCommit?: boolean;
|
||||
},
|
||||
JsonObject
|
||||
>;
|
||||
|
||||
@@ -219,6 +219,7 @@ export function createPublishGiteaAction(options: {
|
||||
gitAuthorName?: string;
|
||||
gitAuthorEmail?: string;
|
||||
sourcePath?: string;
|
||||
signCommit?: boolean;
|
||||
}>({
|
||||
id: 'publish:gitea',
|
||||
description:
|
||||
@@ -268,6 +269,11 @@ export function createPublishGiteaAction(options: {
|
||||
type: 'string',
|
||||
description: `Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.`,
|
||||
},
|
||||
signCommit: {
|
||||
title: 'Sign commit',
|
||||
type: 'boolean',
|
||||
description: 'Sign commit with configured PGP private key',
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
@@ -298,6 +304,7 @@ export function createPublishGiteaAction(options: {
|
||||
gitAuthorEmail,
|
||||
gitCommitMessage = 'initial commit',
|
||||
sourcePath,
|
||||
signCommit,
|
||||
} = ctx.input;
|
||||
|
||||
const { repo, host, owner } = parseRepoUrl(repoUrl, integrations);
|
||||
@@ -338,6 +345,16 @@ export function createPublishGiteaAction(options: {
|
||||
? gitAuthorEmail
|
||||
: config.getOptionalString('scaffolder.defaultAuthor.email'),
|
||||
};
|
||||
|
||||
const signingKey =
|
||||
integrationConfig.config.commitSigningKey ??
|
||||
config.getOptionalString('scaffolder.defaultCommitSigningKey');
|
||||
if (signCommit && !signingKey) {
|
||||
throw new Error(
|
||||
'Signing commits is enabled but no signing key is provided in the configuration',
|
||||
);
|
||||
}
|
||||
|
||||
// The owner to be used should be either the org name or user authenticated with the gitea server
|
||||
const remoteUrl = `${integrationConfig.config.baseUrl}/${owner}/${repo}.git`;
|
||||
const commitResult = await initRepoAndPush({
|
||||
|
||||
@@ -144,6 +144,7 @@ export function createPublishGitlabAction(options: {
|
||||
gitCommitMessage?: string;
|
||||
gitAuthorName?: string;
|
||||
gitAuthorEmail?: string;
|
||||
signCommit?: boolean;
|
||||
setUserAsOwner?: boolean;
|
||||
topics?: string[];
|
||||
settings?: {
|
||||
|
||||
@@ -74,6 +74,7 @@ describe('publish:gitlab', () => {
|
||||
host: 'gitlab.com',
|
||||
token: 'tokenlols',
|
||||
apiBaseUrl: 'https://api.gitlab.com',
|
||||
signingKey: 'test-signing-key',
|
||||
},
|
||||
{
|
||||
host: 'hosted.gitlab.com',
|
||||
@@ -420,6 +421,31 @@ describe('publish:gitlab', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should call initRepoAndPush with the signing key', async () => {
|
||||
mockGitlabClient.Users.showCurrentUser.mockResolvedValue({ id: 12345 });
|
||||
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
|
||||
mockGitlabClient.Groups.allProjects.mockResolvedValue([]);
|
||||
mockGitlabClient.Projects.create.mockResolvedValue({
|
||||
http_url_to_repo: 'http://mockurl.git',
|
||||
});
|
||||
|
||||
await action.handler({
|
||||
...mockContext,
|
||||
input: { ...mockContext.input, signCommit: true },
|
||||
});
|
||||
|
||||
expect(initRepoAndPush).toHaveBeenCalledWith({
|
||||
dir: mockContext.workspacePath,
|
||||
defaultBranch: 'master',
|
||||
remoteUrl: 'http://mockurl.git',
|
||||
auth: { username: 'oauth2', password: 'tokenlols' },
|
||||
logger: mockContext.logger,
|
||||
commitMessage: 'initial commit',
|
||||
gitAuthorInfo: {},
|
||||
signingKey: 'test-signing-key',
|
||||
});
|
||||
});
|
||||
|
||||
it('should not call initRepoAndPush when sourcePath is false', async () => {
|
||||
mockGitlabClient.Users.showCurrentUser.mockResolvedValue({ id: 12345 });
|
||||
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
|
||||
import { InputError } from '@backstage/errors';
|
||||
import { ScmIntegrationRegistry } from '@backstage/integration';
|
||||
import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
|
||||
import { Gitlab, VariableType } from '@gitbeaker/rest';
|
||||
import {
|
||||
initRepoAndPush,
|
||||
createTemplateAction,
|
||||
getRepoSourceDirectory,
|
||||
initRepoAndPush,
|
||||
parseRepoUrl,
|
||||
} from '@backstage/plugin-scaffolder-node';
|
||||
import { Gitlab, VariableType } from '@gitbeaker/rest';
|
||||
import { Config } from '@backstage/config';
|
||||
import { examples } from './gitlab.examples';
|
||||
|
||||
@@ -49,6 +49,7 @@ export function createPublishGitlabAction(options: {
|
||||
gitCommitMessage?: string;
|
||||
gitAuthorName?: string;
|
||||
gitAuthorEmail?: string;
|
||||
signCommit?: boolean;
|
||||
setUserAsOwner?: boolean;
|
||||
/** @deprecated in favour of settings.topics field */
|
||||
topics?: string[];
|
||||
@@ -122,6 +123,11 @@ export function createPublishGitlabAction(options: {
|
||||
type: 'string',
|
||||
description: `Sets the default author email for the commit.`,
|
||||
},
|
||||
signCommit: {
|
||||
title: 'Sign commit',
|
||||
type: 'boolean',
|
||||
description: 'Sign commit with configured PGP private key',
|
||||
},
|
||||
sourcePath: {
|
||||
title: 'Source Path',
|
||||
description:
|
||||
@@ -349,6 +355,7 @@ export function createPublishGitlabAction(options: {
|
||||
branches = [],
|
||||
projectVariables = [],
|
||||
skipExisting = false,
|
||||
signCommit,
|
||||
} = ctx.input;
|
||||
const { owner, repo, host } = parseRepoUrl(repoUrl, integrations);
|
||||
|
||||
@@ -447,6 +454,15 @@ export function createPublishGitlabAction(options: {
|
||||
? gitAuthorEmail
|
||||
: config.getOptionalString('scaffolder.defaultAuthor.email'),
|
||||
};
|
||||
const signingKey =
|
||||
integrationConfig.config.commitSigningKey ??
|
||||
config.getOptionalString('scaffolder.defaultCommitSigningKey');
|
||||
if (signCommit && !signingKey) {
|
||||
throw new Error(
|
||||
'Signing commits is enabled but no signing key is provided in the configuration',
|
||||
);
|
||||
}
|
||||
|
||||
const shouldSkipPublish =
|
||||
typeof ctx.input.sourcePath === 'boolean' && !ctx.input.sourcePath;
|
||||
if (!shouldSkipPublish) {
|
||||
@@ -469,6 +485,7 @@ export function createPublishGitlabAction(options: {
|
||||
? gitCommitMessage
|
||||
: config.getOptionalString('scaffolder.defaultCommitMessage'),
|
||||
gitAuthorInfo,
|
||||
signingKey: signCommit ? signingKey : undefined,
|
||||
});
|
||||
|
||||
if (branches) {
|
||||
|
||||
+4
@@ -27,6 +27,10 @@ export interface Config {
|
||||
email?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Default PGP signing key for signing commits.
|
||||
*/
|
||||
defaultCommitSigningKey?: string;
|
||||
/**
|
||||
* The commit message used when new components are created.
|
||||
*/
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
"@backstage/integration": "workspace:^",
|
||||
"@backstage/plugin-scaffolder-common": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"@isomorphic-git/pgp-plugin": "^0.0.7",
|
||||
"concat-stream": "^2.0.0",
|
||||
"fs-extra": "^11.2.0",
|
||||
"globby": "^11.0.0",
|
||||
|
||||
@@ -106,6 +106,7 @@ export function commitAndPushBranch(options: {
|
||||
branch?: string;
|
||||
remoteRef?: string;
|
||||
remote?: string;
|
||||
signingKey?: string;
|
||||
}): Promise<{
|
||||
commitHash: string;
|
||||
}>;
|
||||
@@ -129,6 +130,7 @@ export function commitAndPushRepo(input: {
|
||||
};
|
||||
branch?: string;
|
||||
remoteRef?: string;
|
||||
signingKey?: string;
|
||||
}): Promise<{
|
||||
commitHash: string;
|
||||
}>;
|
||||
@@ -242,6 +244,7 @@ export function initRepoAndPush(input: {
|
||||
name?: string;
|
||||
email?: string;
|
||||
};
|
||||
signingKey?: string;
|
||||
}): Promise<{
|
||||
commitHash: string;
|
||||
}>;
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
|
||||
import { Git } from '../scm';
|
||||
import {
|
||||
commitAndPushRepo,
|
||||
initRepoAndPush,
|
||||
commitAndPushBranch,
|
||||
addFiles,
|
||||
createBranch,
|
||||
cloneRepo,
|
||||
commitAndPushBranch,
|
||||
commitAndPushRepo,
|
||||
createBranch,
|
||||
initRepoAndPush,
|
||||
} from './gitHelpers';
|
||||
import { mockServices } from '@backstage/backend-test-utils';
|
||||
import { loggerToWinstonLogger } from './loggerToWinstonLogger';
|
||||
@@ -224,6 +224,32 @@ describe('commitAndPushRepo', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('creates commit with signing key', async () => {
|
||||
await commitAndPushRepo({
|
||||
dir: '/test/repo/dir/',
|
||||
auth: {
|
||||
username: 'test-user',
|
||||
password: 'test-password',
|
||||
},
|
||||
logger: loggerToWinstonLogger(mockServices.logger.mock()),
|
||||
commitMessage: 'commit message',
|
||||
signingKey: 'test-signing-key',
|
||||
});
|
||||
expect(mockedGit.commit).toHaveBeenCalledWith({
|
||||
dir: '/test/repo/dir/',
|
||||
message: 'commit message',
|
||||
author: {
|
||||
name: 'Scaffolder',
|
||||
email: 'scaffolder@backstage.io',
|
||||
},
|
||||
committer: {
|
||||
name: 'Scaffolder',
|
||||
email: 'scaffolder@backstage.io',
|
||||
},
|
||||
signingKey: 'test-signing-key',
|
||||
});
|
||||
});
|
||||
|
||||
it('pushes to the remote', () => {
|
||||
expect(mockedGit.push).toHaveBeenCalledWith({
|
||||
dir: '/test/repo/dir/',
|
||||
|
||||
@@ -31,6 +31,7 @@ export async function initRepoAndPush(input: {
|
||||
defaultBranch?: string;
|
||||
commitMessage?: string;
|
||||
gitAuthorInfo?: { name?: string; email?: string };
|
||||
signingKey?: string;
|
||||
}): Promise<{ commitHash: string }> {
|
||||
const {
|
||||
dir,
|
||||
@@ -40,6 +41,7 @@ export async function initRepoAndPush(input: {
|
||||
defaultBranch = 'master',
|
||||
commitMessage = 'Initial commit',
|
||||
gitAuthorInfo,
|
||||
signingKey,
|
||||
} = input;
|
||||
const git = Git.fromAuth({
|
||||
...auth,
|
||||
@@ -64,6 +66,7 @@ export async function initRepoAndPush(input: {
|
||||
message: commitMessage,
|
||||
author: authorInfo,
|
||||
committer: authorInfo,
|
||||
signingKey,
|
||||
});
|
||||
|
||||
await git.push({
|
||||
@@ -89,6 +92,7 @@ export async function commitAndPushRepo(input: {
|
||||
gitAuthorInfo?: { name?: string; email?: string };
|
||||
branch?: string;
|
||||
remoteRef?: string;
|
||||
signingKey?: string;
|
||||
}): Promise<{ commitHash: string }> {
|
||||
const {
|
||||
dir,
|
||||
@@ -98,6 +102,7 @@ export async function commitAndPushRepo(input: {
|
||||
gitAuthorInfo,
|
||||
branch = 'master',
|
||||
remoteRef,
|
||||
signingKey,
|
||||
} = input;
|
||||
|
||||
const git = Git.fromAuth({
|
||||
@@ -120,6 +125,7 @@ export async function commitAndPushRepo(input: {
|
||||
message: commitMessage,
|
||||
author: authorInfo,
|
||||
committer: authorInfo,
|
||||
signingKey,
|
||||
});
|
||||
|
||||
await git.push({
|
||||
@@ -213,6 +219,7 @@ export async function commitAndPushBranch(options: {
|
||||
branch?: string;
|
||||
remoteRef?: string;
|
||||
remote?: string;
|
||||
signingKey?: string;
|
||||
}): Promise<{ commitHash: string }> {
|
||||
const {
|
||||
dir,
|
||||
@@ -223,6 +230,7 @@ export async function commitAndPushBranch(options: {
|
||||
branch = 'master',
|
||||
remoteRef,
|
||||
remote = 'origin',
|
||||
signingKey,
|
||||
} = options;
|
||||
const git = Git.fromAuth({
|
||||
...auth,
|
||||
@@ -240,6 +248,7 @@ export async function commitAndPushBranch(options: {
|
||||
message: commitMessage,
|
||||
author: authorInfo,
|
||||
committer: authorInfo,
|
||||
signingKey,
|
||||
});
|
||||
|
||||
await git.push({
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
jest.mock('isomorphic-git');
|
||||
jest.mock('isomorphic-git/http/node');
|
||||
jest.mock('fs-extra');
|
||||
jest.mock('@isomorphic-git/pgp-plugin', () => ({
|
||||
...jest.requireActual('@isomorphic-git/pgp-plugin'),
|
||||
pgp: {
|
||||
sign: jest.fn().mockResolvedValue({ signature: 'sign' }),
|
||||
},
|
||||
}));
|
||||
|
||||
import * as isomorphic from 'isomorphic-git';
|
||||
import { Git } from './git';
|
||||
@@ -140,8 +146,9 @@ describe('Git', () => {
|
||||
name: 'comitter',
|
||||
email: 'test@backstage.io',
|
||||
};
|
||||
const signingKey = 'test-signing-key';
|
||||
|
||||
await git.commit({ dir, message, author, committer });
|
||||
await git.commit({ dir, message, author, committer, signingKey });
|
||||
|
||||
expect(isomorphic.commit).toHaveBeenCalledWith({
|
||||
fs,
|
||||
@@ -149,6 +156,8 @@ describe('Git', () => {
|
||||
message,
|
||||
author,
|
||||
committer,
|
||||
signingKey,
|
||||
onSign: expect.any(Function),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,14 +15,16 @@
|
||||
*/
|
||||
|
||||
import git, {
|
||||
ProgressCallback,
|
||||
MergeResult,
|
||||
ReadCommitResult,
|
||||
AuthCallback,
|
||||
MergeResult,
|
||||
ProgressCallback,
|
||||
ReadCommitResult,
|
||||
} from 'isomorphic-git';
|
||||
import http from 'isomorphic-git/http/node';
|
||||
import fs from 'fs-extra';
|
||||
import { LoggerService } from '@backstage/backend-plugin-api';
|
||||
// @ts-ignore
|
||||
import { pgp } from '@isomorphic-git/pgp-plugin';
|
||||
|
||||
function isAuthCallbackOptions(
|
||||
options: StaticAuthOptions | AuthCallbackOptions,
|
||||
@@ -137,12 +139,21 @@ export class Git {
|
||||
message: string;
|
||||
author: { name: string; email: string };
|
||||
committer: { name: string; email: string };
|
||||
signingKey?: string;
|
||||
}): Promise<string> {
|
||||
const { dir, message, author, committer } = options;
|
||||
const { dir, message, author, committer, signingKey } = options;
|
||||
this.config.logger?.info(
|
||||
`Committing file to repo {dir=${dir},message=${message}}`,
|
||||
);
|
||||
return git.commit({ fs, dir, message, author, committer });
|
||||
return git.commit({
|
||||
fs,
|
||||
dir,
|
||||
message,
|
||||
author,
|
||||
committer,
|
||||
signingKey,
|
||||
onSign: signingKey ? pgp.sign : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
/** https://isomorphic-git.org/docs/en/clone */
|
||||
@@ -241,8 +252,9 @@ export class Git {
|
||||
ours?: string;
|
||||
author: { name: string; email: string };
|
||||
committer: { name: string; email: string };
|
||||
signingKey?: string;
|
||||
}): Promise<MergeResult> {
|
||||
const { dir, theirs, ours, author, committer } = options;
|
||||
const { dir, theirs, ours, author, committer, signingKey } = options;
|
||||
this.config.logger?.info(
|
||||
`Merging branch '${theirs}' into '${ours}' for repository {dir=${dir}}`,
|
||||
);
|
||||
@@ -255,6 +267,8 @@ export class Git {
|
||||
theirs,
|
||||
author,
|
||||
committer,
|
||||
signingKey,
|
||||
onSign: signingKey ? pgp.sign : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -7790,6 +7790,7 @@ __metadata:
|
||||
"@backstage/integration": "workspace:^"
|
||||
"@backstage/plugin-scaffolder-common": "workspace:^"
|
||||
"@backstage/types": "workspace:^"
|
||||
"@isomorphic-git/pgp-plugin": ^0.0.7
|
||||
concat-stream: ^2.0.0
|
||||
fs-extra: ^11.2.0
|
||||
globby: ^11.0.0
|
||||
@@ -10929,6 +10930,59 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@isomorphic-git/pgp-plugin@npm:^0.0.7":
|
||||
version: 0.0.7
|
||||
resolution: "@isomorphic-git/pgp-plugin@npm:0.0.7"
|
||||
dependencies:
|
||||
"@isomorphic-pgp/sign-and-verify": ^0.0.10
|
||||
"@isomorphic-pgp/util": ^0.0.6
|
||||
checksum: 5361b4e58933f87747607b4bcfdf7ce2e4d75f591d5839ecd313fba55196020ee0e867c307fbfa2cd0aa85442942a5efca40653dfac0acabe8043e80f1dbebc1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@isomorphic-pgp/parser@npm:^0.0.3":
|
||||
version: 0.0.3
|
||||
resolution: "@isomorphic-pgp/parser@npm:0.0.3"
|
||||
dependencies:
|
||||
array-buffer-to-hex: ^1.0.0
|
||||
base64-js: ^1.3.0
|
||||
bn.js: ^4.11.8
|
||||
clz-buffer: ^1.0.0
|
||||
concat-buffers: ^1.0.0
|
||||
crc: ^3.8.0
|
||||
isomorphic-textencoder: ^1.0.1
|
||||
select-case: ^1.0.0
|
||||
checksum: 3ddfb1d39e7a9c0da98940c95bf2a9b7a59819a1ee0a4839fcbf3152c386aa974a16854043e6cd5f987db2f9475b480c10f3ef5686f0da1495675cb399cdd22f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@isomorphic-pgp/sign-and-verify@npm:^0.0.10":
|
||||
version: 0.0.10
|
||||
resolution: "@isomorphic-pgp/sign-and-verify@npm:0.0.10"
|
||||
dependencies:
|
||||
"@isomorphic-pgp/parser": ^0.0.3
|
||||
"@isomorphic-pgp/util": ^0.0.6
|
||||
"@wmhilton/crypto-hash": ^1.0.2
|
||||
array-buffer-to-hex: ^1.0.0
|
||||
isomorphic-textencoder: ^1.0.1
|
||||
jsbn: ^1.1.0
|
||||
sha.js: ^2.4.11
|
||||
checksum: 3d43408abdb0d53c4514797ef47ec1d8f634e4a6b4a80f0df9ac826b9ba51df1a9cedcb26f7ddbee4594827de9676d7cda57549d321ea87bc95facfaa7127146
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@isomorphic-pgp/util@npm:^0.0.6":
|
||||
version: 0.0.6
|
||||
resolution: "@isomorphic-pgp/util@npm:0.0.6"
|
||||
dependencies:
|
||||
"@isomorphic-pgp/parser": ^0.0.3
|
||||
array-buffer-to-hex: ^1.0.0
|
||||
concat-buffers: ^1.0.0
|
||||
sha.js: ^2.4.11
|
||||
checksum: 721a15ddb4597f90b7b897b2d18a5819e86988ac44510f9aee9dc6a7823a62c3f1ba5b12eb35792c803b3b1c6d4af924ae0bc31123f21fbc6f5a8e8e7962a412
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@istanbuljs/load-nyc-config@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "@istanbuljs/load-nyc-config@npm:1.0.0"
|
||||
@@ -21810,6 +21864,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@wmhilton/crypto-hash@npm:^1.0.2":
|
||||
version: 1.0.2
|
||||
resolution: "@wmhilton/crypto-hash@npm:1.0.2"
|
||||
checksum: 99c7e46856d75dbd828922ed8088dcd85ac405d58976f785e3d3062e3e4044b11073ef43a6c74976d42abd2c320820993afcd6a1d41db22f19bf7a9fe5557140
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@xmldom/is-dom-node@npm:^1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "@xmldom/is-dom-node@npm:1.0.1"
|
||||
@@ -23059,6 +23120,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"array-buffer-to-hex@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "array-buffer-to-hex@npm:1.0.0"
|
||||
checksum: 8de16fbb42fc79c839e5579e3e7dbf9a36dfa52cfcb4c0576a0e9cc6eeb5bf3f066b671858a292c97fcf9bd117c6eebc121085325e836dfb62b2737babd29264
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"array-differ@npm:^3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "array-differ@npm:3.0.0"
|
||||
@@ -23985,7 +24053,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"bn.js@npm:^4.0.0, bn.js@npm:^4.1.0, bn.js@npm:^4.11.9":
|
||||
"bn.js@npm:^4.0.0, bn.js@npm:^4.1.0, bn.js@npm:^4.11.8, bn.js@npm:^4.11.9":
|
||||
version: 4.12.0
|
||||
resolution: "bn.js@npm:4.12.0"
|
||||
checksum: 39afb4f15f4ea537b55eaf1446c896af28ac948fdcf47171961475724d1bb65118cca49fa6e3d67706e4790955ec0e74de584e45c8f1ef89f46c812bee5b5a12
|
||||
@@ -24310,7 +24378,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"buffer@npm:^5.5.0, buffer@npm:^5.7.1":
|
||||
"buffer@npm:^5.1.0, buffer@npm:^5.5.0, buffer@npm:^5.7.1":
|
||||
version: 5.7.1
|
||||
resolution: "buffer@npm:5.7.1"
|
||||
dependencies:
|
||||
@@ -25149,6 +25217,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"clz-buffer@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "clz-buffer@npm:1.0.0"
|
||||
checksum: 00a177ec2e7732e2c6393e3825de5f9d4a530d77fefb1797cdf1782a3d72407c43941e0c30d4511dd6c0536ed0652cf17d356ce8408e4c3234e80e1d5c88e980
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cmd-extension@npm:^1.0.2":
|
||||
version: 1.0.2
|
||||
resolution: "cmd-extension@npm:1.0.2"
|
||||
@@ -25537,6 +25612,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"concat-buffers@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "concat-buffers@npm:1.0.0"
|
||||
checksum: 5b1d0215687a1ab27d9181d9a5036664e0f86f7da5bda5a9e446962572736e5c345eb3ca40b7d276198efad703754f8870fd216e70a36990d231b0b27c5fe9d7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"concat-map@npm:0.0.1":
|
||||
version: 0.0.1
|
||||
resolution: "concat-map@npm:0.0.1"
|
||||
@@ -25938,6 +26020,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"crc@npm:^3.8.0":
|
||||
version: 3.8.0
|
||||
resolution: "crc@npm:3.8.0"
|
||||
dependencies:
|
||||
buffer: ^5.1.0
|
||||
checksum: dabbc4eba223b206068b92ca82bb471d583eb6be2384a87f5c3712730cfd6ba4b13a45e8ba3ef62174d5a781a2c5ac5c20bf36cf37bba73926899bd0aa19186f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"create-ecdh@npm:^4.0.4":
|
||||
version: 4.0.4
|
||||
resolution: "create-ecdh@npm:4.0.4"
|
||||
@@ -29385,6 +29476,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fast-text-encoding@npm:^1.0.0":
|
||||
version: 1.0.6
|
||||
resolution: "fast-text-encoding@npm:1.0.6"
|
||||
checksum: 9d58f694314b3283e785bf61954902536da228607ad246905e30256f9ab8331f780ac987e7222c9f5eafd04168d07e12b8054c85cedb76a2c05af0e82387a903
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fast-uri@npm:^3.0.1":
|
||||
version: 3.0.1
|
||||
resolution: "fast-uri@npm:3.0.1"
|
||||
@@ -33006,6 +33104,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"isomorphic-textencoder@npm:^1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "isomorphic-textencoder@npm:1.0.1"
|
||||
dependencies:
|
||||
fast-text-encoding: ^1.0.0
|
||||
checksum: 9bd0c04bff7b1dc9e410d2f9a2705ca4cc288872929d88fbb7758f06b5147de8dbaea5f95ce6cf4d314f064643f3d42d69a07bbb68df0261e81153d2d56f77f3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"isomorphic-timers-promises@npm:^1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "isomorphic-timers-promises@npm:1.0.1"
|
||||
@@ -33803,7 +33910,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"jsbn@npm:1.1.0":
|
||||
"jsbn@npm:1.1.0, jsbn@npm:^1.1.0":
|
||||
version: 1.1.0
|
||||
resolution: "jsbn@npm:1.1.0"
|
||||
checksum: 944f924f2bd67ad533b3850eee47603eed0f6ae425fd1ee8c760f477e8c34a05f144c1bd4f5a5dd1963141dc79a2c55f89ccc5ab77d039e7077f3ad196b64965
|
||||
@@ -43002,6 +43109,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"select-case@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "select-case@npm:1.0.0"
|
||||
checksum: 19cf1c8fd16ae4b811dea9fc4a11860dc764b9f7d2e6f7c8910814d91617e0d0d508ce2186aa9f99a3708834caf261e963769fed3a313552e1dae3d28d64042a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"select-hose@npm:^2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "select-hose@npm:2.0.0"
|
||||
|
||||
Reference in New Issue
Block a user