Skip to content
This repository was archived by the owner on Apr 13, 2020. It is now read-only.
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
105 changes: 64 additions & 41 deletions src/commands/service/create-revision.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */

import commander from "commander";
import { join } from "path";
import { Bedrock, Config } from "../../config";
Expand Down Expand Up @@ -29,6 +27,16 @@ export interface CommandOptions {
targetBranch: string | undefined;
}

export interface CommandValues {
sourceBranch: string;
title: string | undefined;
description: string;
remoteUrl: string;
personalAccessToken: string;
orgName: string;
targetBranch: string | undefined;
}

export const getRemoteUrl = async (
remoteUrl: string | undefined
): Promise<string> => {
Expand Down Expand Up @@ -99,70 +107,85 @@ export const getSourceBranch = async (
/**
* Creates a pull request from the given source branch
* @param defaultRings List of default rings
* @param opts option values
* @param values option values
*/
export const makePullRequest = async (
defaultRings: string[],
opts: CommandOptions
values: CommandValues
): Promise<void> => {
for (const ring of defaultRings) {
const title = opts.title || `[SPK] ${opts.sourceBranch} => ${ring}`;
await createPullRequest(title, opts.sourceBranch!, ring, {
description: opts.description!,
orgName: opts.orgName!,
originPushUrl: opts.remoteUrl!,
personalAccessToken: opts.personalAccessToken!,
const title = values.title || `[SPK] ${values.sourceBranch} => ${ring}`;
await createPullRequest(title, values.sourceBranch, ring, {
description: values.description,
orgName: values.orgName,
originPushUrl: values.remoteUrl,
personalAccessToken: values.personalAccessToken,
});
}
};

const populateValues = async (opts: CommandOptions): Promise<CommandValues> => {
const { azure_devops } = Config();
opts.orgName = opts.orgName || azure_devops?.org;
opts.personalAccessToken =
opts.personalAccessToken || azure_devops?.access_token;

// Default the remote to the git origin
opts.remoteUrl = await getRemoteUrl(opts.remoteUrl);

// default pull request source branch to the current branch
opts.sourceBranch = await getSourceBranch(opts.sourceBranch);

const errors = validateForRequiredValues(decorator, {
orgName: opts.orgName,
personalAccessToken: opts.personalAccessToken,
remoteUrl: opts.remoteUrl,
sourceBranch: opts.sourceBranch,
});
if (errors.length > 0) {
throw Error("missing required values");
}

return {
// validateForRequiredValues confirm that sourceBranch has value
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
sourceBranch: opts.sourceBranch!,
title: opts.title,
description: opts.description || "This is automated PR generated via SPK",
remoteUrl: opts.remoteUrl,
// validateForRequiredValues confirm that personalAccessToken has value
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
personalAccessToken: opts.personalAccessToken!,
// validateForRequiredValues confirm that orgName has value
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
orgName: opts.orgName!,
targetBranch: opts.targetBranch,
};
};

export const execute = async (
opts: CommandOptions,
exitFn: (status: number) => Promise<void>
): Promise<void> => {
try {
const { azure_devops } = Config();
opts.orgName = opts.orgName || azure_devops?.org;
opts.personalAccessToken =
opts.personalAccessToken || azure_devops?.access_token!;
opts.description =
opts.description || "This is automated PR generated via SPK";

////////////////////////////////////////////////////////////////////////
// Give defaults
////////////////////////////////////////////////////////////////////////
const values = await populateValues(opts);

// default pull request against initial ring
const bedrockConfig = Bedrock();
// Default to the --target-branch for creating a revision; if not specified, fallback to default rings in bedrock.yaml
const defaultRings = getDefaultRings(opts.targetBranch, bedrockConfig);

// default pull request source branch to the current branch
opts.sourceBranch = await getSourceBranch(opts.sourceBranch);
const defaultRings = getDefaultRings(values.targetBranch, bedrockConfig);

// Make sure the user isn't trying to make a PR for a branch against itself
if (defaultRings.includes(opts.sourceBranch)) {
if (defaultRings.includes(values.sourceBranch)) {
throw Error(
`A pull request for a branch cannot be made against itself. Ensure your target branch(es) '${JSON.stringify(
defaultRings
)}' do not include your source branch '${opts.sourceBranch}'`
)}' do not include your source branch '${values.sourceBranch}'`
);
}

// Default the remote to the git origin
opts.remoteUrl = await getRemoteUrl(opts.remoteUrl);
const errors = validateForRequiredValues(decorator, {
orgName: opts.orgName,
personalAccessToken: opts.personalAccessToken,
remoteUrl: opts.remoteUrl,
sourceBranch: opts.sourceBranch,
});

if (errors.length > 0) {
await exitFn(1);
} else {
await makePullRequest(defaultRings, opts);
await exitFn(0);
}
await makePullRequest(defaultRings, values);
await exitFn(0);
} catch (err) {
logger.error(err);
await exitFn(1);
Expand Down
48 changes: 24 additions & 24 deletions src/commands/service/create.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
/* eslint-disable @typescript-eslint/no-use-before-define */
import fs from "fs";
import path from "path";
import { promisify } from "util";
Expand Down Expand Up @@ -292,6 +290,26 @@ describe("Validate Git URLs", () => {
});
});

const writeSampleMaintainersFileToDir = async (
maintainersFilePath: string
): Promise<void> => {
await promisify(fs.writeFile)(
maintainersFilePath,
createTestMaintainersYaml(),
"utf8"
);
};

const writeSampleBedrockFileToDir = async (
bedrockFilePath: string
): Promise<void> => {
await promisify(fs.writeFile)(
bedrockFilePath,
createTestBedrockYaml(),
"utf8"
);
};

describe("Adding a service to a repo directory", () => {
let randomTmpDir = "";
beforeEach(() => {
Expand Down Expand Up @@ -460,8 +478,10 @@ describe("Adding a service to a repo directory", () => {
)) {
if (servicePath.includes(serviceName)) {
expect(service.middlewares).toBeDefined();
expect(Array.isArray(service.middlewares)).toBe(true);
expect(service.middlewares!.length).toBe(0);
if (service.middlewares) {
expect(Array.isArray(service.middlewares)).toBe(true);
expect(service.middlewares.length).toBe(0);
}
}
}
});
Expand Down Expand Up @@ -501,23 +521,3 @@ describe("Adding a service to a repo directory", () => {
}
});
});

const writeSampleMaintainersFileToDir = async (
maintainersFilePath: string
): Promise<void> => {
await promisify(fs.writeFile)(
maintainersFilePath,
createTestMaintainersYaml(),
"utf8"
);
};

const writeSampleBedrockFileToDir = async (
bedrockFilePath: string
): Promise<void> => {
await promisify(fs.writeFile)(
bedrockFilePath,
createTestBedrockYaml(),
"utf8"
);
};
Loading