Compare commits

..

27 Commits

Author SHA1 Message Date
8dc49dbd17 Adding node modules 2020-07-22 21:25:03 -07:00
f25dd68be2 Merge branch 'dependabot/npm_and_yarn/lodash-4.17.19' into dev 2020-07-22 21:15:24 -07:00
3fedb575b0 Merge branch 'dev' into dependabot/npm_and_yarn/lodash-4.17.19 2020-07-22 21:15:13 -07:00
84ff5b46d8 Merge branch 'dependabot/npm_and_yarn/actions/http-client-1.0.8' into dev 2020-07-22 21:14:53 -07:00
e4874c190b Merge branch 'dependabot/npm_and_yarn/acorn-5.7.4' into dev 2020-07-22 21:14:33 -07:00
41a4f5dd79 Merge branch 'dev' into dependabot/npm_and_yarn/acorn-5.7.4 2020-07-22 21:14:17 -07:00
9c8b0140a4 Merge branch 'dev' into dependabot/npm_and_yarn/actions/http-client-1.0.8 2020-07-22 21:13:00 -07:00
57920ca044 Merge branch 'heaths-issue10' into dev 2020-07-22 20:55:48 -07:00
0d4f73260b Bump lodash from 4.17.15 to 4.17.19
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-20 00:55:11 +00:00
341cfb53e3 Bump @actions/http-client from 1.0.2 to 1.0.8
Bumps [@actions/http-client](https://github.com/actions/http-client) from 1.0.2 to 1.0.8.
- [Release notes](https://github.com/actions/http-client/releases)
- [Changelog](https://github.com/actions/http-client/blob/master/RELEASES.md)
- [Commits](https://github.com/actions/http-client/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2020-04-29 18:02:20 +00:00
c4f3bee2c4 Add tests for different path resolution 2020-04-21 17:04:39 -07:00
20e1303853 Fix tool lookup and revert logging 2020-04-21 16:57:28 -07:00
e9f4898311 Add more logging 2020-04-21 16:50:45 -07:00
9499ca8787 Fix path resolution
Looking for vswhere in the PATH was never triggered and had some bugs (like failing unconditionally if the code path was executed).
2020-04-21 16:27:45 -07:00
0ddbddf06e Quote vs-version example 2020-04-21 16:14:19 -07:00
80d0deb83b Use -latest and -version properly
Fixes #8
2020-04-21 15:46:27 -07:00
2f9b9c17d6 Use specific paths for faster lookup
Fixes #2
2020-04-21 15:38:49 -07:00
7d7af37b7e Fix sync/async callback issue 2020-04-21 15:38:49 -07:00
5cf04033c1 Use sync callback 2020-04-21 15:38:49 -07:00
f6890ff843 Fix typo 2020-04-21 15:38:49 -07:00
f486e795bf Add pull_request to Actions triggers 2020-04-21 15:38:49 -07:00
4652bfc96e Do not use newer -find parameter
Fixes #10
2020-04-21 15:38:49 -07:00
bb70c6a023 Find any product with MSBuild component
Fixes #7
2020-04-21 15:38:49 -07:00
dc59c705e4 Merge pull request #16 from microsoft/dev
Merge pull request #15 from microsoft/master
2020-04-21 13:22:43 -07:00
f05df80b32 Merge pull request #15 from microsoft/master
Adding remark about arguments in readme
2020-04-21 13:21:03 -07:00
43cd4ebaec Bump acorn from 5.7.3 to 5.7.4
Bumps [acorn](https://github.com/acornjs/acorn) from 5.7.3 to 5.7.4.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/5.7.3...5.7.4)

Signed-off-by: dependabot[bot] <support@github.com>
2020-03-26 15:44:00 +00:00
9c9a1a34a4 Adding remark about arguments in readme 2020-03-26 08:42:27 -07:00
30 changed files with 508 additions and 168 deletions

View File

@ -1,5 +1,10 @@
name: "build-test-dev" name: "build-test-dev"
on: on:
pull_request:
branches:
- dev
paths-ignore:
- '*.md'
push: push:
branches: branches:
- dev - dev
@ -12,14 +17,27 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Setup MSBuild - name: Setup MSBuild (vswhere-path)
id: setup_msbuild id: setup_msbuild_explicit
uses: ./ uses: ./
with: with:
vs-version: "[16.4,16.5]" vswhere-path: C:\ProgramData\chocolatey\bin
- name: Setup MSBuild (PATH)
id: setup_msbuild_path
uses: ./
- name: Setup MSBuild (fallback)
id: setup_msbuild_fallback
uses: ./
env:
PATH: ''
- name: echo msbuild path - name: echo msbuild path
run: echo "${{ steps.setup_msbuild.outputs.msbuildPath }}" run: |
echo "vswhere-path: ${{ steps.setup_msbuild_explicit.outputs.msbuildPath }}"
echo "PATH: ${{ steps.setup_msbuild_path.outputs.msbuildPath }}"
echo "Fallback: ${{ steps.setup_msbuild_fallback.outputs.msbuildPath }}"
- name: echo MSBuild - name: echo MSBuild
run: msbuild -version run: msbuild -version

View File

@ -3,35 +3,40 @@ You know how handy that 'Visual Studio Developer Command Prompt' is on your loca
## Usage ## Usage
``` ```yml
- name: Add msbuild to PATH - name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.0.0 uses: microsoft/setup-msbuild@v1.0.1
``` ```
## Specifying specific versions of Visual Studio ## Specifying specific versions of Visual Studio
You may have a situation where your Actions runner has multiple versions of Visual Studio and you need to find a specific version of the tool. Simply add the `vs-version` input to specify the range of versions to find. If looking for a specific version, enter that version number twice as a range. You may have a situation where your Actions runner has multiple versions of Visual Studio and you need to find a specific version of the tool. Simply add the `vs-version` input to specify the range of versions to find. If looking for a specific version, specify the minimum and maximum versions as shown in the example below, which will look for just 16.4.
``` ```yml
- name: Add msbuild to PATH - name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.0.0 uses: microsoft/setup-msbuild@v1.0.1
with: with:
vs-version: [16.4,16.5] vs-version: '[16.4,16.5)'
``` ```
The syntax is the same used for Visual Studio extensions, where square brackets like "[" mean inclusive, and parenthesis like "(" mean exclusive. A comma is always required, but eliding the minimum version looks for all older versions and eliding the maximum version looks for all newer versions. See the [vswhere wiki](https://github.com/microsoft/vswhere/wiki) for more details.
## How does this work? ## How does this work?
This makes use of the vswhere tool which is a tool is delivered by Microsoft to help in identifying Visual Studio installs and various components. This tool is installed on the hosted Windows runners for GitHub Actions. If you are using a self-hosted runner, you either need to make sure vswhere.exe is in your agent's PATH or specify a full path to the location using: This makes use of the vswhere tool which is a tool is delivered by Microsoft to help in identifying Visual Studio installs and various components. This tool is installed on the hosted Windows runners for GitHub Actions. If you are using a self-hosted runner, you either need to make sure vswhere.exe is in your agent's PATH or specify a full path to the location using:
``` ```yml
- name: Add msbuild to PATH - name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.0.0 uses: microsoft/setup-msbuild@v1.0.1
with: with:
vswhere-path: 'C:\path\to\your\tools\' vswhere-path: 'C:\path\to\your\tools\'
``` ```
## Notes on arguments
While the Action enables you to specify a `vswhere` path as well as a `vs-version`, these are more advanced options and when using GitHub-hosted runners you should not need these and is recommended you don't specify them. Using these require you to fully understand the runner environment, updates to the tools on the runner, and can cause failures if you are out of sync. For GitHub-hosted runners, omitting these arguments is the preferred usage.
## Building this repo ## Building this repo
As with most GitHub Actions, this requires NodeJS development tools. After installing NodeJS, you can build this by executing: As with most GitHub Actions, this requires NodeJS development tools. After installing NodeJS, you can build this by executing:
``` ```bash
npm install npm install
npm run build npm run build
npm run pack npm run pack

44
dist/index.js vendored
View File

@ -972,22 +972,17 @@ var __importStar = (this && this.__importStar) || function (mod) {
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(__webpack_require__(470)); const core = __importStar(__webpack_require__(470));
const exec = __importStar(__webpack_require__(986)); const exec = __importStar(__webpack_require__(986));
const fs = __importStar(__webpack_require__(747));
const path = __importStar(__webpack_require__(622)); const path = __importStar(__webpack_require__(622));
const io = __importStar(__webpack_require__(1)); const io = __importStar(__webpack_require__(1));
const IS_WINDOWS = process.platform === 'win32'; const IS_WINDOWS = process.platform === 'win32';
const VS_VERSION = core.getInput('vs-version') || 'latest'; const VS_VERSION = core.getInput('vs-version') || 'latest';
const VSWHERE_PATH = core.getInput('vswhere-path') || const VSWHERE_PATH = core.getInput('vswhere-path');
path.join(process.env['ProgramFiles(x86)'], 'Microsoft Visual Studio\\Installer');
// if a specific version of VS is requested // if a specific version of VS is requested
let VSWHERE_EXEC = ''; let VSWHERE_EXEC = '-products * -requires Microsoft.Component.MSBuild -property installationPath -latest ';
if (VS_VERSION === 'latest') { if (VS_VERSION !== 'latest') {
VSWHERE_EXEC += '-latest '; VSWHERE_EXEC += `-version "${VS_VERSION}" `;
} }
else {
VSWHERE_EXEC += `-version ${VS_VERSION} `;
}
VSWHERE_EXEC +=
'-requires Microsoft.Component.MSBuild -find MSBuild\\**\\Bin\\MSBuild.exe';
core.debug(`Execution arguments: ${VSWHERE_EXEC}`); core.debug(`Execution arguments: ${VSWHERE_EXEC}`);
function run() { function run() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
@ -1001,6 +996,7 @@ function run() {
let vswhereToolExe = ''; let vswhereToolExe = '';
if (VSWHERE_PATH) { if (VSWHERE_PATH) {
// specified a path for vswhere, use it // specified a path for vswhere, use it
core.debug(`Using given vswhere-path: ${VSWHERE_PATH}`);
vswhereToolExe = path.join(VSWHERE_PATH, 'vswhere.exe'); vswhereToolExe = path.join(VSWHERE_PATH, 'vswhere.exe');
} }
else { else {
@ -1008,29 +1004,41 @@ function run() {
try { try {
const vsWhereInPath = yield io.which('vswhere', true); const vsWhereInPath = yield io.which('vswhere', true);
core.debug(`Found tool in PATH: ${vsWhereInPath}`); core.debug(`Found tool in PATH: ${vsWhereInPath}`);
vswhereToolExe = path.join(vsWhereInPath, 'vswhere.exe'); vswhereToolExe = vsWhereInPath;
} }
catch (_a) { catch (_a) {
// wasn't found because which threw // fall back to VS-installed path
vswhereToolExe = path.join(process.env['ProgramFiles(x86)'], 'Microsoft Visual Studio\\Installer\\vswhere.exe');
core.debug(`Trying Visual Studio-installed path: ${vswhereToolExe}`);
} }
finally { }
if (!fs.existsSync(vswhereToolExe)) {
core.setFailed('setup-msbuild requires the path to where vswhere.exe exists'); core.setFailed('setup-msbuild requires the path to where vswhere.exe exists');
} return;
} }
core.debug(`Full tool exe: ${vswhereToolExe}`); core.debug(`Full tool exe: ${vswhereToolExe}`);
let foundToolPath = ''; let foundToolPath = '';
const options = {}; const options = {};
options.listeners = { options.listeners = {
stdout: (data) => { stdout: (data) => {
// eslint-disable-next-line prefer-const const installationPath = data.toString().trim();
let output = data.toString(); core.debug(`Found installation path: ${installationPath}`);
foundToolPath += output; let toolPath = path.join(installationPath, 'MSBuild\\Current\\Bin\\MSBuild.exe');
core.debug(`Checking for path: ${toolPath}`);
if (!fs.existsSync(toolPath)) {
toolPath = path.join(installationPath, 'MSBuild\\15.0\\Bin\\MSBuild.exe');
core.debug(`Checking for path: ${toolPath}`);
if (!fs.existsSync(toolPath)) {
return;
}
}
foundToolPath = toolPath;
} }
}; };
// execute the find putting the result of the command in the options foundToolPath // execute the find putting the result of the command in the options foundToolPath
yield exec.exec(`"${vswhereToolExe}" ${VSWHERE_EXEC}`, [], options); yield exec.exec(`"${vswhereToolExe}" ${VSWHERE_EXEC}`, [], options);
if (!foundToolPath) { if (!foundToolPath) {
core.setFailed('Unable to find msbuild.'); core.setFailed('Unable to find MSBuild.');
return; return;
} }
// extract the folder location for the tool // extract the folder location for the tool

2
node_modules/.bin/semver generated vendored
View File

@ -2,7 +2,7 @@
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in case `uname` in
*CYGWIN*) basedir=`cygpath -w "$basedir"`;; *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac esac
if [ -x "$basedir/node" ]; then if [ -x "$basedir/node" ]; then

20
node_modules/.bin/semver.cmd generated vendored
View File

@ -1,7 +1,17 @@
@IF EXIST "%~dp0\node.exe" ( @ECHO off
"%~dp0\node.exe" "%~dp0\..\semver\bin\semver.js" %* SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE ( ) ELSE (
@SETLOCAL SET "_prog=node"
@SET PATHEXT=%PATHEXT:;.JS;=;% SET PATHEXT=%PATHEXT:;.JS;=;%
node "%~dp0\..\semver\bin\semver.js" %*
) )
"%_prog%" "%dp0%\..\semver\bin\semver.js" %*
ENDLOCAL
EXIT /b %errorlevel%
:find_dp0
SET dp0=%~dp0
EXIT /b

18
node_modules/.bin/semver.ps1 generated vendored Normal file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
& "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args
$ret=$LASTEXITCODE
} else {
& "node$exe" "$basedir/../semver/bin/semver.js" $args
$ret=$LASTEXITCODE
}
exit $ret

2
node_modules/.bin/uuid generated vendored
View File

@ -2,7 +2,7 @@
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in case `uname` in
*CYGWIN*) basedir=`cygpath -w "$basedir"`;; *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac esac
if [ -x "$basedir/node" ]; then if [ -x "$basedir/node" ]; then

20
node_modules/.bin/uuid.cmd generated vendored
View File

@ -1,7 +1,17 @@
@IF EXIST "%~dp0\node.exe" ( @ECHO off
"%~dp0\node.exe" "%~dp0\..\uuid\bin\uuid" %* SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE ( ) ELSE (
@SETLOCAL SET "_prog=node"
@SET PATHEXT=%PATHEXT:;.JS;=;% SET PATHEXT=%PATHEXT:;.JS;=;%
node "%~dp0\..\uuid\bin\uuid" %*
) )
"%_prog%" "%dp0%\..\uuid\bin\uuid" %*
ENDLOCAL
EXIT /b %errorlevel%
:find_dp0
SET dp0=%~dp0
EXIT /b

18
node_modules/.bin/uuid.ps1 generated vendored Normal file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
& "$basedir/node$exe" "$basedir/../uuid/bin/uuid" $args
$ret=$LASTEXITCODE
} else {
& "node$exe" "$basedir/../uuid/bin/uuid" $args
$ret=$LASTEXITCODE
}
exit $ret

View File

@ -2,7 +2,7 @@
"_args": [ "_args": [
[ [
"@actions/core@1.2.0", "@actions/core@1.2.0",
"C:\\users\\timheuer\\documents\\github\\setup-msbuild" "C:\\Users\\timheuer\\Documents\\GitHub\\setup-msbuild"
] ]
], ],
"_from": "@actions/core@1.2.0", "_from": "@actions/core@1.2.0",
@ -28,7 +28,7 @@
], ],
"_resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.0.tgz", "_resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.0.tgz",
"_spec": "1.2.0", "_spec": "1.2.0",
"_where": "C:\\users\\timheuer\\documents\\github\\setup-msbuild", "_where": "C:\\Users\\timheuer\\Documents\\GitHub\\setup-msbuild",
"bugs": { "bugs": {
"url": "https://github.com/actions/toolkit/issues" "url": "https://github.com/actions/toolkit/issues"
}, },

View File

@ -2,7 +2,7 @@
"_args": [ "_args": [
[ [
"@actions/exec@1.0.3", "@actions/exec@1.0.3",
"C:\\users\\timheuer\\documents\\github\\setup-msbuild" "C:\\Users\\timheuer\\Documents\\GitHub\\setup-msbuild"
] ]
], ],
"_from": "@actions/exec@1.0.3", "_from": "@actions/exec@1.0.3",
@ -28,7 +28,7 @@
], ],
"_resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.0.3.tgz", "_resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.0.3.tgz",
"_spec": "1.0.3", "_spec": "1.0.3",
"_where": "C:\\users\\timheuer\\documents\\github\\setup-msbuild", "_where": "C:\\Users\\timheuer\\Documents\\GitHub\\setup-msbuild",
"bugs": { "bugs": {
"url": "https://github.com/actions/toolkit/issues" "url": "https://github.com/actions/toolkit/issues"
}, },

View File

@ -18,6 +18,8 @@ A lightweight HTTP client optimized for use with actions, TypeScript with generi
- Basic, Bearer and PAT Support out of the box. Extensible handlers for others. - Basic, Bearer and PAT Support out of the box. Extensible handlers for others.
- Redirects supported - Redirects supported
Features and releases [here](./RELEASES.md)
## Install ## Install
``` ```
@ -49,7 +51,11 @@ export NODE_DEBUG=http
## Node support ## Node support
The http-client is built using the latest LTS version of Node 12. We also support the latest LTS for Node 6, 8 and Node 10. The http-client is built using the latest LTS version of Node 12. It may work on previous node LTS versions but it's tested and officially supported on Node12+.
## Support and Versioning
We follow semver and will hold compatibility between major versions and increment the minor version with new features and capabilities (while holding compat).
## Contributing ## Contributing

16
node_modules/@actions/http-client/RELEASES.md generated vendored Normal file
View File

@ -0,0 +1,16 @@
## Releases
## 1.0.7
Update NPM dependencies and add 429 to the list of HttpCodes
## 1.0.6
Automatically sends Content-Type and Accept application/json headers for \<verb>Json() helper methods if not set in the client or parameters.
## 1.0.5
Adds \<verb>Json() helper methods for json over http scenarios.
## 1.0.4
Started to add \<verb>Json() helper methods. Do not use this release for that. Use >= 1.0.5 since there was an issue with types.
## 1.0.1 to 1.0.3
Adds proxy support.

View File

@ -6,7 +6,9 @@ class BasicCredentialHandler {
this.password = password; this.password = password;
} }
prepareRequest(options) { prepareRequest(options) {
options.headers['Authorization'] = 'Basic ' + Buffer.from(this.username + ':' + this.password).toString('base64'); options.headers['Authorization'] =
'Basic ' +
Buffer.from(this.username + ':' + this.password).toString('base64');
} }
// This handler cannot handle 401 // This handler cannot handle 401
canHandleAuthentication(response) { canHandleAuthentication(response) {
@ -42,7 +44,8 @@ class PersonalAccessTokenCredentialHandler {
// currently implements pre-authorization // currently implements pre-authorization
// TODO: support preAuth = false where it hooks on 401 // TODO: support preAuth = false where it hooks on 401
prepareRequest(options) { prepareRequest(options) {
options.headers['Authorization'] = 'Basic ' + Buffer.from('PAT:' + this.token).toString('base64'); options.headers['Authorization'] =
'Basic ' + Buffer.from('PAT:' + this.token).toString('base64');
} }
// This handler cannot handle 401 // This handler cannot handle 401
canHandleAuthentication(response) { canHandleAuthentication(response) {

View File

@ -1,5 +1,5 @@
/// <reference types="node" /> /// <reference types="node" />
import http = require("http"); import http = require('http');
import ifm = require('./interfaces'); import ifm = require('./interfaces');
export declare enum HttpCodes { export declare enum HttpCodes {
OK = 200, OK = 200,
@ -23,12 +23,25 @@ export declare enum HttpCodes {
RequestTimeout = 408, RequestTimeout = 408,
Conflict = 409, Conflict = 409,
Gone = 410, Gone = 410,
TooManyRequests = 429,
InternalServerError = 500, InternalServerError = 500,
NotImplemented = 501, NotImplemented = 501,
BadGateway = 502, BadGateway = 502,
ServiceUnavailable = 503, ServiceUnavailable = 503,
GatewayTimeout = 504 GatewayTimeout = 504
} }
export declare enum Headers {
Accept = "accept",
ContentType = "content-type"
}
export declare enum MediaTypes {
ApplicationJson = "application/json"
}
/**
* Returns the proxy URL, depending upon the supplied url and proxy environment variables.
* @param serverUrl The server URL where the request will be sent. For example, https://api.github.com
*/
export declare function getProxyUrl(serverUrl: string): string;
export declare class HttpClientResponse implements ifm.IHttpClientResponse { export declare class HttpClientResponse implements ifm.IHttpClientResponse {
constructor(message: http.IncomingMessage); constructor(message: http.IncomingMessage);
message: http.IncomingMessage; message: http.IncomingMessage;
@ -59,6 +72,14 @@ export declare class HttpClient {
put(requestUrl: string, data: string, additionalHeaders?: ifm.IHeaders): Promise<ifm.IHttpClientResponse>; put(requestUrl: string, data: string, additionalHeaders?: ifm.IHeaders): Promise<ifm.IHttpClientResponse>;
head(requestUrl: string, additionalHeaders?: ifm.IHeaders): Promise<ifm.IHttpClientResponse>; head(requestUrl: string, additionalHeaders?: ifm.IHeaders): Promise<ifm.IHttpClientResponse>;
sendStream(verb: string, requestUrl: string, stream: NodeJS.ReadableStream, additionalHeaders?: ifm.IHeaders): Promise<ifm.IHttpClientResponse>; sendStream(verb: string, requestUrl: string, stream: NodeJS.ReadableStream, additionalHeaders?: ifm.IHeaders): Promise<ifm.IHttpClientResponse>;
/**
* Gets a typed object from an endpoint
* Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise
*/
getJson<T>(requestUrl: string, additionalHeaders?: ifm.IHeaders): Promise<ifm.ITypedResponse<T>>;
postJson<T>(requestUrl: string, obj: any, additionalHeaders?: ifm.IHeaders): Promise<ifm.ITypedResponse<T>>;
putJson<T>(requestUrl: string, obj: any, additionalHeaders?: ifm.IHeaders): Promise<ifm.ITypedResponse<T>>;
patchJson<T>(requestUrl: string, obj: any, additionalHeaders?: ifm.IHeaders): Promise<ifm.ITypedResponse<T>>;
/** /**
* Makes a raw http request. * Makes a raw http request.
* All other methods such as get, post, patch, and request ultimately call this. * All other methods such as get, post, patch, and request ultimately call this.
@ -90,6 +111,9 @@ export declare class HttpClient {
getAgent(serverUrl: string): http.Agent; getAgent(serverUrl: string): http.Agent;
private _prepareRequest; private _prepareRequest;
private _mergeHeaders; private _mergeHeaders;
private _getExistingOrDefaultHeader;
private _getAgent; private _getAgent;
private _performExponentialBackoff; private _performExponentialBackoff;
private static dateTimeDeserializer;
private _processResponse;
} }

View File

@ -28,14 +28,43 @@ var HttpCodes;
HttpCodes[HttpCodes["RequestTimeout"] = 408] = "RequestTimeout"; HttpCodes[HttpCodes["RequestTimeout"] = 408] = "RequestTimeout";
HttpCodes[HttpCodes["Conflict"] = 409] = "Conflict"; HttpCodes[HttpCodes["Conflict"] = 409] = "Conflict";
HttpCodes[HttpCodes["Gone"] = 410] = "Gone"; HttpCodes[HttpCodes["Gone"] = 410] = "Gone";
HttpCodes[HttpCodes["TooManyRequests"] = 429] = "TooManyRequests";
HttpCodes[HttpCodes["InternalServerError"] = 500] = "InternalServerError"; HttpCodes[HttpCodes["InternalServerError"] = 500] = "InternalServerError";
HttpCodes[HttpCodes["NotImplemented"] = 501] = "NotImplemented"; HttpCodes[HttpCodes["NotImplemented"] = 501] = "NotImplemented";
HttpCodes[HttpCodes["BadGateway"] = 502] = "BadGateway"; HttpCodes[HttpCodes["BadGateway"] = 502] = "BadGateway";
HttpCodes[HttpCodes["ServiceUnavailable"] = 503] = "ServiceUnavailable"; HttpCodes[HttpCodes["ServiceUnavailable"] = 503] = "ServiceUnavailable";
HttpCodes[HttpCodes["GatewayTimeout"] = 504] = "GatewayTimeout"; HttpCodes[HttpCodes["GatewayTimeout"] = 504] = "GatewayTimeout";
})(HttpCodes = exports.HttpCodes || (exports.HttpCodes = {})); })(HttpCodes = exports.HttpCodes || (exports.HttpCodes = {}));
const HttpRedirectCodes = [HttpCodes.MovedPermanently, HttpCodes.ResourceMoved, HttpCodes.SeeOther, HttpCodes.TemporaryRedirect, HttpCodes.PermanentRedirect]; var Headers;
const HttpResponseRetryCodes = [HttpCodes.BadGateway, HttpCodes.ServiceUnavailable, HttpCodes.GatewayTimeout]; (function (Headers) {
Headers["Accept"] = "accept";
Headers["ContentType"] = "content-type";
})(Headers = exports.Headers || (exports.Headers = {}));
var MediaTypes;
(function (MediaTypes) {
MediaTypes["ApplicationJson"] = "application/json";
})(MediaTypes = exports.MediaTypes || (exports.MediaTypes = {}));
/**
* Returns the proxy URL, depending upon the supplied url and proxy environment variables.
* @param serverUrl The server URL where the request will be sent. For example, https://api.github.com
*/
function getProxyUrl(serverUrl) {
let proxyUrl = pm.getProxyUrl(url.parse(serverUrl));
return proxyUrl ? proxyUrl.href : '';
}
exports.getProxyUrl = getProxyUrl;
const HttpRedirectCodes = [
HttpCodes.MovedPermanently,
HttpCodes.ResourceMoved,
HttpCodes.SeeOther,
HttpCodes.TemporaryRedirect,
HttpCodes.PermanentRedirect
];
const HttpResponseRetryCodes = [
HttpCodes.BadGateway,
HttpCodes.ServiceUnavailable,
HttpCodes.GatewayTimeout
];
const RetryableHttpVerbs = ['OPTIONS', 'GET', 'DELETE', 'HEAD']; const RetryableHttpVerbs = ['OPTIONS', 'GET', 'DELETE', 'HEAD'];
const ExponentialBackoffCeiling = 10; const ExponentialBackoffCeiling = 10;
const ExponentialBackoffTimeSlice = 5; const ExponentialBackoffTimeSlice = 5;
@ -123,6 +152,36 @@ class HttpClient {
sendStream(verb, requestUrl, stream, additionalHeaders) { sendStream(verb, requestUrl, stream, additionalHeaders) {
return this.request(verb, requestUrl, stream, additionalHeaders); return this.request(verb, requestUrl, stream, additionalHeaders);
} }
/**
* Gets a typed object from an endpoint
* Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise
*/
async getJson(requestUrl, additionalHeaders = {}) {
additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson);
let res = await this.get(requestUrl, additionalHeaders);
return this._processResponse(res, this.requestOptions);
}
async postJson(requestUrl, obj, additionalHeaders = {}) {
let data = JSON.stringify(obj, null, 2);
additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson);
additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson);
let res = await this.post(requestUrl, data, additionalHeaders);
return this._processResponse(res, this.requestOptions);
}
async putJson(requestUrl, obj, additionalHeaders = {}) {
let data = JSON.stringify(obj, null, 2);
additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson);
additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson);
let res = await this.put(requestUrl, data, additionalHeaders);
return this._processResponse(res, this.requestOptions);
}
async patchJson(requestUrl, obj, additionalHeaders = {}) {
let data = JSON.stringify(obj, null, 2);
additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson);
additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson);
let res = await this.patch(requestUrl, data, additionalHeaders);
return this._processResponse(res, this.requestOptions);
}
/** /**
* Makes a raw http request. * Makes a raw http request.
* All other methods such as get, post, patch, and request ultimately call this. * All other methods such as get, post, patch, and request ultimately call this.
@ -130,18 +189,22 @@ class HttpClient {
*/ */
async request(verb, requestUrl, data, headers) { async request(verb, requestUrl, data, headers) {
if (this._disposed) { if (this._disposed) {
throw new Error("Client has already been disposed."); throw new Error('Client has already been disposed.');
} }
let parsedUrl = url.parse(requestUrl); let parsedUrl = url.parse(requestUrl);
let info = this._prepareRequest(verb, parsedUrl, headers); let info = this._prepareRequest(verb, parsedUrl, headers);
// Only perform retries on reads since writes may not be idempotent. // Only perform retries on reads since writes may not be idempotent.
let maxTries = (this._allowRetries && RetryableHttpVerbs.indexOf(verb) != -1) ? this._maxRetries + 1 : 1; let maxTries = this._allowRetries && RetryableHttpVerbs.indexOf(verb) != -1
? this._maxRetries + 1
: 1;
let numTries = 0; let numTries = 0;
let response; let response;
while (numTries < maxTries) { while (numTries < maxTries) {
response = await this.requestRaw(info, data); response = await this.requestRaw(info, data);
// Check if it's an authentication challenge // Check if it's an authentication challenge
if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) { if (response &&
response.message &&
response.message.statusCode === HttpCodes.Unauthorized) {
let authenticationHandler; let authenticationHandler;
for (let i = 0; i < this.handlers.length; i++) { for (let i = 0; i < this.handlers.length; i++) {
if (this.handlers[i].canHandleAuthentication(response)) { if (this.handlers[i].canHandleAuthentication(response)) {
@ -159,21 +222,32 @@ class HttpClient {
} }
} }
let redirectsRemaining = this._maxRedirects; let redirectsRemaining = this._maxRedirects;
while (HttpRedirectCodes.indexOf(response.message.statusCode) != -1 while (HttpRedirectCodes.indexOf(response.message.statusCode) != -1 &&
&& this._allowRedirects this._allowRedirects &&
&& redirectsRemaining > 0) { redirectsRemaining > 0) {
const redirectUrl = response.message.headers["location"]; const redirectUrl = response.message.headers['location'];
if (!redirectUrl) { if (!redirectUrl) {
// if there's no location to redirect to, we won't // if there's no location to redirect to, we won't
break; break;
} }
let parsedRedirectUrl = url.parse(redirectUrl); let parsedRedirectUrl = url.parse(redirectUrl);
if (parsedUrl.protocol == 'https:' && parsedUrl.protocol != parsedRedirectUrl.protocol && !this._allowRedirectDowngrade) { if (parsedUrl.protocol == 'https:' &&
throw new Error("Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true."); parsedUrl.protocol != parsedRedirectUrl.protocol &&
!this._allowRedirectDowngrade) {
throw new Error('Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.');
} }
// we need to finish reading the response before reassigning response // we need to finish reading the response before reassigning response
// which will leak the open socket. // which will leak the open socket.
await response.readBody(); await response.readBody();
// strip authorization header if redirected to a different hostname
if (parsedRedirectUrl.hostname !== parsedUrl.hostname) {
for (let header in headers) {
// header names are case insensitive
if (header.toLowerCase() === 'authorization') {
delete headers[header];
}
}
}
// let's make the request with the new redirectUrl // let's make the request with the new redirectUrl
info = this._prepareRequest(verb, parsedRedirectUrl, headers); info = this._prepareRequest(verb, parsedRedirectUrl, headers);
response = await this.requestRaw(info, data); response = await this.requestRaw(info, data);
@ -224,8 +298,8 @@ class HttpClient {
*/ */
requestRawWithCallback(info, data, onResult) { requestRawWithCallback(info, data, onResult) {
let socket; let socket;
if (typeof (data) === 'string') { if (typeof data === 'string') {
info.options.headers["Content-Length"] = Buffer.byteLength(data, 'utf8'); info.options.headers['Content-Length'] = Buffer.byteLength(data, 'utf8');
} }
let callbackCalled = false; let callbackCalled = false;
let handleResult = (err, res) => { let handleResult = (err, res) => {
@ -238,7 +312,7 @@ class HttpClient {
let res = new HttpClientResponse(msg); let res = new HttpClientResponse(msg);
handleResult(null, res); handleResult(null, res);
}); });
req.on('socket', (sock) => { req.on('socket', sock => {
socket = sock; socket = sock;
}); });
// If we ever get disconnected, we want the socket to timeout eventually // If we ever get disconnected, we want the socket to timeout eventually
@ -253,10 +327,10 @@ class HttpClient {
// res should have headers // res should have headers
handleResult(err, null); handleResult(err, null);
}); });
if (data && typeof (data) === 'string') { if (data && typeof data === 'string') {
req.write(data, 'utf8'); req.write(data, 'utf8');
} }
if (data && typeof (data) !== 'string') { if (data && typeof data !== 'string') {
data.on('close', function () { data.on('close', function () {
req.end(); req.end();
}); });
@ -283,29 +357,40 @@ class HttpClient {
const defaultPort = usingSsl ? 443 : 80; const defaultPort = usingSsl ? 443 : 80;
info.options = {}; info.options = {};
info.options.host = info.parsedUrl.hostname; info.options.host = info.parsedUrl.hostname;
info.options.port = info.parsedUrl.port ? parseInt(info.parsedUrl.port) : defaultPort; info.options.port = info.parsedUrl.port
info.options.path = (info.parsedUrl.pathname || '') + (info.parsedUrl.search || ''); ? parseInt(info.parsedUrl.port)
: defaultPort;
info.options.path =
(info.parsedUrl.pathname || '') + (info.parsedUrl.search || '');
info.options.method = method; info.options.method = method;
info.options.headers = this._mergeHeaders(headers); info.options.headers = this._mergeHeaders(headers);
if (this.userAgent != null) { if (this.userAgent != null) {
info.options.headers["user-agent"] = this.userAgent; info.options.headers['user-agent'] = this.userAgent;
} }
info.options.agent = this._getAgent(info.parsedUrl); info.options.agent = this._getAgent(info.parsedUrl);
// gives handlers an opportunity to participate // gives handlers an opportunity to participate
if (this.handlers) { if (this.handlers) {
this.handlers.forEach((handler) => { this.handlers.forEach(handler => {
handler.prepareRequest(info.options); handler.prepareRequest(info.options);
}); });
} }
return info; return info;
} }
_mergeHeaders(headers) { _mergeHeaders(headers) {
const lowercaseKeys = obj => Object.keys(obj).reduce((c, k) => (c[k.toLowerCase()] = obj[k], c), {}); const lowercaseKeys = obj => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {});
if (this.requestOptions && this.requestOptions.headers) { if (this.requestOptions && this.requestOptions.headers) {
return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers)); return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers));
} }
return lowercaseKeys(headers || {}); return lowercaseKeys(headers || {});
} }
_getExistingOrDefaultHeader(additionalHeaders, header, _default) {
const lowercaseKeys = obj => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {});
let clientHeader;
if (this.requestOptions && this.requestOptions.headers) {
clientHeader = lowercaseKeys(this.requestOptions.headers)[header];
}
return additionalHeaders[header] || clientHeader || _default;
}
_getAgent(parsedUrl) { _getAgent(parsedUrl) {
let agent; let agent;
let proxyUrl = pm.getProxyUrl(parsedUrl); let proxyUrl = pm.getProxyUrl(parsedUrl);
@ -337,7 +422,7 @@ class HttpClient {
proxyAuth: proxyUrl.auth, proxyAuth: proxyUrl.auth,
host: proxyUrl.hostname, host: proxyUrl.hostname,
port: proxyUrl.port port: proxyUrl.port
}, }
}; };
let tunnelAgent; let tunnelAgent;
const overHttps = proxyUrl.protocol === 'https:'; const overHttps = proxyUrl.protocol === 'https:';
@ -364,7 +449,9 @@ class HttpClient {
// we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process
// http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options
// we have to cast it to any and change it directly // we have to cast it to any and change it directly
agent.options = Object.assign(agent.options || {}, { rejectUnauthorized: false }); agent.options = Object.assign(agent.options || {}, {
rejectUnauthorized: false
});
} }
return agent; return agent;
} }
@ -373,5 +460,72 @@ class HttpClient {
const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber); const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber);
return new Promise(resolve => setTimeout(() => resolve(), ms)); return new Promise(resolve => setTimeout(() => resolve(), ms));
} }
static dateTimeDeserializer(key, value) {
if (typeof value === 'string') {
let a = new Date(value);
if (!isNaN(a.valueOf())) {
return a;
}
}
return value;
}
async _processResponse(res, options) {
return new Promise(async (resolve, reject) => {
const statusCode = res.message.statusCode;
const response = {
statusCode: statusCode,
result: null,
headers: {}
};
// not found leads to null obj returned
if (statusCode == HttpCodes.NotFound) {
resolve(response);
}
let obj;
let contents;
// get the result from the body
try {
contents = await res.readBody();
if (contents && contents.length > 0) {
if (options && options.deserializeDates) {
obj = JSON.parse(contents, HttpClient.dateTimeDeserializer);
}
else {
obj = JSON.parse(contents);
}
response.result = obj;
}
response.headers = res.message.headers;
}
catch (err) {
// Invalid resource (contents not json); leaving result obj null
}
// note that 3xx redirects are handled by the http layer.
if (statusCode > 299) {
let msg;
// if exception/error in body, attempt to get better error
if (obj && obj.message) {
msg = obj.message;
}
else if (contents && contents.length > 0) {
// it may be the case that the exception is in the body message as string
msg = contents;
}
else {
msg = 'Failed request: (' + statusCode + ')';
}
let err = new Error(msg);
// attach statusCode and body obj (if available) to the error object
err['statusCode'] = statusCode;
if (response.result) {
err['result'] = response.result;
}
reject(err);
}
else {
resolve(response);
}
});
}
} }
exports.HttpClient = HttpClient; exports.HttpClient = HttpClient;

View File

@ -1,6 +1,6 @@
/// <reference types="node" /> /// <reference types="node" />
import http = require("http"); import http = require('http');
import url = require("url"); import url = require('url');
export interface IHeaders { export interface IHeaders {
[key: string]: any; [key: string]: any;
} }
@ -39,6 +39,12 @@ export interface IRequestOptions {
maxRedirects?: number; maxRedirects?: number;
maxSockets?: number; maxSockets?: number;
keepAlive?: boolean; keepAlive?: boolean;
deserializeDates?: boolean;
allowRetries?: boolean; allowRetries?: boolean;
maxRetries?: number; maxRetries?: number;
} }
export interface ITypedResponse<T> {
statusCode: number;
result: T | null;
headers: Object;
}

View File

@ -1,3 +1,2 @@
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
;

View File

@ -1,33 +1,33 @@
{ {
"_args": [ "_args": [
[ [
"@actions/http-client@1.0.2", "@actions/http-client@1.0.8",
"C:\\users\\timheuer\\documents\\github\\setup-msbuild" "."
] ]
], ],
"_from": "@actions/http-client@1.0.2", "_from": "@actions/http-client@1.0.8",
"_id": "@actions/http-client@1.0.2", "_id": "@actions/http-client@1.0.8",
"_inBundle": false, "_inBundle": false,
"_integrity": "sha512-ngdGx7aXM7i9BFT+7e3RWWAEt3bX4tKrdI5w5hf0wYpHz66u5Nw6AFSFXG5wzQyUQbkgeNRnJZyK2zciGqXgrQ==", "_integrity": "sha512-G4JjJ6f9Hb3Zvejj+ewLLKLf99ZC+9v+yCxoYf9vSyH+WkzPLB2LuUtRMGNkooMqdugGBFStIKXOuvH1W+EctA==",
"_location": "/@actions/http-client", "_location": "/@actions/http-client",
"_phantomChildren": {}, "_phantomChildren": {},
"_requested": { "_requested": {
"type": "version", "type": "version",
"registry": true, "registry": true,
"raw": "@actions/http-client@1.0.2", "raw": "@actions/http-client@1.0.8",
"name": "@actions/http-client", "name": "@actions/http-client",
"escapedName": "@actions%2fhttp-client", "escapedName": "@actions%2fhttp-client",
"scope": "@actions", "scope": "@actions",
"rawSpec": "1.0.2", "rawSpec": "1.0.8",
"saveSpec": null, "saveSpec": null,
"fetchSpec": "1.0.2" "fetchSpec": "1.0.8"
}, },
"_requiredBy": [ "_requiredBy": [
"/@actions/tool-cache" "/@actions/tool-cache"
], ],
"_resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.2.tgz", "_resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.8.tgz",
"_spec": "1.0.2", "_spec": "1.0.8",
"_where": "C:\\users\\timheuer\\documents\\github\\setup-msbuild", "_where": ".",
"author": { "author": {
"name": "GitHub, Inc." "name": "GitHub, Inc."
}, },
@ -39,12 +39,13 @@
}, },
"description": "Actions Http Client", "description": "Actions Http Client",
"devDependencies": { "devDependencies": {
"@types/jest": "^24.0.25", "@types/jest": "^25.1.4",
"@types/node": "^12.12.24", "@types/node": "^12.12.31",
"jest": "^24.9.0", "jest": "^25.1.0",
"prettier": "^2.0.4",
"proxy": "^1.0.1", "proxy": "^1.0.1",
"ts-jest": "^24.3.0", "ts-jest": "^25.2.1",
"typescript": "^3.7.4" "typescript": "^3.8.3"
}, },
"homepage": "https://github.com/actions/http-client#readme", "homepage": "https://github.com/actions/http-client#readme",
"keywords": [ "keywords": [
@ -59,8 +60,11 @@
"url": "git+https://github.com/actions/http-client.git" "url": "git+https://github.com/actions/http-client.git"
}, },
"scripts": { "scripts": {
"audit-check": "npm audit --audit-level=moderate",
"build": "rm -Rf ./_out && tsc && cp package*.json ./_out && cp *.md ./_out && cp LICENSE ./_out && cp actions.png ./_out", "build": "rm -Rf ./_out && tsc && cp package*.json ./_out && cp *.md ./_out && cp LICENSE ./_out && cp actions.png ./_out",
"format": "prettier --write *.ts && prettier --write **/*.ts",
"format-check": "prettier --check *.ts && prettier --check **/*.ts",
"test": "jest" "test": "jest"
}, },
"version": "1.0.2" "version": "1.0.8"
} }

View File

@ -1,3 +1,4 @@
/// <reference types="node" /> /// <reference types="node" />
import * as url from 'url'; import * as url from 'url';
export declare function getProxyUrl(reqUrl: url.Url): url.Url; export declare function getProxyUrl(reqUrl: url.Url): url.Url | undefined;
export declare function checkBypass(reqUrl: url.Url): boolean;

View File

@ -3,33 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
const url = require("url"); const url = require("url");
function getProxyUrl(reqUrl) { function getProxyUrl(reqUrl) {
let usingSsl = reqUrl.protocol === 'https:'; let usingSsl = reqUrl.protocol === 'https:';
let noProxy = process.env["no_proxy"] ||
process.env["NO_PROXY"];
let bypass;
if (noProxy && typeof noProxy === 'string') {
let bypassList = noProxy.split(',');
for (let i = 0; i < bypassList.length; i++) {
let item = bypassList[i];
if (item &&
typeof item === "string" &&
reqUrl.host.toLocaleLowerCase() == item.trim().toLocaleLowerCase()) {
bypass = true;
break;
}
}
}
let proxyUrl; let proxyUrl;
if (bypass) { if (checkBypass(reqUrl)) {
return proxyUrl; return proxyUrl;
} }
let proxyVar; let proxyVar;
if (usingSsl) { if (usingSsl) {
proxyVar = process.env["https_proxy"] || proxyVar = process.env['https_proxy'] || process.env['HTTPS_PROXY'];
process.env["HTTPS_PROXY"];
} }
else { else {
proxyVar = process.env["http_proxy"] || proxyVar = process.env['http_proxy'] || process.env['HTTP_PROXY'];
process.env["HTTP_PROXY"];
} }
if (proxyVar) { if (proxyVar) {
proxyUrl = url.parse(proxyVar); proxyUrl = url.parse(proxyVar);
@ -37,3 +20,39 @@ function getProxyUrl(reqUrl) {
return proxyUrl; return proxyUrl;
} }
exports.getProxyUrl = getProxyUrl; exports.getProxyUrl = getProxyUrl;
function checkBypass(reqUrl) {
if (!reqUrl.hostname) {
return false;
}
let noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || '';
if (!noProxy) {
return false;
}
// Determine the request port
let reqPort;
if (reqUrl.port) {
reqPort = Number(reqUrl.port);
}
else if (reqUrl.protocol === 'http:') {
reqPort = 80;
}
else if (reqUrl.protocol === 'https:') {
reqPort = 443;
}
// Format the request hostname and hostname with port
let upperReqHosts = [reqUrl.hostname.toUpperCase()];
if (typeof reqPort === 'number') {
upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`);
}
// Compare request host against noproxy
for (let upperNoProxyItem of noProxy
.split(',')
.map(x => x.trim().toUpperCase())
.filter(x => x)) {
if (upperReqHosts.some(x => x === upperNoProxyItem)) {
return true;
}
}
return false;
}
exports.checkBypass = checkBypass;

View File

@ -2,7 +2,7 @@
"_args": [ "_args": [
[ [
"@actions/io@1.0.2", "@actions/io@1.0.2",
"C:\\users\\timheuer\\documents\\github\\setup-msbuild" "C:\\Users\\timheuer\\Documents\\GitHub\\setup-msbuild"
] ]
], ],
"_from": "@actions/io@1.0.2", "_from": "@actions/io@1.0.2",
@ -28,7 +28,7 @@
], ],
"_resolved": "https://registry.npmjs.org/@actions/io/-/io-1.0.2.tgz", "_resolved": "https://registry.npmjs.org/@actions/io/-/io-1.0.2.tgz",
"_spec": "1.0.2", "_spec": "1.0.2",
"_where": "C:\\users\\timheuer\\documents\\github\\setup-msbuild", "_where": "C:\\Users\\timheuer\\Documents\\GitHub\\setup-msbuild",
"bugs": { "bugs": {
"url": "https://github.com/actions/toolkit/issues" "url": "https://github.com/actions/toolkit/issues"
}, },

View File

@ -2,7 +2,7 @@
"_args": [ "_args": [
[ [
"@actions/tool-cache@1.3.0", "@actions/tool-cache@1.3.0",
"C:\\users\\timheuer\\documents\\github\\setup-msbuild" "C:\\Users\\timheuer\\Documents\\GitHub\\setup-msbuild"
] ]
], ],
"_from": "@actions/tool-cache@1.3.0", "_from": "@actions/tool-cache@1.3.0",
@ -27,7 +27,7 @@
], ],
"_resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-1.3.0.tgz", "_resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-1.3.0.tgz",
"_spec": "1.3.0", "_spec": "1.3.0",
"_where": "C:\\users\\timheuer\\documents\\github\\setup-msbuild", "_where": "C:\\Users\\timheuer\\Documents\\GitHub\\setup-msbuild",
"bugs": { "bugs": {
"url": "https://github.com/actions/toolkit/issues" "url": "https://github.com/actions/toolkit/issues"
}, },

6
node_modules/semver/package.json generated vendored
View File

@ -2,7 +2,7 @@
"_args": [ "_args": [
[ [
"semver@6.3.0", "semver@6.3.0",
"C:\\users\\timheuer\\documents\\github\\setup-msbuild" "C:\\Users\\timheuer\\Documents\\GitHub\\setup-msbuild"
] ]
], ],
"_from": "semver@6.3.0", "_from": "semver@6.3.0",
@ -29,9 +29,9 @@
], ],
"_resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "_resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"_spec": "6.3.0", "_spec": "6.3.0",
"_where": "C:\\users\\timheuer\\documents\\github\\setup-msbuild", "_where": "C:\\Users\\timheuer\\Documents\\GitHub\\setup-msbuild",
"bin": { "bin": {
"semver": "./bin/semver.js" "semver": "bin/semver.js"
}, },
"bugs": { "bugs": {
"url": "https://github.com/npm/node-semver/issues" "url": "https://github.com/npm/node-semver/issues"

4
node_modules/tunnel/package.json generated vendored
View File

@ -2,7 +2,7 @@
"_args": [ "_args": [
[ [
"tunnel@0.0.6", "tunnel@0.0.6",
"C:\\users\\timheuer\\documents\\github\\setup-msbuild" "C:\\Users\\timheuer\\Documents\\GitHub\\setup-msbuild"
] ]
], ],
"_from": "tunnel@0.0.6", "_from": "tunnel@0.0.6",
@ -26,7 +26,7 @@
], ],
"_resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", "_resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
"_spec": "0.0.6", "_spec": "0.0.6",
"_where": "C:\\users\\timheuer\\documents\\github\\setup-msbuild", "_where": "C:\\Users\\timheuer\\Documents\\GitHub\\setup-msbuild",
"author": { "author": {
"name": "Koichi Kobayashi", "name": "Koichi Kobayashi",
"email": "koichik@improvement.jp" "email": "koichik@improvement.jp"

6
node_modules/uuid/package.json generated vendored
View File

@ -2,7 +2,7 @@
"_args": [ "_args": [
[ [
"uuid@3.3.3", "uuid@3.3.3",
"C:\\users\\timheuer\\documents\\github\\setup-msbuild" "C:\\Users\\timheuer\\Documents\\GitHub\\setup-msbuild"
] ]
], ],
"_from": "uuid@3.3.3", "_from": "uuid@3.3.3",
@ -27,9 +27,9 @@
], ],
"_resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", "_resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
"_spec": "3.3.3", "_spec": "3.3.3",
"_where": "C:\\users\\timheuer\\documents\\github\\setup-msbuild", "_where": "C:\\Users\\timheuer\\Documents\\GitHub\\setup-msbuild",
"bin": { "bin": {
"uuid": "./bin/uuid" "uuid": "bin/uuid"
}, },
"browser": { "browser": {
"./lib/rng.js": "./lib/rng-browser.js", "./lib/rng.js": "./lib/rng-browser.js",

26
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "setup-msbuild", "name": "setup-msbuild",
"version": "1.0.0", "version": "1.0.1",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -18,9 +18,9 @@
} }
}, },
"@actions/http-client": { "@actions/http-client": {
"version": "1.0.2", "version": "1.0.8",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.2.tgz", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.8.tgz",
"integrity": "sha512-ngdGx7aXM7i9BFT+7e3RWWAEt3bX4tKrdI5w5hf0wYpHz66u5Nw6AFSFXG5wzQyUQbkgeNRnJZyK2zciGqXgrQ==", "integrity": "sha512-G4JjJ6f9Hb3Zvejj+ewLLKLf99ZC+9v+yCxoYf9vSyH+WkzPLB2LuUtRMGNkooMqdugGBFStIKXOuvH1W+EctA==",
"requires": { "requires": {
"tunnel": "0.0.6" "tunnel": "0.0.6"
} }
@ -662,9 +662,9 @@
"dev": true "dev": true
}, },
"acorn": { "acorn": {
"version": "6.4.0", "version": "6.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
"integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==", "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
"dev": true "dev": true
}, },
"acorn-globals": { "acorn-globals": {
@ -4226,9 +4226,9 @@
}, },
"dependencies": { "dependencies": {
"acorn": { "acorn": {
"version": "5.7.3", "version": "5.7.4",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz",
"integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==",
"dev": true "dev": true
} }
} }
@ -4365,9 +4365,9 @@
} }
}, },
"lodash": { "lodash": {
"version": "4.17.15", "version": "4.17.19",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
"dev": true "dev": true
}, },
"lodash.memoize": { "lodash.memoize": {

View File

@ -1,6 +1,6 @@
{ {
"name": "setup-msbuild", "name": "setup-msbuild",
"version": "1.0.0", "version": "1.0.1",
"private": true, "private": true,
"description": "Helps set up specific MSBuild tool into PATH for later usage.", "description": "Helps set up specific MSBuild tool into PATH for later usage.",
"main": "lib/main.js", "main": "lib/main.js",
@ -11,7 +11,7 @@
"lint": "eslint src/**/*.ts", "lint": "eslint src/**/*.ts",
"pack": "ncc build", "pack": "ncc build",
"test": "jest", "test": "jest",
"all": "npm run build && npm run format && npm run lint && npm run pack && npm test" "all": "npm run build && npm run format && npm run lint && npm run pack"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -1,27 +1,19 @@
import * as core from '@actions/core' import * as core from '@actions/core'
import * as exec from '@actions/exec' import * as exec from '@actions/exec'
import * as fs from 'fs'
import * as path from 'path' import * as path from 'path'
import * as io from '@actions/io' import * as io from '@actions/io'
import {ExecOptions} from '@actions/exec/lib/interfaces' import {ExecOptions} from '@actions/exec/lib/interfaces'
const IS_WINDOWS = process.platform === 'win32' const IS_WINDOWS = process.platform === 'win32'
const VS_VERSION = core.getInput('vs-version') || 'latest' const VS_VERSION = core.getInput('vs-version') || 'latest'
const VSWHERE_PATH = const VSWHERE_PATH = core.getInput('vswhere-path')
core.getInput('vswhere-path') ||
path.join(
process.env['ProgramFiles(x86)'] as string,
'Microsoft Visual Studio\\Installer'
)
// if a specific version of VS is requested // if a specific version of VS is requested
let VSWHERE_EXEC = '' let VSWHERE_EXEC = '-products * -requires Microsoft.Component.MSBuild -property installationPath -latest '
if (VS_VERSION === 'latest') { if (VS_VERSION !== 'latest') {
VSWHERE_EXEC += '-latest ' VSWHERE_EXEC += `-version "${VS_VERSION}" `
} else {
VSWHERE_EXEC += `-version ${VS_VERSION} `
} }
VSWHERE_EXEC +=
'-requires Microsoft.Component.MSBuild -find MSBuild\\**\\Bin\\MSBuild.exe'
core.debug(`Execution arguments: ${VSWHERE_EXEC}`) core.debug(`Execution arguments: ${VSWHERE_EXEC}`)
@ -38,20 +30,30 @@ async function run(): Promise<void> {
if (VSWHERE_PATH) { if (VSWHERE_PATH) {
// specified a path for vswhere, use it // specified a path for vswhere, use it
core.debug(`Using given vswhere-path: ${VSWHERE_PATH}`)
vswhereToolExe = path.join(VSWHERE_PATH, 'vswhere.exe') vswhereToolExe = path.join(VSWHERE_PATH, 'vswhere.exe')
} else { } else {
// check in PATH to see if it is there // check in PATH to see if it is there
try { try {
const vsWhereInPath: string = await io.which('vswhere', true) const vsWhereInPath: string = await io.which('vswhere', true)
core.debug(`Found tool in PATH: ${vsWhereInPath}`) core.debug(`Found tool in PATH: ${vsWhereInPath}`)
vswhereToolExe = path.join(vsWhereInPath, 'vswhere.exe') vswhereToolExe = vsWhereInPath
} catch { } catch {
// wasn't found because which threw // fall back to VS-installed path
} finally { vswhereToolExe = path.join(
process.env['ProgramFiles(x86)'] as string,
'Microsoft Visual Studio\\Installer\\vswhere.exe'
)
core.debug(`Trying Visual Studio-installed path: ${vswhereToolExe}`)
}
}
if (!fs.existsSync(vswhereToolExe)) {
core.setFailed( core.setFailed(
'setup-msbuild requires the path to where vswhere.exe exists' 'setup-msbuild requires the path to where vswhere.exe exists'
) )
}
return
} }
core.debug(`Full tool exe: ${vswhereToolExe}`) core.debug(`Full tool exe: ${vswhereToolExe}`)
@ -60,9 +62,28 @@ async function run(): Promise<void> {
const options: ExecOptions = {} const options: ExecOptions = {}
options.listeners = { options.listeners = {
stdout: (data: Buffer) => { stdout: (data: Buffer) => {
// eslint-disable-next-line prefer-const const installationPath = data.toString().trim()
let output = data.toString() core.debug(`Found installation path: ${installationPath}`)
foundToolPath += output
let toolPath = path.join(
installationPath,
'MSBuild\\Current\\Bin\\MSBuild.exe'
)
core.debug(`Checking for path: ${toolPath}`)
if (!fs.existsSync(toolPath)) {
toolPath = path.join(
installationPath,
'MSBuild\\15.0\\Bin\\MSBuild.exe'
)
core.debug(`Checking for path: ${toolPath}`)
if (!fs.existsSync(toolPath)) {
return
}
}
foundToolPath = toolPath
} }
} }
@ -70,7 +91,7 @@ async function run(): Promise<void> {
await exec.exec(`"${vswhereToolExe}" ${VSWHERE_EXEC}`, [], options) await exec.exec(`"${vswhereToolExe}" ${VSWHERE_EXEC}`, [], options)
if (!foundToolPath) { if (!foundToolPath) {
core.setFailed('Unable to find msbuild.') core.setFailed('Unable to find MSBuild.')
return return
} }