Skip to content

Commit 31d2e46

Browse files
shubhekshakumar303
authored andcommitted
feat: web-ext automatically checks for updates (#676)
1 parent dbdf9e2 commit 31d2e46

File tree

5 files changed

+120
-11
lines changed

5 files changed

+120
-11
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,13 @@
5757
"minimatch": "3.0.3",
5858
"mz": "2.6.0",
5959
"node-firefox-connect": "1.2.0",
60-
"regenerator-runtime": "0.10.1",
6160
"parse-json": "2.2.0",
61+
"regenerator-runtime": "0.10.1",
6262
"sign-addon": "0.2.0",
6363
"source-map-support": "0.4.7",
6464
"stream-to-promise": "2.2.0",
6565
"tmp": "0.0.30",
66+
"update-notifier": "1.0.3",
6667
"watchpack": "1.1.0",
6768
"yargs": "6.5.0",
6869
"zip-dir": "1.0.2"

src/program.js

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,14 @@ import defaultCommands from './cmd';
99
import {UsageError} from './errors';
1010
import {createLogger, consoleStream as defaultLogStream} from './util/logger';
1111
import {coerceCLICustomPreference} from './firefox/preferences';
12+
import {checkForUpdates as defaultUpdateChecker} from './util/updates';
1213

1314
const log = createLogger(__filename);
1415
const envPrefix = 'WEB_EXT';
1516

17+
type ProgramOptions = {|
18+
absolutePackageDir?: string,
19+
|}
1620

1721
/*
1822
* The command line program.
@@ -24,7 +28,9 @@ export class Program {
2428

2529
constructor(
2630
argv: ?Array<string>,
27-
{absolutePackageDir = process.cwd()}: {absolutePackageDir?: string} = {}
31+
{
32+
absolutePackageDir = process.cwd(),
33+
}: ProgramOptions = {}
2834
) {
2935
// This allows us to override the process argv which is useful for
3036
// testing.
@@ -84,8 +90,9 @@ export class Program {
8490
async execute(
8591
absolutePackageDir: string,
8692
{
87-
systemProcess = process, logStream = defaultLogStream,
88-
getVersion = defaultVersionGetter, shouldExitProgram = true,
93+
checkForUpdates = defaultUpdateChecker, systemProcess = process,
94+
logStream = defaultLogStream, getVersion = defaultVersionGetter,
95+
shouldExitProgram = true, globalEnv = WEBEXT_BUILD_ENV,
8996
}: Object = {}
9097
): Promise<void> {
9198

@@ -112,7 +119,14 @@ export class Program {
112119
if (!runCommand) {
113120
throw new UsageError(`Unknown command: ${cmd}`);
114121
}
122+
if (globalEnv === 'production') {
123+
checkForUpdates ({
124+
version: getVersion(absolutePackageDir),
125+
});
126+
}
127+
115128
await runCommand(argv);
129+
116130
} catch (error) {
117131
const prefix = cmd ? `${cmd}: ` : '';
118132
if (!(error instanceof UsageError) || argv.verbose) {
@@ -138,14 +152,14 @@ declare var WEBEXT_BUILD_ENV: string;
138152

139153
//A defintion of type of argument for defaultVersionGetter
140154
type versionGetterOptions = {
141-
localEnv?: string,
155+
globalEnv?: string,
142156
};
143157

144158
export function defaultVersionGetter(
145159
absolutePackageDir: string,
146-
{localEnv = WEBEXT_BUILD_ENV}: versionGetterOptions = {}
160+
{globalEnv = WEBEXT_BUILD_ENV}: versionGetterOptions = {}
147161
): string {
148-
if (localEnv === 'production') {
162+
if (globalEnv === 'production') {
149163
log.debug('Getting the version from package.json');
150164
const packageData: any = readFileSync(
151165
path.join(absolutePackageDir, 'package.json'));
@@ -164,7 +178,9 @@ export function main(
164178
runOptions = {},
165179
}: Object = {}
166180
): Promise<any> {
181+
167182
const program = new Program(argv, {absolutePackageDir});
183+
168184
// yargs uses magic camel case expansion to expose options on the
169185
// final argv object. For example, the 'artifacts-dir' option is alternatively
170186
// available as argv.artifactsDir.

src/util/updates.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/* @flow */
2+
import defaultUpdateNotifier from 'update-notifier';
3+
4+
type checkForUpdatesParams = {|
5+
version: string,
6+
updateNotifier?: typeof defaultUpdateNotifier,
7+
|};
8+
9+
export function checkForUpdates(
10+
{
11+
version,
12+
updateNotifier = defaultUpdateNotifier,
13+
}: checkForUpdatesParams
14+
) {
15+
const pkg = {name: 'web-ext', version};
16+
17+
updateNotifier({
18+
pkg,
19+
updateCheckInterval: 1000 * 60 * 60 * 24 * 3, // 3 days,
20+
}).notify();
21+
}

tests/unit/test-util/test.updates.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/* @flow */
2+
import {it, describe} from 'mocha';
3+
import {assert} from 'chai';
4+
import sinon from 'sinon';
5+
6+
import {checkForUpdates} from '../../../src/util/updates';
7+
8+
describe('util/updates', () => {
9+
describe('checkForUpdates()', () => {
10+
it('calls the notifier with the correct parameters', () => {
11+
const updateNotifierStub = sinon.spy(() => {
12+
return {
13+
notify: sinon.spy(),
14+
};
15+
});
16+
17+
checkForUpdates({
18+
version: '1.0.0',
19+
updateNotifier: updateNotifierStub,
20+
});
21+
assert.equal(updateNotifierStub.called, true);
22+
assert.equal(updateNotifierStub.firstCall.args[0].pkg.name, 'web-ext');
23+
assert.equal(updateNotifierStub.firstCall.args[0].pkg.version, '1.0.0');
24+
assert.isNumber(updateNotifierStub.firstCall.args[0].updateCheckInterval);
25+
assert.equal(updateNotifierStub.firstCall.args[0].updateCheckInterval,
26+
1000 * 60 * 60 * 24 * 3);
27+
});
28+
});
29+
});

tests/unit/test.program.js

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ describe('program.Program', () => {
2121
const absolutePackageDir = path.join(__dirname, '..', '..');
2222
return program.execute(
2323
absolutePackageDir, {
24+
getVersion: () => spy(),
25+
checkForUpdates: spy(),
2426
systemProcess: fakeProcess,
2527
shouldExitProgram: false,
2628
...options,
@@ -176,7 +178,10 @@ describe('program.Program', () => {
176178
});
177179
program.command('thing', 'does a thing', () => {});
178180

179-
return execProgram(program, {getVersion: spy(), logStream})
181+
return execProgram(program, {
182+
getVersion: spy(),
183+
logStream,
184+
})
180185
.then(() => {
181186
assert.equal(logStream.makeVerbose.called, true);
182187
});
@@ -241,13 +246,50 @@ describe('program.Program', () => {
241246
});
242247
});
243248

249+
it('checks for updates automatically', () => {
250+
const handler = spy();
251+
const getVersion = () => 'some-package-version';
252+
const checkForUpdates = sinon.stub();
253+
const program = new Program(['run'])
254+
.command('run', 'some command', handler);
255+
return execProgram(program, {
256+
checkForUpdates,
257+
getVersion,
258+
globalEnv: 'production',
259+
})
260+
.then(() => {
261+
assert.equal(checkForUpdates.firstCall.args[0].version,
262+
'some-package-version');
263+
});
264+
});
265+
266+
it('does not check for updates during development', () => {
267+
const handler = spy();
268+
const getVersion = () => 'some-package-version';
269+
const checkForUpdates = sinon.stub();
270+
const program = new Program(['run'])
271+
.command('run', 'some command', handler);
272+
return execProgram(program, {
273+
checkForUpdates,
274+
getVersion,
275+
globalEnv: 'development',
276+
})
277+
.then(() => {
278+
assert.equal(checkForUpdates.called, false);
279+
});
280+
});
244281
});
245282

246283

247284
describe('program.main', () => {
248285

249286
function execProgram(argv, {projectRoot = '', ...mainOptions}: Object = {}) {
250-
const runOptions = {shouldExitProgram: false, systemProcess: fake(process)};
287+
const runOptions = {
288+
getVersion: () => 'not-a-real-version',
289+
checkForUpdates: spy(),
290+
shouldExitProgram: false,
291+
systemProcess: fake(process),
292+
};
251293
return main(projectRoot, {argv, runOptions, ...mainOptions});
252294
}
253295

@@ -351,15 +393,15 @@ describe('program.defaultVersionGetter', () => {
351393
const pkgFile = path.join(root, 'package.json');
352394
return fs.readFile(pkgFile)
353395
.then((pkgData) => {
354-
const testBuildEnv = {localEnv: 'production'};
396+
const testBuildEnv = {globalEnv: 'production'};
355397
assert.equal(defaultVersionGetter(root, testBuildEnv),
356398
JSON.parse(pkgData).version);
357399
});
358400
});
359401

360402
it('returns git commit information in development', () => {
361403
const commit = `${git.branch()}-${git.long()}`;
362-
const testBuildEnv = {localEnv: 'development'};
404+
const testBuildEnv = {globalEnv: 'development'};
363405
assert.equal(defaultVersionGetter(root, testBuildEnv),
364406
commit);
365407
});

0 commit comments

Comments
 (0)