Skip to content

Commit c8340ca

Browse files
authored
Merge pull request #1 from rchougule/binary_check
Cache binary and multiple artifacts
2 parents 3a1b742 + 80d1894 commit c8340ca

File tree

6 files changed

+175
-14
lines changed

6 files changed

+175
-14
lines changed

setup-local/config/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ module.exports = {
1515
ENV_VARS: {
1616
BROWSERSTACK_ACCESS_KEY: 'BROWSERSTACK_ACCESS_KEY',
1717
BROWSERSTACK_LOCAL_IDENTIFIER: 'BROWSERSTACK_LOCAL_IDENTIFIER',
18+
BROWSERSTACK_LOCAL_LOGS_FILE: 'BROWSERSTACK_LOCAL_LOGS_FILE',
1819
},
1920

2021
BINARY_LINKS: {

setup-local/dist/index.js

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,7 @@ const github = __webpack_require__(469);
10711071
const os = __webpack_require__(87);
10721072
const path = __webpack_require__(622);
10731073
const fs = __webpack_require__(747);
1074+
const Utils = __webpack_require__(353);
10741075
const ArtifactsManager = __webpack_require__(513);
10751076
const constants = __webpack_require__(613);
10761077

@@ -1084,6 +1085,9 @@ const {
10841085
ALLOWED_INPUT_VALUES: {
10851086
LOCAL_TESTING,
10861087
},
1088+
ENV_VARS: {
1089+
BROWSERSTACK_LOCAL_LOGS_FILE,
1090+
},
10871091
} = constants;
10881092

10891093
/**
@@ -1126,8 +1130,9 @@ class BinaryControl {
11261130
* Generates logging file name and its path for Local Binary
11271131
*/
11281132
_generateLogFileMetadata() {
1129-
this.logFileName = `${LOCAL_LOG_FILE_PREFIX}_${github.context.job}.log`;
1133+
this.logFileName = process.env[BROWSERSTACK_LOCAL_LOGS_FILE] || `${LOCAL_LOG_FILE_PREFIX}_${github.context.job}_${Date.now()}.log`;
11301134
this.logFilePath = path.resolve(this.binaryFolder, this.logFileName);
1135+
core.exportVariable(BROWSERSTACK_LOCAL_LOGS_FILE, this.logFileName);
11311136
}
11321137

11331138
/**
@@ -1201,6 +1206,10 @@ class BinaryControl {
12011206
*/
12021207
async downloadBinary() {
12031208
try {
1209+
if (Utils.checkToolInCache(LOCAL_BINARY_NAME)) {
1210+
core.info('BrowserStackLocal binary already exists in cache. Using that instead of downloading again...');
1211+
return;
1212+
}
12041213
await this._makeDirectory();
12051214
core.info('Downloading BrowserStackLocal binary...');
12061215
const downloadPath = await tc.downloadTool(this.binaryLink, path.resolve(this.binaryFolder, 'binaryZip'));
@@ -1281,6 +1290,7 @@ class BinaryControl {
12811290
);
12821291
await io.rmRF(this.logFilePath);
12831292
}
1293+
Utils.clearEnvironmentVariable(BROWSERSTACK_LOCAL_LOGS_FILE);
12841294
}
12851295
}
12861296

@@ -7166,6 +7176,29 @@ exports.default = void 0;
71667176
var _default = '00000000-0000-0000-0000-000000000000';
71677177
exports.default = _default;
71687178

7179+
/***/ }),
7180+
7181+
/***/ 353:
7182+
/***/ (function(module, __unusedexports, __webpack_require__) {
7183+
7184+
const core = __webpack_require__(470);
7185+
const tc = __webpack_require__(533);
7186+
7187+
class Utils {
7188+
static clearEnvironmentVariable(environmentVariable) {
7189+
core.exportVariable(environmentVariable, '');
7190+
delete process.env[environmentVariable];
7191+
}
7192+
7193+
static checkToolInCache(toolName) {
7194+
const toolCache = tc.findAllVersions(toolName);
7195+
return toolCache.length !== 0;
7196+
}
7197+
}
7198+
7199+
module.exports = Utils;
7200+
7201+
71697202
/***/ }),
71707203

71717204
/***/ 357:
@@ -13371,6 +13404,7 @@ module.exports = {
1337113404
ENV_VARS: {
1337213405
BROWSERSTACK_ACCESS_KEY: 'BROWSERSTACK_ACCESS_KEY',
1337313406
BROWSERSTACK_LOCAL_IDENTIFIER: 'BROWSERSTACK_LOCAL_IDENTIFIER',
13407+
BROWSERSTACK_LOCAL_LOGS_FILE: 'BROWSERSTACK_LOCAL_LOGS_FILE',
1337413408
},
1337513409

1337613410
BINARY_LINKS: {

setup-local/src/binaryControl.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const github = require('@actions/github');
66
const os = require('os');
77
const path = require('path');
88
const fs = require('fs');
9+
const Utils = require('./utils');
910
const ArtifactsManager = require('./artifacts');
1011
const constants = require('../config/constants');
1112

@@ -19,6 +20,9 @@ const {
1920
ALLOWED_INPUT_VALUES: {
2021
LOCAL_TESTING,
2122
},
23+
ENV_VARS: {
24+
BROWSERSTACK_LOCAL_LOGS_FILE,
25+
},
2226
} = constants;
2327

2428
/**
@@ -61,8 +65,9 @@ class BinaryControl {
6165
* Generates logging file name and its path for Local Binary
6266
*/
6367
_generateLogFileMetadata() {
64-
this.logFileName = `${LOCAL_LOG_FILE_PREFIX}_${github.context.job}.log`;
68+
this.logFileName = process.env[BROWSERSTACK_LOCAL_LOGS_FILE] || `${LOCAL_LOG_FILE_PREFIX}_${github.context.job}_${Date.now()}.log`;
6569
this.logFilePath = path.resolve(this.binaryFolder, this.logFileName);
70+
core.exportVariable(BROWSERSTACK_LOCAL_LOGS_FILE, this.logFileName);
6671
}
6772

6873
/**
@@ -136,6 +141,10 @@ class BinaryControl {
136141
*/
137142
async downloadBinary() {
138143
try {
144+
if (Utils.checkToolInCache(LOCAL_BINARY_NAME)) {
145+
core.info('BrowserStackLocal binary already exists in cache. Using that instead of downloading again...');
146+
return;
147+
}
139148
await this._makeDirectory();
140149
core.info('Downloading BrowserStackLocal binary...');
141150
const downloadPath = await tc.downloadTool(this.binaryLink, path.resolve(this.binaryFolder, 'binaryZip'));
@@ -216,6 +225,7 @@ class BinaryControl {
216225
);
217226
await io.rmRF(this.logFilePath);
218227
}
228+
Utils.clearEnvironmentVariable(BROWSERSTACK_LOCAL_LOGS_FILE);
219229
}
220230
}
221231

setup-local/src/utils/index.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
const core = require('@actions/core');
2+
const tc = require('@actions/tool-cache');
3+
4+
class Utils {
5+
static clearEnvironmentVariable(environmentVariable) {
6+
core.exportVariable(environmentVariable, '');
7+
delete process.env[environmentVariable];
8+
}
9+
10+
static checkToolInCache(toolName) {
11+
const toolCache = tc.findAllVersions(toolName);
12+
return toolCache.length !== 0;
13+
}
14+
}
15+
16+
module.exports = Utils;

setup-local/test/binaryControl.test.js

Lines changed: 78 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const fs = require('fs');
1111
const BinaryControl = require('../src/binaryControl');
1212
const ArtifactsManager = require('../src/artifacts');
1313
const constants = require('../config/constants');
14+
const Utils = require('../src/utils');
1415

1516
const {
1617
BINARY_LINKS,
@@ -22,6 +23,9 @@ const {
2223
ALLOWED_INPUT_VALUES: {
2324
LOCAL_TESTING,
2425
},
26+
ENV_VARS: {
27+
BROWSERSTACK_LOCAL_LOGS_FILE,
28+
},
2529
} = constants;
2630

2731
describe('Binary Control Operations', () => {
@@ -84,18 +88,51 @@ describe('Binary Control Operations', () => {
8488
os.platform.restore();
8589
});
8690

87-
it('Generates log-file name and path for Binary', () => {
88-
sinon.stub(os, 'platform').returns('darwin');
89-
sinon.stub(github, 'context').value({
90-
job: 'someJobName',
91+
context('Log File metadata', () => {
92+
beforeEach(() => {
93+
sinon.stub(core, 'exportVariable');
94+
sinon.stub(os, 'platform').returns('darwin');
95+
sinon.stub(github, 'context').value({
96+
job: 'someJobName',
97+
});
98+
});
99+
100+
afterEach(() => {
101+
delete process.env[BROWSERSTACK_LOCAL_LOGS_FILE];
102+
core.exportVariable.restore();
103+
os.platform.restore();
104+
});
105+
106+
it('Generates log-file name and path for Binary', () => {
107+
sinon.stub(Date, 'now').returns('now');
108+
const expectedLogFileName = `${LOCAL_LOG_FILE_PREFIX}_${github.context.job}_now.log`;
109+
const expectedLogFilePath = path.resolve(path.resolve(process.env.HOME, 'work', 'binary', LOCAL_BINARY_FOLDER, 'darwin'), expectedLogFileName);
110+
const binaryControl = new BinaryControl();
111+
binaryControl._generateLogFileMetadata();
112+
expect(binaryControl.logFileName).to.eq(expectedLogFileName);
113+
expect(binaryControl.logFilePath).to.eq(expectedLogFilePath);
114+
sinon.assert.calledWith(
115+
core.exportVariable,
116+
BROWSERSTACK_LOCAL_LOGS_FILE,
117+
expectedLogFileName,
118+
);
119+
Date.now.restore();
120+
});
121+
122+
it('Fetches log-file name and generates path for Binary if logs file name was already defined', () => {
123+
process.env[BROWSERSTACK_LOCAL_LOGS_FILE] = `${LOCAL_LOG_FILE_PREFIX}_${github.context.job}_now.log`;
124+
const expectedLogFileName = `${LOCAL_LOG_FILE_PREFIX}_${github.context.job}_now.log`;
125+
const expectedLogFilePath = path.resolve(path.resolve(process.env.HOME, 'work', 'binary', LOCAL_BINARY_FOLDER, 'darwin'), expectedLogFileName);
126+
const binaryControl = new BinaryControl();
127+
binaryControl._generateLogFileMetadata();
128+
expect(binaryControl.logFileName).to.eq(expectedLogFileName);
129+
expect(binaryControl.logFilePath).to.eq(expectedLogFilePath);
130+
sinon.assert.calledWith(
131+
core.exportVariable,
132+
BROWSERSTACK_LOCAL_LOGS_FILE,
133+
expectedLogFileName,
134+
);
91135
});
92-
const expectedLogFileName = `${LOCAL_LOG_FILE_PREFIX}_${github.context.job}.log`;
93-
const expectedLogFilePath = path.resolve(path.resolve(process.env.HOME, 'work', 'binary', LOCAL_BINARY_FOLDER, 'darwin'), expectedLogFileName);
94-
const binaryControl = new BinaryControl();
95-
binaryControl._generateLogFileMetadata();
96-
expect(binaryControl.logFileName).to.eq(expectedLogFileName);
97-
expect(binaryControl.logFilePath).to.eq(expectedLogFilePath);
98-
os.platform.restore();
99136
});
100137

101138
context('Generates args string based on the input to Binary Control & the operation required, i.e. start/stop', () => {
@@ -104,10 +141,14 @@ describe('Binary Control Operations', () => {
104141
sinon.stub(github, 'context').value({
105142
job: 'someJobName',
106143
});
144+
sinon.stub(Date, 'now').returns('now');
145+
sinon.stub(core, 'exportVariable');
107146
});
108147

109148
afterEach(() => {
110149
os.platform.restore();
150+
Date.now.restore();
151+
core.exportVariable.restore();
111152
});
112153

113154
context('Start Operation', () => {
@@ -120,7 +161,7 @@ describe('Binary Control Operations', () => {
120161
localTesting: 'start',
121162
};
122163

123-
const expectedFinalArgs = `--key someKey --only-automate --ci-plugin GitHubAction --arg1 val1 --arg2 val2 --local-identifier someIdentifier --verbose 1 --log-file ${path.resolve(process.env.HOME, 'work', 'binary', 'LocalBinaryFolder', 'darwin', 'BrowserStackLocal_someJobName.log')} `;
164+
const expectedFinalArgs = `--key someKey --only-automate --ci-plugin GitHubAction --arg1 val1 --arg2 val2 --local-identifier someIdentifier --verbose 1 --log-file ${path.resolve(process.env.HOME, 'work', 'binary', 'LocalBinaryFolder', 'darwin', 'BrowserStackLocal_someJobName_now.log')} `;
124165
const binaryControl = new BinaryControl(stateForBinary);
125166
binaryControl._generateArgsForBinary();
126167
expect(binaryControl.binaryArgs).to.eq(expectedFinalArgs);
@@ -274,6 +315,7 @@ describe('Binary Control Operations', () => {
274315
});
275316

276317
it('Downloads and sets the binary path without any error', async () => {
318+
sinon.stub(Utils, 'checkToolInCache').returns(false);
277319
sinon.stub(tc, 'downloadTool').returns('downloadPath');
278320
sinon.stub(tc, 'extractZip').returns('extractedPath');
279321
sinon.stub(tc, 'cacheDir').returns('cachedPath');
@@ -282,16 +324,36 @@ describe('Binary Control Operations', () => {
282324
tc.downloadTool.restore();
283325
tc.extractZip.restore();
284326
tc.cacheDir.restore();
327+
Utils.checkToolInCache.restore();
328+
});
329+
330+
it('Uses cached binary if it already exists (was already downloaded)', async () => {
331+
sinon.stub(Utils, 'checkToolInCache').returns(true);
332+
sinon.stub(tc, 'downloadTool').returns('downloadPath');
333+
sinon.stub(tc, 'extractZip').returns('extractedPath');
334+
sinon.stub(tc, 'cacheDir').returns('cachedPath');
335+
await binaryControl.downloadBinary();
336+
sinon.assert.calledWith(core.info, 'BrowserStackLocal binary already exists in cache. Using that instead of downloading again...');
337+
sinon.assert.notCalled(tc.downloadTool);
338+
sinon.assert.notCalled(tc.extractZip);
339+
sinon.assert.notCalled(tc.cacheDir);
340+
sinon.assert.notCalled(binaryControl._makeDirectory);
341+
tc.downloadTool.restore();
342+
tc.extractZip.restore();
343+
tc.cacheDir.restore();
344+
Utils.checkToolInCache.restore();
285345
});
286346

287347
it('Throws error if download of Binary fails', async () => {
348+
sinon.stub(Utils, 'checkToolInCache').returns(false);
288349
sinon.stub(tc, 'downloadTool').throws(Error('someError'));
289350
try {
290351
await binaryControl.downloadBinary();
291352
} catch (e) {
292353
expect(e.message).to.eq('BrowserStackLocal binary could not be downloaded due to someError');
293354
}
294355
tc.downloadTool.restore();
356+
Utils.checkToolInCache.restore();
295357
});
296358
});
297359

@@ -467,6 +529,7 @@ describe('Binary Control Operations', () => {
467529
sinon.stub(binaryControl, '_generateLogFileMetadata');
468530
sinon.stub(io, 'rmRF');
469531
sinon.stub(ArtifactsManager, 'uploadArtifacts').returns(true);
532+
sinon.stub(Utils, 'clearEnvironmentVariable');
470533
binaryControl.logFilePath = 'somePath';
471534
binaryControl.logFileName = 'someName';
472535
binaryControl.binaryFolder = 'someFolderPath';
@@ -475,6 +538,7 @@ describe('Binary Control Operations', () => {
475538
afterEach(() => {
476539
io.rmRF.restore();
477540
ArtifactsManager.uploadArtifacts.restore();
541+
Utils.clearEnvironmentVariable.restore();
478542
});
479543

480544
it('Uploads the log files if they exists', async () => {
@@ -487,6 +551,7 @@ describe('Binary Control Operations', () => {
487551
'someFolderPath',
488552
);
489553
sinon.assert.calledWith(io.rmRF, 'somePath');
554+
sinon.assert.calledWith(Utils.clearEnvironmentVariable, BROWSERSTACK_LOCAL_LOGS_FILE);
490555
fs.existsSync.restore();
491556
});
492557

@@ -495,6 +560,7 @@ describe('Binary Control Operations', () => {
495560
await binaryControl.uploadLogFilesIfAny();
496561
sinon.assert.notCalled(ArtifactsManager.uploadArtifacts);
497562
sinon.assert.notCalled(io.rmRF);
563+
sinon.assert.calledWith(Utils.clearEnvironmentVariable, BROWSERSTACK_LOCAL_LOGS_FILE);
498564
fs.existsSync.restore();
499565
});
500566
});
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
const { expect } = require("chai");
2+
const sinon = require("sinon");
3+
const core = require('@actions/core');
4+
const tc = require('@actions/tool-cache');
5+
const Utils = require("../../src/utils");
6+
7+
describe('Utils', () => {
8+
context('Clear Environment Variables', () => {
9+
it('Sets empty string as the value and deletes the entry from process.env', () => {
10+
sinon.stub(core, 'exportVariable');
11+
process.env.someVariable = 'someValue';
12+
Utils.clearEnvironmentVariable('someVariable');
13+
sinon.assert.calledWith(core.exportVariable, 'someVariable', '');
14+
expect(process.env.someVariable).to.eq(undefined);
15+
core.exportVariable.restore();
16+
});
17+
});
18+
19+
context('Check if tool exists in cache', () => {
20+
it('Returns true if tool exists in cache', () => {
21+
sinon.stub(tc, 'findAllVersions').returns(['somePath']);
22+
expect(Utils.checkToolInCache('someTool')).to.eq(true);
23+
sinon.assert.calledWith(tc.findAllVersions, 'someTool');
24+
tc.findAllVersions.restore();
25+
});
26+
27+
it("Returns false if tool doesn't exists in cache", () => {
28+
sinon.stub(tc, 'findAllVersions').returns([]);
29+
expect(Utils.checkToolInCache('someTool')).to.eq(false);
30+
sinon.assert.calledWith(tc.findAllVersions, 'someTool');
31+
tc.findAllVersions.restore();
32+
});
33+
});
34+
});

0 commit comments

Comments
 (0)