Skip to content

CB-11279 Support arbitrary repositories for 'coho nightly' #122

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

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ module.exports = function() {
entryPoint: lazyRequire('./update-release-notes')
}, {
name: 'npm-unpublish-nightly',
desc: 'Unpublishes last nightly versions for cli and lib',
entryPoint: lazyRequire('./npm-publish', 'unpublish')
desc: 'Unpublishes last nightly versions for all specified repositories',
entryPoint: lazyRequire('./npm-publish', 'unpublishNightly')
}];
var otherCommands = [{
name: 'list-pulls',
Expand All @@ -137,7 +137,7 @@ module.exports = function() {
desc: 'Launches github PR UI for the specified topic branch',
entryPoint: lazyRequire('./create-pr'),
noChdir : true
},
},
{
name: 'last-week',
desc: 'Prints out git logs of things that happened last week.',
Expand Down
140 changes: 96 additions & 44 deletions src/nightly.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ var npmlink = require('./npm-link');
var repoclone = require('./repo-clone');

module.exports = function*(argv) {
var repos = flagutil.computeReposFromFlag('tools');
var cli = repoutil.getRepoById('cli');
var cordovaLib = repoutil.getRepoById('lib');
/** Specifies the default repos to build nightlies for */
var DEFAULT_NIGHTLY_REPOS = ['cli', 'lib'];

var opt = flagutil.registerHelpFlag(optimist);
opt = flagutil.registerRepoFlag(opt);

argv = opt
.usage('Publish CLI & LIB to NPM under nightly tag. \n' +
Expand All @@ -52,6 +53,7 @@ module.exports = function*(argv) {
type:'boolean',
alias : 'ignoreTestFailures'
})
.default({ r: DEFAULT_NIGHTLY_REPOS})
.argv;

if(argv.h) {
Expand All @@ -60,36 +62,26 @@ module.exports = function*(argv) {
}

// Clone and update Repos
yield repoclone.cloneRepos(repos, /*silent=*/true);
yield repoupdate.updateRepos(repos);
yield prepareRepos(argv.r);

//remove local changes and sync up with remote master
yield repoutil.forEachRepo(repos, function*() {
yield gitutil.gitClean();
yield gitutil.resetFromOrigin();
});
var reposToBuild = flagutil.computeReposFromFlag(argv.r, { includeModules: true });
// Get updated nightly versions for all repos
/** @type {Object} A map of repo.id and a short SHA for every repo to build */
var VERSIONS = yield retrieveVersions(reposToBuild);

// Get SHAS from repos
var SHAJSON = yield retrieveSha(repos);
// Update version in package.json and other respective files for every repo
// and update dependencies to use nightly versions of packages to be released
yield repoutil.forEachRepo(reposToBuild, function*(repo) {
apputil.print('Updating ' + repo.id + ' version to ' + VERSIONS[repo.id]);
yield versionutil.updateRepoVersion(repo, VERSIONS[repo.id], { commitChanges: false });

var currentDate = new Date();
var nightlyVersion = '-nightly.' + currentDate.getFullYear() + '.' +
(currentDate.getMonth() + 1) + '.' + currentDate.getDate();
var cordovaLibVersion;
//update package.json version for cli + lib, update lib reference for cli
yield repoutil.forEachRepo([cordovaLib, cli], function*(repo) {
var dir = process.cwd();
var packageJSON = require(dir+'/package.json');
packageJSON.version = versionutil.removeDev(packageJSON.version) + nightlyVersion +
'+' + SHAJSON[repo.id];

if(repo.id === 'lib'){
cordovaLibVersion = packageJSON.version;
} else {
packageJSON.dependencies['cordova-lib'] = cordovaLibVersion;
}
var packageJSONPath = path.join(process.cwd(), 'package.json');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like updateRepoVersion already updates package.json - you can probably remove the code here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still need to update dependencies in package.json in case if we're releasing both dependent package and its dependency (e.g. cordova-lib and cordova-common), so the code is still required.

Anyway this code will be updated in the next PR that adds more robust support for platforms nightly releases

var packageJSON = JSON.parse(fs.readFileSync(packageJSONPath));

fs.writeFileSync(dir+'/package.json', JSON.stringify(packageJSON, null, 4), 'utf8', function(err) {
// If there is a dependencies listed, iterate through and update cordova-* dependencies
packageJSON.dependencies = mapDependenciesVersions(packageJSON.dependencies, VERSIONS);

fs.writeFileSync(packageJSONPath, JSON.stringify(packageJSON, null, 2) + '\n', 'utf8', function(err) {
if (err) return console.log (err);
});
});
Expand All @@ -98,36 +90,64 @@ module.exports = function*(argv) {
yield npmlink();

// npm install cli
var cli = repoutil.getRepoById('cli');
yield repoutil.forEachRepo([cli], function*(repo) {
yield executil.execHelper(executil.ARGS('npm install'), /*silent=*/true, false);
});

//run CLI + cordova-lib tests
yield runTests(cli, cordovaLib, argv.ignoreTestFailures);
yield runTests(reposToBuild, argv.ignoreTestFailures);

var options = {};
options.tag = 'nightly';
options.pretend = argv.pretend;
options.r = reposToBuild.map(function (repo) { return repo.id; });

//unpublish old nightly
yield repoutil.forEachRepo([cordovaLib, cli], function*(repo) {
var packageName = repo.packageName || repo.repoName;
var oldNightlyVersion = yield executil.execHelper(executil.ARGS('npm view ' + packageName + ' dist-tags.nightly'));
apputil.print('Latest ' + packageName + '@nightly version is ' + oldNightlyVersion);

options.r = [repo.id];
options.version = oldNightlyVersion;

yield npmpublish.unpublish(options);
});

options.r = ['lib', 'cli'];
yield npmpublish.unpublishNightly(options);
//publish to npm under nightly tag
yield npmpublish.publishTag(options);
};

function* prepareRepos(repoNames) {
// Clone and update required repos
apputil.print('Cloning and updating required repositories...');
var reposToClone = flagutil.computeReposFromFlag(['tools'].concat(repoNames));
yield repoclone.cloneRepos(reposToClone, /*silent=*/true);
yield repoupdate.updateRepos(reposToClone, /*silent=*/true);

// Remove local changes and sync up with remote master
apputil.print('Resetting repositories to "master" branches...');
var reposToUpdate = flagutil.computeReposFromFlag(repoNames);
yield repoutil.forEachRepo(reposToUpdate, function*() {
yield gitutil.gitClean();
yield gitutil.resetFromOrigin();
});
}

function *runTests(cli, lib, ignoreTestFailures) {
yield repoutil.forEachRepo([cli, lib], function *(repo) {
/**
* Updates provided dependencies object with versions, supplied in packageVersions object
* @param {Object<String, String>} packageDependencies A map of current package's dependencies to versions
* @param {Object<String, String>} packageVersions Map of package's id's to nightly versions
* @returns {Object<String, String>} A mapped object
*/
function mapDependenciesVersions(packageDependencies, packageVersions) {
return Object.keys(packageDependencies)
.reduce(function (result, dependency) {
var dep = repoutil.getRepoById(dependency);
// If this is a cordova-* dependency, and we're going to build nightly for it
if (dependency.match(/cordova\-.*/) && dep && packageVersions[dep.id]) {
// Update its version in package's dependencies to nightly version
apputil.print('Updating ' + dependency + ' dependency version to ' + packageVersions[dep.id]);
result[dependency] = packageVersions[dep.id];
}

return result;
}, packageDependencies);
}

function *runTests(repos, ignoreTestFailures) {
yield repoutil.forEachRepo(repos, function *(repo) {
try {
yield executil.execHelper(executil.ARGS('npm test'), false, ignoreTestFailures);
} catch (e) {
Expand All @@ -136,3 +156,35 @@ function *runTests(cli, lib, ignoreTestFailures) {
}
});
}

/**
* Generates suffix for appending to nightly package version
* based on current date and SHA string.
* @param SHA {String} String to use to generate nightly version
* @returns {String} A newly generated nightly suffix
*/
function getNightlySuffix (SHA) {
var currentDate = new Date();
var nightlySuffix = '-nightly.' + currentDate.getFullYear() + '.' +
(currentDate.getMonth() + 1) + '.' + currentDate.getDate() +
'+' + SHA;

return nightlySuffix;
}

/**
* Generates map of repo.id -> nightly version based on current
* date and SHA of current revision of repository
* @param {Object[]} repos An array of cordova repos
* @returns {Object} Mapped object
*/
function* retrieveVersions(repos) {
var SHAJSON = yield retrieveSha(repos);

return Object.keys(SHAJSON).reduce(function (result, repoId) {
var repoPath = repoutil.getRepoDir(repoutil.getRepoById(repoId));
var oldVersion = require(path.join(repoPath, 'package.json')).version;
result[repoId] = versionutil.removeDev(oldVersion) + getNightlySuffix(SHAJSON[repoId]);
return result;
}, {});
}
27 changes: 9 additions & 18 deletions src/npm-publish.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,8 @@ function *publishTag(options) {

module.exports.publishTag = publishTag;

//TODO: Does npm tag cordova-js*.tgz latest
exports.setLatest = function*(argv) {


}

//Gets last nightly tag and unpublishes it
function *unpublish(options) {
function *unpublishNightly(options) {
var opt = flagutil.registerHelpFlag(optimist);

if(options) {
Expand All @@ -92,24 +86,17 @@ function *unpublish(options) {
.options('r', {
default:options.r
})
.options('version', {
default:options.version
})
}

argv = opt
var argv = opt
.usage("Unpublishes the nightly version for the cli & lib from npm \n" +
"Usage: $0 npm-unpublish-nightly")
.options("pretend", {
desc: "Don't actually run commands, just print what would be run",
type: "boolean"
})
.options('r', {
desc: "Which repo(s) to publish",
demand: true
})
.options('version', {
desc: "Which version to unpublish",
desc: "Which repo(s) to unpublish",
demand: true
})
.argv;
Expand All @@ -123,8 +110,12 @@ function *unpublish(options) {

yield repoutil.forEachRepo(repos, function*(repo) {
var packageId = repo.packageName || repo.repoName;
yield executil.execOrPretend(executil.ARGS('npm unpublish '+ packageId + '@' + argv.version), argv.pretend);
var oldNightlyVersion = yield executil.execHelper(executil.ARGS('npm view ' + packageId + ' dist-tags.nightly'));

if (oldNightlyVersion && oldNightlyVersion !== 'undefined') {
yield executil.execOrPretend(executil.ARGS('npm unpublish '+ packageId + '@' + oldNightlyVersion), argv.pretend);
}
});
}

module.exports.unpublish = unpublish;
module.exports.unpublishNightly = unpublishNightly;
58 changes: 3 additions & 55 deletions src/platform-release.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ specific language governing permissions and limitations
under the License.
*/

var fs = require('fs');
var path = require('path');
var optimist = require('optimist');
var shelljs = require('shelljs');
Expand All @@ -27,6 +26,7 @@ var flagutil = require('./flagutil');
var gitutil = require('./gitutil');
var repoutil = require('./repoutil');
var repoupdate = require('./repo-update');
var versionutil = require('./versionutil');
var print = apputil.print;

function createPlatformDevVersion(version) {
Expand Down Expand Up @@ -114,58 +114,6 @@ function *updateJsSnapshot(repo, version) {
}
}

function *updateRepoVersion(repo, version) {
// Update the VERSION files.
var versionFilePaths = repo.versionFilePaths || ['VERSION'];
if (fs.existsSync(versionFilePaths[0])) {
versionFilePaths.forEach(function(versionFilePath) {
fs.writeFileSync(versionFilePath, version + '\n');
});
shelljs.config.fatal = true;
if (repo.id == 'android' || repo.id == 'amazon-fireos') {
shelljs.sed('-i', /CORDOVA_VERSION.*=.*;/, 'CORDOVA_VERSION = "' + version + '";', path.join('framework', 'src', 'org', 'apache', 'cordova', 'CordovaWebView.java'));
shelljs.sed('-i', /VERSION.*=.*;/, 'VERSION = "' + version + '";', path.join('bin', 'templates', 'cordova', 'version'));
} else if (repo.id == 'ios' || repo.id == 'osx') {
shelljs.sed('-i', /VERSION.*=.*/, 'VERSION="' + version + '";', path.join('bin', 'templates', 'scripts', 'cordova', 'version'));
} else if (repo.id == 'blackberry') {
shelljs.sed('-i', /VERSION.*=.*;/, 'VERSION = "' + version + '";', path.join('bin', 'templates', 'project','cordova', 'lib', 'version.js'));
} else if (repo.id == 'firefoxos' || repo.id == 'browser' || repo.id == 'ubuntu') {
shelljs.sed('-i', /VERSION.*=.*;/, 'VERSION = "' + version + '";', path.join('bin', 'templates', 'project','cordova', 'version'));
} else if (repo.id == 'windows') {
if(fs.existsSync(path.join('template', 'cordova', 'version'))) {
console.log('version exists');
shelljs.sed('-i', /VERSION.*=.*;/, 'VERSION = "' + version + '";', path.join('template', 'cordova', 'version'));
}
}
shelljs.config.fatal = false;
if (!(yield gitutil.pendingChangesExist())) {
print('VERSION file was already up-to-date.');
}
} else {
console.warn('No VERSION file exists in repo ' + repo.repoName);
}

// Update the package.json VERSION.
var packageFilePaths = repo.packageFilePaths || ['package.json'];
if (fs.existsSync(packageFilePaths[0])) {
fs.readFile(packageFilePaths[0], {encoding: 'utf-8'},function (err, data) {
if (err) throw err;
var packageJSON = JSON.parse(data);
packageJSON.version = version;
fs.writeFileSync(packageFilePaths[0], JSON.stringify(packageJSON, null, " "));
});
if (!(yield gitutil.pendingChangesExist())) {
print('package.json file was already up-to-date.');
}
} else {
console.warn('No package.json file exists in repo ' + repo.repoName);
}

if (yield gitutil.pendingChangesExist()) {
yield executil.execHelper(executil.ARGS('git commit -am', 'Set VERSION to ' + version + ' (via coho)'));
}
}

exports.prepareReleaseBranchCommand = function*() {
var argv = configureReleaseCommandFlags(optimist
.usage('Prepares release branches but does not create tags. This includes:\n' +
Expand Down Expand Up @@ -206,12 +154,12 @@ exports.prepareReleaseBranchCommand = function*() {
}
yield updateJsSnapshot(repo, version);
print(repo.repoName + ': ' + 'Setting VERSION to "' + version + '" on branch + "' + branchName + '".');
yield updateRepoVersion(repo, version);
yield versionutil.updateRepoVersion(repo, version);

yield gitutil.gitCheckout('master');
var devVersion = createPlatformDevVersion(version);
print(repo.repoName + ': ' + 'Setting VERSION to "' + devVersion + '" on branch + "master".');
yield updateRepoVersion(repo, devVersion);
yield versionutil.updateRepoVersion(repo, devVersion);
yield updateJsSnapshot(repo, devVersion);
yield gitutil.gitCheckout(branchName);
});
Expand Down
11 changes: 10 additions & 1 deletion src/repoutil.js
Original file line number Diff line number Diff line change
Expand Up @@ -439,11 +439,20 @@ repoGroups.__defineGetter__('auto', function() {

exports.repoGroups = repoGroups;

function isInRepoGroup(repoToCheck, groupName) {
var repos = repoGroups[groupName];
if (!repos) return false;
return repos.some(function (repo) {
return repo.id === repoToCheck.id;
});
}
exports.isInRepoGroup = isInRepoGroup;

function getRepoById(id, opt_repos) {
// Strip cordova- prefix if it exists.
var repos = opt_repos || allRepos;
for (var i = 0; i < repos.length; ++i) {
if (repos[i].id == id || repos[i].repoName == id) {
if (repos[i].id == id || repos[i].packageName == id || repos[i].repoName == id) {
return repos[i];
}
}
Expand Down
Loading