Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to update package.json automatically. #62

Merged
merged 1 commit into from May 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
76 changes: 63 additions & 13 deletions bin/ember-source-channel-url
Expand Up @@ -3,26 +3,76 @@

/* eslint-disable no-console */

const fs = require('fs');
const getChannelURL = require('../src');
const channel = process.argv[2];
const shouldUpdatePackage = process.argv.includes('-w') || process.argv.includes('--write');

if (['release', 'beta', 'canary'].indexOf(channel) === -1) {
console.log(
`ember-source-channel-url is a utility module to easily obtain the URL
function printUsage() {
console.log(`
ember-source-channel-url is a utility module to easily obtain the URL
to a tarball representing the latest \`ember-source\` build for a given
channel.

Usage:
USAGE:
ember-source-channel-url [CHANNEL] [FLAGS]

FLAGS:

-w, --write Update the local package.json to use the retrieved ember-source URL
-h, --help Prints help information

EXAMPLE:

* Print the most recent URL for the specified channel:

$ ember-source-channel-url canary
$ ember-source-channel-url beta
$ ember-source-channel-url release

* Update the local project's \`package.json\` to use the most recent URL for the canary channel:

$ ember-source-channel-url canary --write
`);
}

ember-source-channel-url canary
ember-source-channel-url beta
ember-source-channel-url release
`
);
if (['release', 'beta', 'canary'].indexOf(channel) === -1) {
printUsage();
process.exitCode = 1;
} else {
getChannelURL(channel).then(url =>
getChannelURL(channel).then(url => {
console.log(
`The URL for the latest tarball from ember-source's ${channel} channel is:\n\n\t${url}`
)
);
`The URL for the latest tarball from ember-source's ${channel} channel is:\n\n\t${url}\n`
);

if (shouldUpdatePackage) {
if (!fs.existsSync('package.json')) {
console.log(
`You passed --write to ember-source-channel-url but no package.json is available to update.`
);

process.exitCode = 2;
}

let contents = fs.readFileSync('package.json', { encoding: 'utf8' });
let pkg = JSON.parse(contents);

let dependencyType = ['dependencies', 'devDependencies'].find(
type => pkg[type] && pkg[type]['ember-source']
);

if (dependencyType) {
pkg[dependencyType]['ember-source'] = url;

let updatedContents = JSON.stringify(pkg, null, 2);
fs.writeFileSync('package.json', updatedContents, { encoding: 'utf8' });
} else {
console.log(
`You passed --write to ember-source-channel-url but ember-source is not included in dependencies or devDependencies in the package.json.`
);

process.exitCode = 3;
}
}
});
}
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -27,7 +27,8 @@
"prettier": "^1.17.1",
"qunit": "~2.9.2",
"qunit-eslint": "^2.0.0",
"rsvp": "^4.7.0"
"rsvp": "^4.7.0",
"tmp": "^0.1.0"
},
"engines": {
"node": "6.* || 8.* || >= 10.*"
Expand Down
105 changes: 99 additions & 6 deletions tests/index-test.js
@@ -1,24 +1,36 @@
'use strict';

const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const execa = require('execa');
const createServer = require('./helpers/server').createServer;
const getChannelURL = require('../src');
const tmp = require('tmp');

tmp.setGracefulCleanup();

const ROOT = process.cwd();
const EXECUTABLE_PATH = path.join(__dirname, '..', 'bin', 'ember-source-channel-url');

QUnit.module('ember-source-channel-url', function(hooks) {
function randomString(length) {
return crypto.randomBytes(Math.ceil(length / 2)).toString('hex');
}

hooks.beforeEach(function() {
let dir = tmp.dirSync();
process.chdir(dir.name);

return createServer().then(server => {
process.env.EMBER_SOURCE_CHANNEL_URL_HOST = `http://localhost:${server.port}`;

this.server = server;
this.fakeSHA = randomString(20);
let assetPath = (this.assetPath = `/canary/shas/${this.fakeSHA}.tgz`);

this.expectedURL = `http://${server.host}:${server.port}/builds.emberjs.com${this.assetPath}`;

server.on('/builds.emberjs.com/canary.json', (req, res) => {
res.end(JSON.stringify({ assetPath }));
});
Expand All @@ -28,6 +40,8 @@ QUnit.module('ember-source-channel-url', function(hooks) {
});

hooks.afterEach(function() {
process.chdir(ROOT);

return this.server.close();
});

Expand All @@ -43,13 +57,92 @@ QUnit.module('ember-source-channel-url', function(hooks) {

QUnit.module('binary', function() {
QUnit.test('works', function(assert) {
let expected = `http://${this.server.host}:${this.server.port}/builds.emberjs.com${
this.assetPath
}`;
return execa(EXECUTABLE_PATH, ['canary']).then(results => {
assert.ok(results.stdout.includes(this.expectedURL), 'URL is present in stdout');
});
});

QUnit.test('updates local package.json when -w is passed (dependencies)', function(assert) {
fs.writeFileSync(
'package.json',
JSON.stringify({ dependencies: { 'ember-source': '^3.10.0' } }),
{ encoding: 'utf8' }
);

return execa(EXECUTABLE_PATH, ['canary', '-w']).then(results => {
assert.ok(results.stdout.includes(this.expectedURL), 'URL is present in stdout');

assert.deepEqual(JSON.parse(fs.readFileSync('package.json', { encoding: 'utf8' })), {
dependencies: {
'ember-source': this.expectedURL,
},
});
});
});

QUnit.test('updates local package.json when --write is passed (dependencies)', function(
assert
) {
fs.writeFileSync(
'package.json',
JSON.stringify({ dependencies: { 'ember-source': '^3.10.0' } }),
{ encoding: 'utf8' }
);

return execa(EXECUTABLE_PATH, ['canary', '--write']).then(results => {
assert.ok(results.stdout.includes(this.expectedURL), 'URL is present in stdout');

assert.deepEqual(JSON.parse(fs.readFileSync('package.json', { encoding: 'utf8' })), {
dependencies: {
'ember-source': this.expectedURL,
},
});
});
});

QUnit.test('updates local package.json when --write is passed (devDependencies)', function(
assert
) {
fs.writeFileSync(
'package.json',
JSON.stringify({ devDependencies: { 'ember-source': '^3.10.0' } }),
{ encoding: 'utf8' }
);

return execa(EXECUTABLE_PATH, ['canary', '--write']).then(results => {
assert.ok(results.stdout.includes(this.expectedURL), 'URL is present in stdout');

assert.deepEqual(JSON.parse(fs.readFileSync('package.json', { encoding: 'utf8' })), {
devDependencies: {
'ember-source': this.expectedURL,
},
});
});
});

QUnit.test('fails when package.json is missing', function(assert) {
return execa(EXECUTABLE_PATH, ['canary', '--write']).catch(results => {
assert.ok(results.stdout.includes(this.expectedURL), 'URL is present in stdout');

assert.ok(
results.stdout.includes('no package.json is available to update'),
'warning is printed indicating -w failed'
);
});
});

QUnit.test('fails when ember-source is not a dep', function(assert) {
fs.writeFileSync('package.json', JSON.stringify({}), { encoding: 'utf8' });

return execa(EXECUTABLE_PATH, ['canary', '--write']).catch(results => {
assert.ok(results.stdout.includes(this.expectedURL), 'URL is present in stdout');

let executablePath = path.join(__dirname, '..', 'bin', 'ember-source-channel-url');
return execa(executablePath, ['canary']).then(results => {
assert.ok(results.stdout.includes(expected), 'URL is present in stdout');
assert.ok(
results.stdout.includes(
'ember-source is not included in dependencies or devDependencies'
),
'warning is printed indicating -w failed'
);
});
});
});
Expand Down
9 changes: 8 additions & 1 deletion yarn.lock
Expand Up @@ -1192,7 +1192,7 @@ restore-cursor@^2.0.0:
onetime "^2.0.0"
signal-exit "^3.0.2"

rimraf@2.6.3:
rimraf@2.6.3, rimraf@^2.6.3:
version "2.6.3"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
dependencies:
Expand Down Expand Up @@ -1379,6 +1379,13 @@ tmp@^0.0.33:
dependencies:
os-tmpdir "~1.0.2"

tmp@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877"
integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==
dependencies:
rimraf "^2.6.3"

tslib@^1.9.0:
version "1.9.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
Expand Down