Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove exec from dist and make it a test helper only #500

Merged
merged 1 commit into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe('cherrypickAndCreateTargetPullRequest', () => {
execSpy = jest
.spyOn(childProcess, 'spawnPromise')

// mock all exec commands to respond without errors
// mock all spawn commands to respond without errors
.mockResolvedValue({ stdout: '', stderr: '', code: 0, cmdArgs: [] });

consoleLogSpy = jest.spyOn(logger, 'consoleLog');
Expand Down
77 changes: 30 additions & 47 deletions src/lib/child-process-promisified.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
import childProcess from 'child_process';
import { promisify } from 'util';
import apm from 'elastic-apm-node';
import { logger } from './logger';
const execPromisified = promisify(childProcess.exec);

export async function exec(
cmd: string,
options: childProcess.ExecOptions & { cwd: string },
) {
const res = await execPromisified(cmd, {
maxBuffer: 100 * 1024 * 1024,
...options,
type SpawnErrorContext = {
cmdArgs: ReadonlyArray<string>;
code: number;
stderr: string;
stdout: string;
};

// ensure that git commands return english error messages
env: { ...process.env, LANG: 'en_US' },
});
export class SpawnError extends Error {
context: SpawnErrorContext;
constructor(context: SpawnErrorContext) {
const cmdArgs = context.cmdArgs.join(' ');
const message = `Code: ${
context.code
}, Args: "${cmdArgs}", Message: ${context.stderr.trim()}`;

return res;
super(message);
Error.captureStackTrace(this, SpawnError);
this.name = 'SpawnError';
this.message = message;
this.context = context;
}
}

type SpawnPromiseResponse = {
Expand Down Expand Up @@ -83,17 +89,6 @@ export async function spawnPromise(
});
}

function startSpawnSpan(cmd: string, cmdArgs: ReadonlyArray<string>) {
const span = apm.startSpan(`Spawn: "${cmd}"`);
const fullCmd = getFullCmd(cmd, cmdArgs);
const firstCmdArg = cmdArgs.filter(
(cmdArg) => !cmdArg.startsWith('--') && !cmdArg.startsWith('-'),
)[0];
span?.setType('spawn', cmd, firstCmdArg);
span?.setLabel(`cmd`, fullCmd);
return span;
}

export const spawnStream = (cmd: string, cmdArgs: ReadonlyArray<string>) => {
const spawnSpan = startSpawnSpan(cmd, cmdArgs);

Expand All @@ -111,29 +106,17 @@ export const spawnStream = (cmd: string, cmdArgs: ReadonlyArray<string>) => {
return res;
};

function getFullCmd(cmd: string, cmdArgs: ReadonlyArray<string>) {
return `${cmd} ${cmdArgs.join(' ')}`;
function startSpawnSpan(cmd: string, cmdArgs: ReadonlyArray<string>) {
const span = apm.startSpan(`Spawn: "${cmd}"`);
const fullCmd = getFullCmd(cmd, cmdArgs);
const firstCmdArg = cmdArgs.filter(
(cmdArg) => !cmdArg.startsWith('--') && !cmdArg.startsWith('-'),
)[0];
span?.setType('spawn', cmd, firstCmdArg);
span?.setLabel(`cmd`, fullCmd);
return span;
}

export type SpawnErrorContext = {
cmdArgs: ReadonlyArray<string>;
code: number;
stderr: string;
stdout: string;
};

export class SpawnError extends Error {
context: SpawnErrorContext;
constructor(context: SpawnErrorContext) {
const cmdArgs = context.cmdArgs.join(' ');
const message = `Code: ${
context.code
}, Args: "${cmdArgs}", Message: ${context.stderr.trim()}`;

super(message);
Error.captureStackTrace(this, SpawnError);
this.name = 'SpawnError';
this.message = message;
this.context = context;
}
function getFullCmd(cmd: string, cmdArgs: ReadonlyArray<string>) {
return `${cmd} ${cmdArgs.join(' ')}`;
}
12 changes: 5 additions & 7 deletions src/lib/git.private.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import path from 'path';
import makeDir from 'make-dir';
import { Commit } from '../entrypoint.api';
import { ValidConfigOptions } from '../options/options';
import { exec } from '../test/childProcessHelper';
import { getDevAccessToken } from '../test/private/getDevAccessToken';
import { getSandboxPath, resetSandbox } from '../test/sandbox';
import * as childProcess from './child-process-promisified';
Expand Down Expand Up @@ -178,7 +179,7 @@ describe('git.private', () => {
targetBranch: '7.x',
backportBranch: 'my-backport-branch',
});
await childProcess.exec(
await exec(
`git remote add sorenlouv https://x-access-token:${accessToken}@github.com/sorenlouv/repo-with-conflicts.git`,
{ cwd },
);
Expand Down Expand Up @@ -380,7 +381,7 @@ describe('git.private', () => {
cwd,
);

await childProcess.exec('git checkout 7.x', { cwd });
await exec('git checkout 7.x', { cwd });

// cherry-pick file
try {
Expand All @@ -394,7 +395,7 @@ describe('git.private', () => {
}

// disregard conflicts and stage all files
await childProcess.exec('git add -A', { cwd });
await exec('git add -A', { cwd });

await commitChanges({ commit, commitAuthor, options });

Expand Down Expand Up @@ -779,10 +780,7 @@ async function getCurrentSha(cwd: string) {
}

async function getCurrentBranchName(cwd: string) {
const { stdout } = await childProcess.exec(
'git rev-parse --abbrev-ref HEAD',
{ cwd },
);
const { stdout } = await exec('git rev-parse --abbrev-ref HEAD', { cwd });
return stdout.trim();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { exec } from '../../../test/childProcessHelper';
import { getDevAccessToken } from '../../../test/private/getDevAccessToken';
import { getSandboxPath, resetSandbox } from '../../../test/sandbox';
import * as childProcess from '../../child-process-promisified';
import { getRepoOwnerAndNameFromGitRemotes } from './getRepoOwnerAndNameFromGitRemotes';

const sandboxPath = getSandboxPath({ filename: __filename });
Expand All @@ -11,8 +11,8 @@ describe('fetchRemoteProjectConfig', () => {
it('retrives the original owner from github', async () => {
await resetSandbox(sandboxPath);
const execOpts = { cwd: sandboxPath };
await childProcess.exec(`git init`, execOpts);
await childProcess.exec(
await exec(`git init`, execOpts);
await exec(
`git remote add sorenlouv git@github.com:sorenlouv/kibana.git`,
execOpts,
);
Expand All @@ -33,16 +33,10 @@ describe('fetchRemoteProjectConfig', () => {
it('swallows the error and returns empty', async () => {
await resetSandbox(sandboxPath);
const execOpts = { cwd: sandboxPath };
await childProcess.exec(`git init`, execOpts);
await childProcess.exec(
`git remote add foo git@github.com:foo/kibana.git`,
execOpts,
);
await exec(`git init`, execOpts);
await exec(`git remote add foo git@github.com:foo/kibana.git`, execOpts);

await childProcess.exec(
`git remote add bar git@github.com:bar/kibana.git`,
execOpts,
);
await exec(`git remote add bar git@github.com:bar/kibana.git`, execOpts);

expect(
await getRepoOwnerAndNameFromGitRemotes({
Expand All @@ -57,7 +51,7 @@ describe('fetchRemoteProjectConfig', () => {
it('returns empty', async () => {
await resetSandbox(sandboxPath);
const execOpts = { cwd: sandboxPath };
await childProcess.exec(`git init`, execOpts);
await exec(`git init`, execOpts);

expect(
await getRepoOwnerAndNameFromGitRemotes({
Expand Down
18 changes: 18 additions & 0 deletions src/test/childProcessHelper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import childProcess from 'child_process';
import { promisify } from 'util';
const execPromisified = promisify(childProcess.exec);

export async function exec(
cmd: string,
options: childProcess.ExecOptions & { cwd: string },
) {
const res = await execPromisified(cmd, {
Dismissed Show dismissed Hide dismissed
maxBuffer: 100 * 1024 * 1024,
...options,

// ensure that git commands return english error messages
env: { ...process.env, LANG: 'en_US' },
});

return res;
}
2 changes: 1 addition & 1 deletion src/test/e2e/cli/commit-author.private.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { exec } from '../../../lib/child-process-promisified';
import { exec } from '../../childProcessHelper';
import { getDevAccessToken } from '../../private/getDevAccessToken';
import { getSandboxPath, resetSandbox } from '../../sandbox';
import { runBackportViaCli } from './runBackportViaCli';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import fs from 'fs/promises';
import { exec } from '../../../lib/child-process-promisified';
import { exec } from '../../childProcessHelper';
import { getDevAccessToken } from '../../private/getDevAccessToken';
import { replaceStringAndLinebreaks } from '../../replaceStringAndLinebreaks';
import { getSandboxPath, resetSandbox } from '../../sandbox';
Expand Down
2 changes: 1 addition & 1 deletion src/test/e2e/cli/entrypoint.cli.private.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { exec } from '../../../lib/child-process-promisified';
import * as packageVersion from '../../../utils/packageVersion';
import { exec } from '../../childProcessHelper';
import { getDevAccessToken } from '../../private/getDevAccessToken';
import { getSandboxPath, resetSandbox } from '../../sandbox';
import { runBackportViaCli } from './runBackportViaCli';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { exec } from '../../../lib/child-process-promisified';
import { exec } from '../../childProcessHelper';
import { getDevAccessToken } from '../../private/getDevAccessToken';
import { getSandboxPath, resetSandbox } from '../../sandbox';
import { runBackportViaCli } from './runBackportViaCli';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { exec } from '../../../lib/child-process-promisified';
import { exec } from '../../childProcessHelper';
import { getDevAccessToken } from '../../private/getDevAccessToken';
import { replaceStringAndLinebreaks } from '../../replaceStringAndLinebreaks';
import { getSandboxPath, resetSandbox } from '../../sandbox';
Expand Down
Loading