Skip to content

Commit

Permalink
refactor(git): prepare support for commit signing with other key form…
Browse files Browse the repository at this point in the history
…ats (#29875)
  • Loading branch information
sisp committed Jun 29, 2024
1 parent a416f77 commit 84ca13a
Showing 1 changed file with 53 additions and 40 deletions.
93 changes: 53 additions & 40 deletions lib/util/git/private-key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,56 +8,69 @@ import { exec } from '../exec';
import { newlineRegex } from '../regex';
import { addSecretForSanitizing } from '../sanitize';

let gitPrivateKey: string | undefined;
let keyId: string | undefined;
let gitPrivateKey: PrivateKey | undefined;

export function setPrivateKey(key: string | undefined): void {
if (!is.nonEmptyStringAndNotWhitespace(key)) {
return;
abstract class PrivateKey {
protected readonly key: string;
protected keyId: string | undefined;

constructor(key: string) {
this.key = key.trim();
addSecretForSanitizing(this.key, 'global');
logger.debug(
'gitPrivateKey: successfully set (but not yet written/configured)',
);
}

async writeKey(): Promise<void> {
try {
if (!this.keyId) {
this.keyId = await this.importKey();
}
logger.debug('gitPrivateKey: imported');
} catch (err) {
logger.warn({ err }, 'gitPrivateKey: error importing');
throw new Error(PLATFORM_GPG_FAILED);
}
}

async configSigningKey(cwd: string): Promise<void> {
logger.debug('gitPrivateKey: configuring commit signing');
// TODO: types (#22198)
await exec(`git config user.signingkey ${this.keyId!}`, { cwd });
await exec(`git config commit.gpgsign true`, { cwd });
}
addSecretForSanitizing(key.trim(), 'global');
logger.debug(
'gitPrivateKey: successfully set (but not yet written/configured)',
);
gitPrivateKey = key.trim();

protected abstract importKey(): Promise<string | undefined>;
}

async function importKey(): Promise<void> {
if (keyId) {
return;
class GPGKey extends PrivateKey {
protected async importKey(): Promise<string | undefined> {
const keyFileName = upath.join(os.tmpdir() + '/git-private-gpg.key');
await fs.outputFile(keyFileName, this.key);
const { stdout, stderr } = await exec(`gpg --import ${keyFileName}`);
logger.debug({ stdout, stderr }, 'Private key import result');
await fs.remove(keyFileName);
return `${stdout}${stderr}`
.split(newlineRegex)
.find((line) => line.includes('secret key imported'))
?.replace('gpg: key ', '')
.split(':')
.shift();
}
const keyFileName = upath.join(os.tmpdir() + '/git-private.key');
await fs.outputFile(keyFileName, gitPrivateKey!);
const { stdout, stderr } = await exec(`gpg --import ${keyFileName}`);
logger.debug({ stdout, stderr }, 'Private key import result');
keyId = `${stdout}${stderr}`
.split(newlineRegex)
.find((line) => line.includes('secret key imported'))
?.replace('gpg: key ', '')
.split(':')
.shift();
await fs.remove(keyFileName);
}

export async function writePrivateKey(): Promise<void> {
if (!gitPrivateKey) {
export function setPrivateKey(key: string | undefined): void {
if (!is.nonEmptyStringAndNotWhitespace(key)) {
return;
}
try {
await importKey();
logger.debug('gitPrivateKey: imported');
} catch (err) {
logger.warn({ err }, 'gitPrivateKey: error importing');
throw new Error(PLATFORM_GPG_FAILED);
}
gitPrivateKey = new GPGKey(key);
}

export async function writePrivateKey(): Promise<void> {
await gitPrivateKey?.writeKey();
}

export async function configSigningKey(cwd: string): Promise<void> {
if (!gitPrivateKey) {
return;
}
logger.debug('gitPrivateKey: configuring commit signing');
// TODO: types (#22198)
await exec(`git config user.signingkey ${keyId!}`, { cwd });
await exec(`git config commit.gpgsign true`, { cwd });
await gitPrivateKey?.configSigningKey(cwd);
}

0 comments on commit 84ca13a

Please sign in to comment.