Skip to content
This repository was archived by the owner on Apr 13, 2020. It is now read-only.

Commit 39286c2

Browse files
authored
resolve optional arguments for spk pipeline commands (#493)
1 parent e523683 commit 39286c2

File tree

6 files changed

+130
-90
lines changed

6 files changed

+130
-90
lines changed

src/commands/project/pipeline.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ describe("test fetchValidateValues function", () => {
9797
fetchValidateValues(mockMissingValues, gitUrl, {
9898
azure_devops: {},
9999
});
100-
}).toThrow(`Repo url not defined`);
100+
}).toThrow(`project-pipeline-err-invalid-options: Invalid option values`);
101101
});
102102
it("SPK Config's azure_devops do not have value and command line does not have values", () => {
103103
expect(() => {

src/commands/project/pipeline.ts

+8-18
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
getRepositoryName,
2323
getRepositoryUrl,
2424
isGitHubUrl,
25+
validateRepoUrl
2526
} from "../../lib/gitutils";
2627
import {
2728
createPipelineForDefinition,
@@ -45,7 +46,7 @@ export interface CommandOptions {
4546
devopsProject: string | undefined;
4647
pipelineName: string;
4748
repoName: string;
48-
repoUrl: string;
49+
repoUrl: string | undefined;
4950
buildScriptUrl: string | undefined;
5051
yamlFileBranch: string;
5152
}
@@ -97,13 +98,7 @@ export const fetchValidateValues = (
9798
);
9899
}
99100
const azureDevops = spkConfig?.azure_devops;
100-
if (!opts.repoUrl) {
101-
throw buildError(
102-
errorStatusCode.VALIDATION_ERR,
103-
"project-pipeline-err-repo-url-undefined"
104-
);
105-
}
106-
101+
const repoUrl = validateRepoUrl(opts,gitOriginUrl);
107102
const values: CommandOptions = {
108103
buildScriptUrl: opts.buildScriptUrl || BUILD_SCRIPT_URL,
109104
devopsProject: opts.devopsProject || azureDevops?.project,
@@ -112,7 +107,7 @@ export const fetchValidateValues = (
112107
pipelineName:
113108
opts.pipelineName || getRepositoryName(gitOriginUrl) + "-lifecycle",
114109
repoName:
115-
getRepositoryName(opts.repoUrl) || getRepositoryName(gitOriginUrl),
110+
getRepositoryName(repoUrl) || getRepositoryName(gitOriginUrl),
116111
repoUrl: opts.repoUrl || getRepositoryUrl(gitOriginUrl),
117112
yamlFileBranch: opts.yamlFileBranch,
118113
};
@@ -259,17 +254,13 @@ export const execute = async (
259254
exitFn: (status: number) => Promise<void>
260255
): Promise<void> => {
261256
try {
262-
if (!opts.repoUrl || !opts.pipelineName) {
263-
throw buildError(errorStatusCode.VALIDATION_ERR, {
264-
errorKey: "project-pipeline-err-missing-values",
265-
values: ["repo url and/or pipeline name"],
266-
});
267-
}
268-
const gitUrlType = await isGitHubUrl(opts.repoUrl);
257+
const gitOriginUrl = await getOriginUrl();
258+
const repoUrl = validateRepoUrl(opts, gitOriginUrl);
259+
const gitUrlType = await isGitHubUrl(repoUrl);
269260
if (gitUrlType) {
270261
throw buildError(errorStatusCode.VALIDATION_ERR, {
271262
errorKey: "project-pipeline-err-github-repo",
272-
values: [opts.repoUrl],
263+
values: [repoUrl],
273264
});
274265
}
275266
if (!projectPath) {
@@ -282,7 +273,6 @@ export const execute = async (
282273
logger.verbose(`project path: ${projectPath}`);
283274

284275
checkDependencies(projectPath);
285-
const gitOriginUrl = await getOriginUrl();
286276
const values = fetchValidateValues(opts, gitOriginUrl, Config());
287277

288278
const accessOpts: AzureDevOpsOpts = {

src/commands/service/pipeline.ts

+73-70
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
/* eslint-disable @typescript-eslint/no-use-before-define */
2-
31
import { IBuildApi } from "azure-devops-node-api/BuildApi";
42
import {
53
BuildDefinition,
@@ -20,6 +18,7 @@ import {
2018
getRepositoryName,
2119
getRepositoryUrl,
2220
isGitHubUrl,
21+
validateRepoUrl
2322
} from "../../lib/gitutils";
2423
import {
2524
createPipelineForDefinition,
@@ -33,6 +32,8 @@ import {
3332
validateOrgNameThrowable,
3433
validateProjectNameThrowable,
3534
} from "../../lib/validator";
35+
import { build as buildError } from "../../lib/errorBuilder";
36+
import { errorStatusCode } from "../../lib/errorStatusCode";
3637

3738
export interface CommandOptions {
3839
orgName: string;
@@ -52,13 +53,14 @@ export const fetchValues = async (
5253
): Promise<CommandOptions> => {
5354
const { azure_devops } = Config();
5455
const gitOriginUrl = await getOriginUrl();
56+
const repoUrl = validateRepoUrl(opts, gitOriginUrl);
5557

5658
opts.orgName = opts.orgName || azure_devops?.org || "";
5759
opts.personalAccessToken =
5860
opts.personalAccessToken || azure_devops?.access_token || "";
5961
opts.devopsProject = opts.devopsProject || azure_devops?.project || "";
6062
opts.pipelineName = opts.pipelineName || serviceName + "-pipeline";
61-
opts.repoName = getRepositoryName(opts.repoUrl);
63+
opts.repoName = getRepositoryName(repoUrl);
6264
opts.repoUrl = opts.repoUrl || getRepositoryUrl(gitOriginUrl);
6365
opts.buildScriptUrl = opts.buildScriptUrl || BUILD_SCRIPT_URL;
6466

@@ -68,60 +70,23 @@ export const fetchValues = async (
6870
return opts;
6971
};
7072

71-
export const execute = async (
72-
serviceName: string,
73-
opts: CommandOptions,
74-
exitFn: (status: number) => Promise<void>
75-
): Promise<void> => {
76-
try {
77-
if (!opts.repoUrl) {
78-
throw Error(`Repo url not defined`);
79-
}
80-
const gitUrlType = await isGitHubUrl(opts.repoUrl);
81-
if (gitUrlType) {
82-
throw Error(
83-
`GitHub repos are not supported. Repo url: ${opts.repoUrl} is invalid`
84-
);
85-
}
86-
await fetchValues(serviceName, opts);
87-
const accessOpts: AzureDevOpsOpts = {
88-
orgName: opts.orgName,
89-
personalAccessToken: opts.personalAccessToken,
90-
project: opts.devopsProject,
91-
};
92-
93-
// if a packages dir is supplied, its a mono-repo
94-
const pipelinesYamlPath = opts.packagesDir
95-
? // if a packages dir is supplied, concat <packages-dir>/<service-name>
96-
path.join(opts.packagesDir, serviceName, SERVICE_PIPELINE_FILENAME)
97-
: // if no packages dir, then just concat with the service directory.
98-
path.join(serviceName, SERVICE_PIPELINE_FILENAME);
99-
100-
// By default the version descriptor is for the master branch
101-
await validateRepository(
102-
opts.devopsProject,
103-
pipelinesYamlPath,
104-
opts.yamlFileBranch ? opts.yamlFileBranch : "master",
105-
opts.repoName,
106-
accessOpts
107-
);
108-
await installBuildUpdatePipeline(pipelinesYamlPath, opts);
109-
await exitFn(0);
110-
} catch (err) {
111-
logger.error(err);
112-
await exitFn(1);
113-
}
73+
/**
74+
* Builds and returns variables required for the Build & Update service pipeline.
75+
* @param buildScriptUrl Build Script URL
76+
* @returns Object containing the necessary run-time variables for the Build & Update service pipeline.
77+
*/
78+
export const requiredPipelineVariables = (
79+
buildScriptUrl: string
80+
): { [key: string]: BuildDefinitionVariable } => {
81+
return {
82+
BUILD_SCRIPT_URL: {
83+
allowOverride: true,
84+
isSecret: false,
85+
value: buildScriptUrl,
86+
},
87+
};
11488
};
11589

116-
export const commandDecorator = (command: commander.Command): void => {
117-
buildCmd(command, decorator).action(
118-
async (serviceName: string, opts: CommandOptions) => {
119-
await execute(serviceName, opts, async (status: number) => {
120-
await exitCmd(logger, process.exit, status);
121-
});
122-
}
123-
);
124-
};
12590

12691
/**
12792
* Install a pipeline for the service in an azure devops org.
@@ -196,19 +161,57 @@ export const installBuildUpdatePipeline = async (
196161
}
197162
};
198163

199-
/**
200-
* Builds and returns variables required for the Build & Update service pipeline.
201-
* @param buildScriptUrl Build Script URL
202-
* @returns Object containing the necessary run-time variables for the Build & Update service pipeline.
203-
*/
204-
export const requiredPipelineVariables = (
205-
buildScriptUrl: string
206-
): { [key: string]: BuildDefinitionVariable } => {
207-
return {
208-
BUILD_SCRIPT_URL: {
209-
allowOverride: true,
210-
isSecret: false,
211-
value: buildScriptUrl,
212-
},
213-
};
164+
export const execute = async (
165+
serviceName: string,
166+
opts: CommandOptions,
167+
exitFn: (status: number) => Promise<void>
168+
): Promise<void> => {
169+
try {
170+
const gitOriginUrl = await getOriginUrl();
171+
const repoUrl = validateRepoUrl(opts, gitOriginUrl);
172+
const gitUrlType = await isGitHubUrl(repoUrl);
173+
if (gitUrlType) {
174+
throw buildError(errorStatusCode.VALIDATION_ERR, {
175+
errorKey: "project-pipeline-err-github-repo",
176+
values: [repoUrl],
177+
});
178+
}
179+
await fetchValues(serviceName, opts);
180+
const accessOpts: AzureDevOpsOpts = {
181+
orgName: opts.orgName,
182+
personalAccessToken: opts.personalAccessToken,
183+
project: opts.devopsProject,
184+
};
185+
186+
// if a packages dir is supplied, its a mono-repo
187+
const pipelinesYamlPath = opts.packagesDir
188+
? // if a packages dir is supplied, concat <packages-dir>/<service-name>
189+
path.join(opts.packagesDir, serviceName, SERVICE_PIPELINE_FILENAME)
190+
: // if no packages dir, then just concat with the service directory.
191+
path.join(serviceName, SERVICE_PIPELINE_FILENAME);
192+
193+
// By default the version descriptor is for the master branch
194+
await validateRepository(
195+
opts.devopsProject,
196+
pipelinesYamlPath,
197+
opts.yamlFileBranch ? opts.yamlFileBranch : "master",
198+
opts.repoName,
199+
accessOpts
200+
);
201+
await installBuildUpdatePipeline(pipelinesYamlPath, opts);
202+
await exitFn(0);
203+
} catch (err) {
204+
logger.error(err);
205+
await exitFn(1);
206+
}
207+
};
208+
209+
export const commandDecorator = (command: commander.Command): void => {
210+
buildCmd(command, decorator).action(
211+
async (serviceName: string, opts: CommandOptions) => {
212+
await execute(serviceName, opts, async (status: number) => {
213+
await exitCmd(logger, process.exit, status);
214+
});
215+
}
216+
);
214217
};

src/lib/gitutils.test.ts

+33
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ import {
1313
pushBranch,
1414
safeGitUrlForLogging,
1515
tryGetGitOrigin,
16+
validateRepoUrl,
1617
} from "../lib/gitutils";
1718
import { disableVerboseLogging, enableVerboseLogging } from "../logger";
1819
import { exec } from "./shell";
20+
import { ConfigValues } from "../commands/project/pipeline";
1921

2022
jest.mock("./shell");
2123

@@ -570,3 +572,34 @@ describe("test github urls", () => {
570572
).toBe(false);
571573
});
572574
});
575+
576+
describe("Returns an azure devops git repo url if it is defined", () => {
577+
it("positive test", async () => {
578+
const mockValues: ConfigValues = {
579+
buildScriptUrl: "buildScriptUrl",
580+
devopsProject: "azDoProject",
581+
orgName: "orgName",
582+
personalAccessToken: "PAT",
583+
pipelineName: "pipelineName",
584+
repoName: "repoName",
585+
repoUrl: "https://dev.azure.com/myOrg/myProject/_git/myRepo",
586+
yamlFileBranch: "master",
587+
};
588+
const gitUrl = "https://github.com/CatalystCode/spk.git";
589+
expect(validateRepoUrl(mockValues, gitUrl)).toBe("https://dev.azure.com/myOrg/myProject/_git/myRepo");
590+
});
591+
it("another positive test", async () => {
592+
const mockValues: ConfigValues = {
593+
buildScriptUrl: "buildScriptUrl",
594+
devopsProject: "azDoProject",
595+
orgName: "orgName",
596+
personalAccessToken: "PAT",
597+
pipelineName: "pipelineName",
598+
repoName: "repoName",
599+
repoUrl: "",
600+
yamlFileBranch: "master",
601+
};
602+
const gitUrl = "https://github.com/CatalystCode/spk";
603+
expect(validateRepoUrl(mockValues, gitUrl)).toBe("https://github.com/CatalystCode/spk");
604+
});
605+
});

src/lib/gitutils.ts

+15
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { logger } from "../logger";
55
import { exec } from "./shell";
66
import { build as buildError } from "./errorBuilder";
77
import { errorStatusCode } from "./errorStatusCode";
8+
import { CommandOptions } from "../commands/project/pipeline";
89

910
/**
1011
* For git urls that you may want to log only!
@@ -345,6 +346,20 @@ export const checkoutCommitPushCreatePRLink = async (
345346
}
346347
};
347348

349+
/**
350+
* Returns a git repository url
351+
*
352+
* @param opts Options object from commander.
353+
* @param gitOriginUrl Git origin URL which is used to set values
354+
* for pipeline, repoName and repoUrl
355+
*/
356+
export const validateRepoUrl = (
357+
opts: CommandOptions,
358+
gitOriginUrl: string
359+
): string => {
360+
return opts.repoUrl || getRepositoryUrl(gitOriginUrl)
361+
};
362+
348363
/**
349364
* Validates whether a url is a github url
350365
* TEMPORARY, UNTIL GITHUB REPOS ARE SUPPORTED

src/lib/i18n.json

-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@
5656
"project-pipeline-err-missing-values": "Value for {0} is missing.",
5757
"project-pipeline-err-init-dependency": "Please run `spk project init` and `spk project cvg` commands before running this command to initialize the project.",
5858
"project-pipeline-err-cvg": "Please run `spk project cvg` command before running this command to create a variable group.",
59-
"project-pipeline-err-repo-url-undefined": "Repo url not defined",
6059
"project-pipeline-err-spk-config-missing": "SPK Config is missing",
6160
"project-pipeline-err-invalid-options": "Invalid option values",
6261
"project-pipeline-err-pipeline-create": "Error occurred during pipeline creation for {0}",

0 commit comments

Comments
 (0)