Skip to content

Commit d62baed

Browse files
author
Steve Winton
authored
Merge pull request #13 from swinton/locate-chrome
Locate chrome binary
2 parents 557bdca + 2567c41 commit d62baed

File tree

5 files changed

+162
-57
lines changed

5 files changed

+162
-57
lines changed

.github/workflows/screenshot.yml

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,62 @@ on:
44
push
55

66
jobs:
7-
screenshot:
8-
name: Screenshot
7+
screenshot-ubuntu:
8+
name: Screenshot (Ubuntu)
99
strategy:
1010
matrix:
11-
os: [ubuntu-latest, macos-latest, windows-latest]
11+
os: [ubuntu-latest]
1212
width: [1200, 992, 768, 600]
1313
runs-on: ${{ matrix.os }}
1414

1515
steps:
1616

1717
- name: Checkout
18-
uses: actions/checkout@v1.0.0
18+
uses: actions/checkout@v2
19+
20+
- name: Capture Screenshot
21+
id: screenshot
22+
uses: ./
23+
with:
24+
source: https://github.com/swinton/screenshot-website
25+
destination: github-com-swinton-screenshot-website-${{ matrix.os }}-${{ matrix.width }}.png
26+
full-page: true
27+
width: ${{ matrix.width }}
28+
29+
screenshot-macos:
30+
name: Screenshot (macOS)
31+
strategy:
32+
matrix:
33+
os: [macos-latest]
34+
width: [1200, 992, 768, 600]
35+
runs-on: ${{ matrix.os }}
36+
37+
steps:
38+
39+
- name: Checkout
40+
uses: actions/checkout@v2
41+
42+
- name: Capture Screenshot
43+
id: screenshot
44+
uses: ./
45+
with:
46+
source: https://github.com/swinton/screenshot-website
47+
destination: github-com-swinton-screenshot-website-${{ matrix.os }}-${{ matrix.width }}.png
48+
full-page: true
49+
width: ${{ matrix.width }}
50+
51+
screenshot-windows:
52+
name: Screenshot (Windows)
53+
strategy:
54+
matrix:
55+
os: [windows-latest]
56+
width: [1200, 992, 768, 600]
57+
runs-on: ${{ matrix.os }}
58+
59+
steps:
60+
61+
- name: Checkout
62+
uses: actions/checkout@v2
1963

2064
- name: Capture Screenshot
2165
id: screenshot

action.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ inputs:
1111
delay:
1212
description: 'The number of seconds to wait after the page finished loading before capturing the screenshot'
1313
required: false
14-
default: 0
14+
default: '0'
1515
full-page:
1616
description: 'Capture the full scrollable page, not just the viewport'
1717
required: false
18-
default: false
18+
default: 'false'
19+
width:
20+
description: 'Page width'
21+
required: false
1922
outputs:
2023
path:
2124
description: 'The filesystem path to the website screenshot'

dist/index.js

Lines changed: 92 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5124,6 +5124,7 @@ const captureWebsite = __webpack_require__(89);
51245124
const core = __webpack_require__(470);
51255125
const artifact = __webpack_require__(330);
51265126
const loadInputs = __webpack_require__(480);
5127+
const whichChrome = __webpack_require__(742);
51275128

51285129
async function run() {
51295130
try {
@@ -5138,15 +5139,7 @@ async function run() {
51385139
const dest = path.join(destFolder, destFile);
51395140

51405141
// Locate Google Chrome executable
5141-
// "google-chrome" on Linux
5142-
// "chrome.exe" on Windows
5143-
// "Google Chrome" on macOSs
5144-
const executables = {
5145-
Linux: '/usr/bin/google-chrome',
5146-
Windows: 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
5147-
macOS: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
5148-
};
5149-
const executablePath = executables[process.env.RUNNER_OS];
5142+
const executablePath = await whichChrome();
51505143
core.debug(`executablePath is ${executablePath}`);
51515144

51525145
// Options for capture
@@ -14495,7 +14488,9 @@ class BasicCredentialHandler {
1449514488
this.password = password;
1449614489
}
1449714490
prepareRequest(options) {
14498-
options.headers['Authorization'] = 'Basic ' + Buffer.from(this.username + ':' + this.password).toString('base64');
14491+
options.headers['Authorization'] =
14492+
'Basic ' +
14493+
Buffer.from(this.username + ':' + this.password).toString('base64');
1449914494
}
1450014495
// This handler cannot handle 401
1450114496
canHandleAuthentication(response) {
@@ -14531,7 +14526,8 @@ class PersonalAccessTokenCredentialHandler {
1453114526
// currently implements pre-authorization
1453214527
// TODO: support preAuth = false where it hooks on 401
1453314528
prepareRequest(options) {
14534-
options.headers['Authorization'] = 'Basic ' + Buffer.from('PAT:' + this.token).toString('base64');
14529+
options.headers['Authorization'] =
14530+
'Basic ' + Buffer.from('PAT:' + this.token).toString('base64');
1453514531
}
1453614532
// This handler cannot handle 401
1453714533
canHandleAuthentication(response) {
@@ -22021,6 +22017,7 @@ var HttpCodes;
2202122017
HttpCodes[HttpCodes["RequestTimeout"] = 408] = "RequestTimeout";
2202222018
HttpCodes[HttpCodes["Conflict"] = 409] = "Conflict";
2202322019
HttpCodes[HttpCodes["Gone"] = 410] = "Gone";
22020+
HttpCodes[HttpCodes["TooManyRequests"] = 429] = "TooManyRequests";
2202422021
HttpCodes[HttpCodes["InternalServerError"] = 500] = "InternalServerError";
2202522022
HttpCodes[HttpCodes["NotImplemented"] = 501] = "NotImplemented";
2202622023
HttpCodes[HttpCodes["BadGateway"] = 502] = "BadGateway";
@@ -22045,8 +22042,18 @@ function getProxyUrl(serverUrl) {
2204522042
return proxyUrl ? proxyUrl.href : '';
2204622043
}
2204722044
exports.getProxyUrl = getProxyUrl;
22048-
const HttpRedirectCodes = [HttpCodes.MovedPermanently, HttpCodes.ResourceMoved, HttpCodes.SeeOther, HttpCodes.TemporaryRedirect, HttpCodes.PermanentRedirect];
22049-
const HttpResponseRetryCodes = [HttpCodes.BadGateway, HttpCodes.ServiceUnavailable, HttpCodes.GatewayTimeout];
22045+
const HttpRedirectCodes = [
22046+
HttpCodes.MovedPermanently,
22047+
HttpCodes.ResourceMoved,
22048+
HttpCodes.SeeOther,
22049+
HttpCodes.TemporaryRedirect,
22050+
HttpCodes.PermanentRedirect
22051+
];
22052+
const HttpResponseRetryCodes = [
22053+
HttpCodes.BadGateway,
22054+
HttpCodes.ServiceUnavailable,
22055+
HttpCodes.GatewayTimeout
22056+
];
2205022057
const RetryableHttpVerbs = ['OPTIONS', 'GET', 'DELETE', 'HEAD'];
2205122058
const ExponentialBackoffCeiling = 10;
2205222059
const ExponentialBackoffTimeSlice = 5;
@@ -22171,18 +22178,22 @@ class HttpClient {
2217122178
*/
2217222179
async request(verb, requestUrl, data, headers) {
2217322180
if (this._disposed) {
22174-
throw new Error("Client has already been disposed.");
22181+
throw new Error('Client has already been disposed.');
2217522182
}
2217622183
let parsedUrl = url.parse(requestUrl);
2217722184
let info = this._prepareRequest(verb, parsedUrl, headers);
2217822185
// Only perform retries on reads since writes may not be idempotent.
22179-
let maxTries = (this._allowRetries && RetryableHttpVerbs.indexOf(verb) != -1) ? this._maxRetries + 1 : 1;
22186+
let maxTries = this._allowRetries && RetryableHttpVerbs.indexOf(verb) != -1
22187+
? this._maxRetries + 1
22188+
: 1;
2218022189
let numTries = 0;
2218122190
let response;
2218222191
while (numTries < maxTries) {
2218322192
response = await this.requestRaw(info, data);
2218422193
// Check if it's an authentication challenge
22185-
if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) {
22194+
if (response &&
22195+
response.message &&
22196+
response.message.statusCode === HttpCodes.Unauthorized) {
2218622197
let authenticationHandler;
2218722198
for (let i = 0; i < this.handlers.length; i++) {
2218822199
if (this.handlers[i].canHandleAuthentication(response)) {
@@ -22200,21 +22211,32 @@ class HttpClient {
2220022211
}
2220122212
}
2220222213
let redirectsRemaining = this._maxRedirects;
22203-
while (HttpRedirectCodes.indexOf(response.message.statusCode) != -1
22204-
&& this._allowRedirects
22205-
&& redirectsRemaining > 0) {
22206-
const redirectUrl = response.message.headers["location"];
22214+
while (HttpRedirectCodes.indexOf(response.message.statusCode) != -1 &&
22215+
this._allowRedirects &&
22216+
redirectsRemaining > 0) {
22217+
const redirectUrl = response.message.headers['location'];
2220722218
if (!redirectUrl) {
2220822219
// if there's no location to redirect to, we won't
2220922220
break;
2221022221
}
2221122222
let parsedRedirectUrl = url.parse(redirectUrl);
22212-
if (parsedUrl.protocol == 'https:' && parsedUrl.protocol != parsedRedirectUrl.protocol && !this._allowRedirectDowngrade) {
22213-
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.");
22223+
if (parsedUrl.protocol == 'https:' &&
22224+
parsedUrl.protocol != parsedRedirectUrl.protocol &&
22225+
!this._allowRedirectDowngrade) {
22226+
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.');
2221422227
}
2221522228
// we need to finish reading the response before reassigning response
2221622229
// which will leak the open socket.
2221722230
await response.readBody();
22231+
// strip authorization header if redirected to a different hostname
22232+
if (parsedRedirectUrl.hostname !== parsedUrl.hostname) {
22233+
for (let header in headers) {
22234+
// header names are case insensitive
22235+
if (header.toLowerCase() === 'authorization') {
22236+
delete headers[header];
22237+
}
22238+
}
22239+
}
2221822240
// let's make the request with the new redirectUrl
2221922241
info = this._prepareRequest(verb, parsedRedirectUrl, headers);
2222022242
response = await this.requestRaw(info, data);
@@ -22265,8 +22287,8 @@ class HttpClient {
2226522287
*/
2226622288
requestRawWithCallback(info, data, onResult) {
2226722289
let socket;
22268-
if (typeof (data) === 'string') {
22269-
info.options.headers["Content-Length"] = Buffer.byteLength(data, 'utf8');
22290+
if (typeof data === 'string') {
22291+
info.options.headers['Content-Length'] = Buffer.byteLength(data, 'utf8');
2227022292
}
2227122293
let callbackCalled = false;
2227222294
let handleResult = (err, res) => {
@@ -22279,7 +22301,7 @@ class HttpClient {
2227922301
let res = new HttpClientResponse(msg);
2228022302
handleResult(null, res);
2228122303
});
22282-
req.on('socket', (sock) => {
22304+
req.on('socket', sock => {
2228322305
socket = sock;
2228422306
});
2228522307
// If we ever get disconnected, we want the socket to timeout eventually
@@ -22294,10 +22316,10 @@ class HttpClient {
2229422316
// res should have headers
2229522317
handleResult(err, null);
2229622318
});
22297-
if (data && typeof (data) === 'string') {
22319+
if (data && typeof data === 'string') {
2229822320
req.write(data, 'utf8');
2229922321
}
22300-
if (data && typeof (data) !== 'string') {
22322+
if (data && typeof data !== 'string') {
2230122323
data.on('close', function () {
2230222324
req.end();
2230322325
});
@@ -22324,31 +22346,34 @@ class HttpClient {
2232422346
const defaultPort = usingSsl ? 443 : 80;
2232522347
info.options = {};
2232622348
info.options.host = info.parsedUrl.hostname;
22327-
info.options.port = info.parsedUrl.port ? parseInt(info.parsedUrl.port) : defaultPort;
22328-
info.options.path = (info.parsedUrl.pathname || '') + (info.parsedUrl.search || '');
22349+
info.options.port = info.parsedUrl.port
22350+
? parseInt(info.parsedUrl.port)
22351+
: defaultPort;
22352+
info.options.path =
22353+
(info.parsedUrl.pathname || '') + (info.parsedUrl.search || '');
2232922354
info.options.method = method;
2233022355
info.options.headers = this._mergeHeaders(headers);
2233122356
if (this.userAgent != null) {
22332-
info.options.headers["user-agent"] = this.userAgent;
22357+
info.options.headers['user-agent'] = this.userAgent;
2233322358
}
2233422359
info.options.agent = this._getAgent(info.parsedUrl);
2233522360
// gives handlers an opportunity to participate
2233622361
if (this.handlers) {
22337-
this.handlers.forEach((handler) => {
22362+
this.handlers.forEach(handler => {
2233822363
handler.prepareRequest(info.options);
2233922364
});
2234022365
}
2234122366
return info;
2234222367
}
2234322368
_mergeHeaders(headers) {
22344-
const lowercaseKeys = obj => Object.keys(obj).reduce((c, k) => (c[k.toLowerCase()] = obj[k], c), {});
22369+
const lowercaseKeys = obj => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {});
2234522370
if (this.requestOptions && this.requestOptions.headers) {
2234622371
return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers));
2234722372
}
2234822373
return lowercaseKeys(headers || {});
2234922374
}
2235022375
_getExistingOrDefaultHeader(additionalHeaders, header, _default) {
22351-
const lowercaseKeys = obj => Object.keys(obj).reduce((c, k) => (c[k.toLowerCase()] = obj[k], c), {});
22376+
const lowercaseKeys = obj => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {});
2235222377
let clientHeader;
2235322378
if (this.requestOptions && this.requestOptions.headers) {
2235422379
clientHeader = lowercaseKeys(this.requestOptions.headers)[header];
@@ -22386,7 +22411,7 @@ class HttpClient {
2238622411
proxyAuth: proxyUrl.auth,
2238722412
host: proxyUrl.hostname,
2238822413
port: proxyUrl.port
22389-
},
22414+
}
2239022415
};
2239122416
let tunnelAgent;
2239222417
const overHttps = proxyUrl.protocol === 'https:';
@@ -22413,7 +22438,9 @@ class HttpClient {
2241322438
// we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process
2241422439
// http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options
2241522440
// we have to cast it to any and change it directly
22416-
agent.options = Object.assign(agent.options || {}, { rejectUnauthorized: false });
22441+
agent.options = Object.assign(agent.options || {}, {
22442+
rejectUnauthorized: false
22443+
});
2241722444
}
2241822445
return agent;
2241922446
}
@@ -22474,7 +22501,7 @@ class HttpClient {
2247422501
msg = contents;
2247522502
}
2247622503
else {
22477-
msg = "Failed request: (" + statusCode + ")";
22504+
msg = 'Failed request: (' + statusCode + ')';
2247822505
}
2247922506
let err = new Error(msg);
2248022507
// attach statusCode and body obj (if available) to the error object
@@ -28394,6 +28421,28 @@ module.exports.isNegativeZero = isNegativeZero;
2839428421
module.exports.extend = extend;
2839528422

2839628423

28424+
/***/ }),
28425+
28426+
/***/ 742:
28427+
/***/ (function(module) {
28428+
28429+
async function whichChrome() {
28430+
// Locate Google Chrome executable
28431+
// "google-chrome" on Linux
28432+
// "chrome.exe" on Windows
28433+
// "Google Chrome" on macOSs
28434+
const executables = {
28435+
Linux: '/usr/bin/google-chrome',
28436+
Windows: 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
28437+
macOS: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
28438+
};
28439+
28440+
return executables[process.env.RUNNER_OS];
28441+
}
28442+
28443+
module.exports = whichChrome;
28444+
28445+
2839728446
/***/ }),
2839828447

2839928448
/***/ 747:
@@ -33445,12 +33494,10 @@ function getProxyUrl(reqUrl) {
3344533494
}
3344633495
let proxyVar;
3344733496
if (usingSsl) {
33448-
proxyVar = process.env["https_proxy"] ||
33449-
process.env["HTTPS_PROXY"];
33497+
proxyVar = process.env['https_proxy'] || process.env['HTTPS_PROXY'];
3345033498
}
3345133499
else {
33452-
proxyVar = process.env["http_proxy"] ||
33453-
process.env["HTTP_PROXY"];
33500+
proxyVar = process.env['http_proxy'] || process.env['HTTP_PROXY'];
3345433501
}
3345533502
if (proxyVar) {
3345633503
proxyUrl = url.parse(proxyVar);
@@ -33462,7 +33509,7 @@ function checkBypass(reqUrl) {
3346233509
if (!reqUrl.hostname) {
3346333510
return false;
3346433511
}
33465-
let noProxy = process.env["no_proxy"] || process.env["NO_PROXY"] || '';
33512+
let noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || '';
3346633513
if (!noProxy) {
3346733514
return false;
3346833515
}
@@ -33483,7 +33530,10 @@ function checkBypass(reqUrl) {
3348333530
upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`);
3348433531
}
3348533532
// Compare request host against noproxy
33486-
for (let upperNoProxyItem of noProxy.split(',').map(x => x.trim().toUpperCase()).filter(x => x)) {
33533+
for (let upperNoProxyItem of noProxy
33534+
.split(',')
33535+
.map(x => x.trim().toUpperCase())
33536+
.filter(x => x)) {
3348733537
if (upperReqHosts.some(x => x === upperNoProxyItem)) {
3348833538
return true;
3348933539
}

0 commit comments

Comments
 (0)