Skip to content

Commit 1c5c137

Browse files
authored
consume getJson function for better error messages (#110)
1 parent d123f10 commit 1c5c137

File tree

6 files changed

+135
-31
lines changed

6 files changed

+135
-31
lines changed

.github/workflows/workflow.yml

-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ jobs:
2222
- run: npm ci
2323
- run: npm run build
2424
- run: npm run format-check
25-
- run: npm run pack
2625
- run: npm test
2726
- name: Verify no unstaged changes
2827
if: runner.os != 'windows'

__tests__/verify-no-unstaged-changes.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ if [[ "$(git status --porcelain)" != "" ]]; then
1212
echo ----------------------------------------
1313
echo Troubleshooting
1414
echo ----------------------------------------
15-
echo "::error::Unstaged changes detected. Locally try running: git clean -ffdx && npm ci && npm run all"
15+
echo "::error::Unstaged changes detected. Locally try running: git clean -ffdx && npm ci && npm run pre-checkin"
1616
exit 1
1717
fi

dist/index.js

+116-5
Original file line numberDiff line numberDiff line change
@@ -10602,6 +10602,15 @@ var HttpCodes;
1060210602
HttpCodes[HttpCodes["ServiceUnavailable"] = 503] = "ServiceUnavailable";
1060310603
HttpCodes[HttpCodes["GatewayTimeout"] = 504] = "GatewayTimeout";
1060410604
})(HttpCodes = exports.HttpCodes || (exports.HttpCodes = {}));
10605+
var Headers;
10606+
(function (Headers) {
10607+
Headers["Accept"] = "accept";
10608+
Headers["ContentType"] = "content-type";
10609+
})(Headers = exports.Headers || (exports.Headers = {}));
10610+
var MediaTypes;
10611+
(function (MediaTypes) {
10612+
MediaTypes["ApplicationJson"] = "application/json";
10613+
})(MediaTypes = exports.MediaTypes || (exports.MediaTypes = {}));
1060510614
/**
1060610615
* Returns the proxy URL, depending upon the supplied url and proxy environment variables.
1060710616
* @param serverUrl The server URL where the request will be sent. For example, https://api.github.com
@@ -10700,6 +10709,36 @@ class HttpClient {
1070010709
sendStream(verb, requestUrl, stream, additionalHeaders) {
1070110710
return this.request(verb, requestUrl, stream, additionalHeaders);
1070210711
}
10712+
/**
10713+
* Gets a typed object from an endpoint
10714+
* Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise
10715+
*/
10716+
async getJson(requestUrl, additionalHeaders = {}) {
10717+
additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson);
10718+
let res = await this.get(requestUrl, additionalHeaders);
10719+
return this._processResponse(res, this.requestOptions);
10720+
}
10721+
async postJson(requestUrl, obj, additionalHeaders = {}) {
10722+
let data = JSON.stringify(obj, null, 2);
10723+
additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson);
10724+
additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson);
10725+
let res = await this.post(requestUrl, data, additionalHeaders);
10726+
return this._processResponse(res, this.requestOptions);
10727+
}
10728+
async putJson(requestUrl, obj, additionalHeaders = {}) {
10729+
let data = JSON.stringify(obj, null, 2);
10730+
additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson);
10731+
additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson);
10732+
let res = await this.put(requestUrl, data, additionalHeaders);
10733+
return this._processResponse(res, this.requestOptions);
10734+
}
10735+
async patchJson(requestUrl, obj, additionalHeaders = {}) {
10736+
let data = JSON.stringify(obj, null, 2);
10737+
additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson);
10738+
additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson);
10739+
let res = await this.patch(requestUrl, data, additionalHeaders);
10740+
return this._processResponse(res, this.requestOptions);
10741+
}
1070310742
/**
1070410743
* Makes a raw http request.
1070510744
* All other methods such as get, post, patch, and request ultimately call this.
@@ -10883,6 +10922,14 @@ class HttpClient {
1088310922
}
1088410923
return lowercaseKeys(headers || {});
1088510924
}
10925+
_getExistingOrDefaultHeader(additionalHeaders, header, _default) {
10926+
const lowercaseKeys = obj => Object.keys(obj).reduce((c, k) => (c[k.toLowerCase()] = obj[k], c), {});
10927+
let clientHeader;
10928+
if (this.requestOptions && this.requestOptions.headers) {
10929+
clientHeader = lowercaseKeys(this.requestOptions.headers)[header];
10930+
}
10931+
return additionalHeaders[header] || clientHeader || _default;
10932+
}
1088610933
_getAgent(parsedUrl) {
1088710934
let agent;
1088810935
let proxyUrl = pm.getProxyUrl(parsedUrl);
@@ -10950,6 +10997,73 @@ class HttpClient {
1095010997
const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber);
1095110998
return new Promise(resolve => setTimeout(() => resolve(), ms));
1095210999
}
11000+
static dateTimeDeserializer(key, value) {
11001+
if (typeof value === 'string') {
11002+
let a = new Date(value);
11003+
if (!isNaN(a.valueOf())) {
11004+
return a;
11005+
}
11006+
}
11007+
return value;
11008+
}
11009+
async _processResponse(res, options) {
11010+
return new Promise(async (resolve, reject) => {
11011+
const statusCode = res.message.statusCode;
11012+
const response = {
11013+
statusCode: statusCode,
11014+
result: null,
11015+
headers: {}
11016+
};
11017+
// not found leads to null obj returned
11018+
if (statusCode == HttpCodes.NotFound) {
11019+
resolve(response);
11020+
}
11021+
let obj;
11022+
let contents;
11023+
// get the result from the body
11024+
try {
11025+
contents = await res.readBody();
11026+
if (contents && contents.length > 0) {
11027+
if (options && options.deserializeDates) {
11028+
obj = JSON.parse(contents, HttpClient.dateTimeDeserializer);
11029+
}
11030+
else {
11031+
obj = JSON.parse(contents);
11032+
}
11033+
response.result = obj;
11034+
}
11035+
response.headers = res.message.headers;
11036+
}
11037+
catch (err) {
11038+
// Invalid resource (contents not json); leaving result obj null
11039+
}
11040+
// note that 3xx redirects are handled by the http layer.
11041+
if (statusCode > 299) {
11042+
let msg;
11043+
// if exception/error in body, attempt to get better error
11044+
if (obj && obj.message) {
11045+
msg = obj.message;
11046+
}
11047+
else if (contents && contents.length > 0) {
11048+
// it may be the case that the exception is in the body message as string
11049+
msg = contents;
11050+
}
11051+
else {
11052+
msg = "Failed request: (" + statusCode + ")";
11053+
}
11054+
let err = new Error(msg);
11055+
// attach statusCode and body obj (if available) to the error object
11056+
err['statusCode'] = statusCode;
11057+
if (response.result) {
11058+
err['result'] = response.result;
11059+
}
11060+
reject(err);
11061+
}
11062+
else {
11063+
resolve(response);
11064+
}
11065+
});
11066+
}
1095311067
}
1095411068
exports.HttpClient = HttpClient;
1095511069

@@ -11979,7 +12093,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
1197912093
Object.defineProperty(exports, "__esModule", { value: true });
1198012094
// Load tempDirectory before it gets wiped by tool-cache
1198112095
let tempDirectory = process.env['RUNNER_TEMPDIRECTORY'] || '';
11982-
const assert = __importStar(__webpack_require__(357));
1198312096
const core = __importStar(__webpack_require__(470));
1198412097
const hc = __importStar(__webpack_require__(539));
1198512098
const io = __importStar(__webpack_require__(1));
@@ -12070,10 +12183,8 @@ function queryLatestMatch(versionSpec) {
1207012183
allowRetries: true,
1207112184
maxRetries: 3
1207212185
});
12073-
let response = yield httpClient.get(dataUrl);
12074-
assert.ok(response.message.statusCode === 200, `Unexpected HTTP status code '${response.message.statusCode}'`);
12075-
let body = yield response.readBody();
12076-
let nodeVersions = JSON.parse(body);
12186+
let response = yield httpClient.getJson(dataUrl);
12187+
let nodeVersions = response.result || [];
1207712188
nodeVersions.forEach((nodeVersion) => {
1207812189
// ensure this version supports your os and platform
1207912190
if (nodeVersion.files.indexOf(dataFileName) >= 0) {

package-lock.json

+13-13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3-4
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@
55
"description": "setup node action",
66
"main": "lib/setup-node.js",
77
"scripts": {
8-
"build": "tsc",
8+
"build": "tsc && ncc build",
99
"format": "prettier --write **/*.ts",
1010
"format-check": "prettier --check **/*.ts",
11-
"pack": "ncc build",
1211
"test": "jest",
13-
"all": "npm run build && npm run format && npm run pack && npm test"
12+
"pre-checkin": "npm run format && npm run build && npm test"
1413
},
1514
"repository": {
1615
"type": "git",
@@ -26,7 +25,7 @@
2625
"dependencies": {
2726
"@actions/core": "^1.2.2",
2827
"@actions/github": "^1.1.0",
29-
"@actions/http-client": "^1.0.3",
28+
"@actions/http-client": "^1.0.6",
3029
"@actions/io": "^1.0.2",
3130
"@actions/tool-cache": "^1.3.1",
3231
"semver": "^6.1.1"

src/installer.ts

+2-7
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,8 @@ async function queryLatestMatch(versionSpec: string): Promise<string> {
105105
allowRetries: true,
106106
maxRetries: 3
107107
});
108-
let response = await httpClient.get(dataUrl);
109-
assert.ok(
110-
response.message.statusCode === 200,
111-
`Unexpected HTTP status code '${response.message.statusCode}'`
112-
);
113-
let body = await response.readBody();
114-
let nodeVersions = JSON.parse(body) as INodeVersion[];
108+
let response = await httpClient.getJson<INodeVersion[]>(dataUrl);
109+
let nodeVersions = response.result || [];
115110
nodeVersions.forEach((nodeVersion: INodeVersion) => {
116111
// ensure this version supports your os and platform
117112
if (nodeVersion.files.indexOf(dataFileName) >= 0) {

0 commit comments

Comments
 (0)