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

Commit 5cbb60c

Browse files
[FEATURE] added error code for setup command related libs (#498)
* [FEATURE] added error code for setup command related libs * added error code for variable groups * added more error handling in prompts.ts * added error id to error condition * add more error handling code * cover error to cascading error * update gitutil function * revert code when we throw exception when pr link cannot be found * throw exception with errorBuilder * Update i18n.json * Update i18n.json Co-authored-by: Andre Briggs <[email protected]>
1 parent 9b39c46 commit 5cbb60c

25 files changed

+1057
-667
lines changed

src/config.test.ts

+10-12
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
import { createTempDir } from "./lib/ioUtil";
1616
import { disableVerboseLogging, enableVerboseLogging } from "./logger";
1717
import { BedrockFile } from "./types";
18+
import { getErrorMessage } from "./lib/errorBuilder";
1819
import { getVersionMessage } from "./lib/fileutils";
1920

2021
beforeAll(() => {
@@ -40,15 +41,16 @@ describe("Test updateVariableWithLocalEnv function", () => {
4041
).toBe("world - world : world1");
4142
});
4243
it("negative test", () => {
43-
try {
44+
expect(() => {
4445
updateVariableWithLocalEnv(
4546
"${env:hello2} - ${env:hello} : ${env:hello1}"
4647
);
47-
} catch (e) {
48-
expect(e.message).toBe(
49-
"Environment variable needs to be defined for hello2 since it's referenced in the config file."
50-
);
51-
}
48+
}).toThrow(
49+
getErrorMessage({
50+
errorKey: "spk-config-yaml-var-undefined",
51+
values: ["hello2"],
52+
})
53+
);
5254
});
5355
});
5456

@@ -180,13 +182,9 @@ describe("Initializing a project a config file but no env vars", () => {
180182
describe("Initializing a project with a non-existent file", () => {
181183
test("Non-existent file test", () => {
182184
const filename = path.resolve("./spk-config-test.yaml");
183-
try {
185+
expect(() => {
184186
loadConfiguration(filename);
185-
// Make sure execution does not get here:
186-
expect(true).toBeFalsy();
187-
} catch (e) {
188-
expect(e.code).toBe("ENOENT");
189-
}
187+
}).toThrow(getErrorMessage("spk-config-yaml-load-err"));
190188
});
191189
});
192190

src/config.ts

+20-9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import fs from "fs";
33
import yaml from "js-yaml";
44
import * as os from "os";
55
import path from "path";
6+
import { build as buildError } from "./lib/errorBuilder";
7+
import { errorStatusCode } from "./lib/errorStatusCode";
68
import { writeVersion } from "./lib/fileutils";
79
import { logger } from "./logger";
810
import {
@@ -32,7 +34,10 @@ export const readYaml = <T>(filepath: string): T => {
3234
const contents = fs.readFileSync(filepath, "utf8");
3335
return yaml.safeLoad(contents) as T;
3436
}
35-
throw Error(`Unable to load file '${filepath}'`);
37+
throw buildError(errorStatusCode.FILE_IO_ERR, {
38+
errorKey: "spk-config-yaml-err-readyaml",
39+
values: [filepath],
40+
});
3641
};
3742

3843
/**
@@ -48,10 +53,10 @@ export const updateVariableWithLocalEnv = (value: string): string => {
4853
if (process.env[matches[1]]) {
4954
value = value.replace(matches[0], process.env[matches[1]] as string);
5055
} else {
51-
logger.error(`Env variable needs to be defined for ${matches[1]}`);
52-
throw Error(
53-
`Environment variable needs to be defined for ${matches[1]} since it's referenced in the config file.`
54-
);
56+
throw buildError(errorStatusCode.ENV_SETTING_ERR, {
57+
errorKey: "spk-config-yaml-var-undefined",
58+
values: [matches[1]],
59+
});
5560
}
5661
matches = regexp.exec(value);
5762
}
@@ -117,8 +122,11 @@ export const loadConfiguration = (
117122
const data = readYaml<ConfigYaml>(filepath);
118123
spkConfig = loadConfigurationFromLocalEnv(data || {});
119124
} catch (err) {
120-
logger.verbose(`An error occurred while loading configuration\n ${err}`);
121-
throw err;
125+
throw buildError(
126+
errorStatusCode.FILE_IO_ERR,
127+
"spk-config-yaml-load-err",
128+
err
129+
);
122130
}
123131
};
124132

@@ -188,7 +196,10 @@ export const Bedrock = (fileDirectory = process.cwd()): BedrockFile => {
188196
for (const error of helmErrors) {
189197
logger.error(error);
190198
}
191-
throw Error(`invalid helm configuration found in ${bedrockYamlPath}`);
199+
throw buildError(errorStatusCode.ENV_SETTING_ERR, {
200+
errorKey: "bedrock-config-invalid",
201+
values: [bedrockYamlPath],
202+
});
192203
}
193204

194205
return { ...bedrock };
@@ -248,7 +259,7 @@ export const write = (
248259
} else {
249260
// Is azure pipelines yaml file
250261
if (typeof fileName === "undefined") {
251-
throw new Error(`Pipeline yaml file name is undefined`);
262+
throw buildError(errorStatusCode.EXE_FLOW_ERR, "config-file-not-defined");
252263
}
253264

254265
writeVersion(path.join(targetDirectory, fileName));

src/lib/azdoClient.ts

+46-19
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { RestClient } from "typed-rest-client";
66
import { Config } from "../config";
77
import { logger } from "../logger";
88
import { AzureDevOpsOpts } from "./git";
9+
import { build as buildError } from "./errorBuilder";
10+
import { errorStatusCode } from "./errorStatusCode";
911

1012
// Module state Variables
1113
let connection: WebApi | undefined;
@@ -41,15 +43,17 @@ export const getWebApi = async (
4143
} = opts;
4244

4345
// PAT and devops URL are required
44-
if (typeof personalAccessToken === "undefined") {
45-
throw Error(
46-
`Unable to parse Azure DevOps Personal Access Token (azure_devops.access_token) from spk config`
46+
if (!personalAccessToken) {
47+
throw buildError(
48+
errorStatusCode.AZURE_CLIENT,
49+
"azure-client-get-web-api-err-missing-access-token"
4750
);
4851
}
4952

50-
if (typeof orgName === "undefined") {
51-
throw Error(
52-
`Unable to parse Azure DevOps Organization name (azure_devops.org) from spk config`
53+
if (!orgName) {
54+
throw buildError(
55+
errorStatusCode.AZURE_CLIENT,
56+
"azure-client-get-web-api-err-missing-org"
5357
);
5458
}
5559

@@ -61,7 +65,6 @@ export const getWebApi = async (
6165

6266
const authHandler = getPersonalAccessTokenHandler(personalAccessToken);
6367
connection = new WebApi(orgUrl, authHandler);
64-
6568
return connection;
6669
};
6770

@@ -77,13 +80,21 @@ export const invalidateWebApi = (): void => {
7780
export const getRestClient = async (
7881
opts: AzureDevOpsOpts = {}
7982
): Promise<RestClient> => {
80-
if (typeof restApi !== "undefined") {
83+
if (restApi) {
8184
return restApi;
8285
}
8386

84-
const webApi = await getWebApi(opts);
85-
restApi = webApi.rest;
86-
return restApi;
87+
try {
88+
const webApi = await getWebApi(opts);
89+
restApi = webApi.rest;
90+
return restApi;
91+
} catch (err) {
92+
throw buildError(
93+
errorStatusCode.AZURE_CLIENT,
94+
"azure-client-get-rest-client-err",
95+
err
96+
);
97+
}
8798
};
8899

89100
/**
@@ -94,13 +105,21 @@ export const getRestClient = async (
94105
export const getBuildApi = async (
95106
opts: AzureDevOpsOpts = {}
96107
): Promise<IBuildApi> => {
97-
if (typeof buildApi !== "undefined") {
108+
if (buildApi) {
98109
return buildApi;
99110
}
100111

101-
const webApi = await getWebApi(opts);
102-
buildApi = await webApi.getBuildApi();
103-
return buildApi;
112+
try {
113+
const webApi = await getWebApi(opts);
114+
buildApi = await webApi.getBuildApi();
115+
return buildApi;
116+
} catch (err) {
117+
throw buildError(
118+
errorStatusCode.AZURE_CLIENT,
119+
"azure-client-get-build-client-err",
120+
err
121+
);
122+
}
104123
};
105124

106125
/**
@@ -112,11 +131,19 @@ export const getBuildApi = async (
112131
export const getTaskAgentApi = async (
113132
opts: AzureDevOpsOpts = {}
114133
): Promise<ITaskAgentApi> => {
115-
if (typeof taskAgentApi !== "undefined") {
134+
if (taskAgentApi) {
116135
return taskAgentApi;
117136
}
118137

119-
const webApi = await getWebApi(opts);
120-
taskAgentApi = await webApi.getTaskAgentApi();
121-
return taskAgentApi;
138+
try {
139+
const webApi = await getWebApi(opts);
140+
taskAgentApi = await webApi.getTaskAgentApi();
141+
return taskAgentApi;
142+
} catch (err) {
143+
throw buildError(
144+
errorStatusCode.AZURE_CLIENT,
145+
"azure-client-get-task-agent-client-err",
146+
err
147+
);
148+
}
122149
};

src/lib/azure/servicePrincipalService.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { logger } from "../../logger";
22
import { exec } from "../shell";
3+
import { build as buildError } from "../errorBuilder";
4+
import { errorStatusCode } from "../errorStatusCode";
35

46
export interface ServicePrincipal {
57
id: string;
@@ -29,9 +31,7 @@ export const azCLILogin = async (): Promise<SubscriptionData[]> => {
2931
};
3032
});
3133
} catch (err) {
32-
logger.error("Unable to execute az login");
33-
logger.error(err);
34-
throw err;
34+
throw buildError(errorStatusCode.AZURE_CLI_ERR, "az-cli-login-err", err);
3535
}
3636
};
3737

@@ -61,8 +61,10 @@ export const createWithAzCLI = async (
6161
tenantId: oResult.tenant,
6262
};
6363
} catch (err) {
64-
logger.error("Unable to create service principal with az command line");
65-
logger.error(err);
66-
throw err;
64+
throw buildError(
65+
errorStatusCode.AZURE_CLI_ERR,
66+
"az-cli-create-sp-err",
67+
err
68+
);
6769
}
6870
};

0 commit comments

Comments
 (0)