--- /dev/null
+module.exports = function( Release ) {
+
+var shell = require( "shelljs" ),
+ path = require( "path" );
+
+function buildPreReleasePackage( callback ) {
+ var builder, files, jqueryUi, packer, target,
+ downloadBuilder = require( "download.jqueryui.com" );
+ jqueryUi = new downloadBuilder.JqueryUi( path.resolve( "." ) );
+ builder = new downloadBuilder.Builder( jqueryUi, ":all:" );
+ packer = new downloadBuilder.Packer( builder, null, {
+ addTests: true,
+ bundleSuffix: "",
+ skipDocs: true,
+ skipTheme: true
+ });
+ target = "../" + jqueryUi.pkg.name + "-" + jqueryUi.pkg.version + "-cdn.zip";
+
+ console.log( "Building release files" );
+ packer.pack(function( error, _files ) {
+ if ( error ) {
+ Release.abort( "Failed packing pre-release package", error );
+ }
+ files = _files.map(function( file ) {
+
+ // Strip first path
+ file.path = file.path.replace( /^[^\/]*\//, "" );
+ return file;
+ }).filter(function( file ) {
+
+ // Filter development-bundle content only
+ return (/^development-bundle/).test( file.path );
+ }).map(function( file ) {
+
+ // Strip development-bundle
+ file.path = file.path.replace( /^development-bundle\//, "" );
+ return file;
+ });
+
+ downloadBuilder.util.createZip( files, target, function( error ) {
+ if ( error ) {
+ Release.abort( "Failed create pre-release zip", error );
+ }
+ console.log( "Built zip package at " + path.relative( "../..", target ).cyan );
+ return callback();
+ });
+ });
+}
+
+function buildCDNPackage( callback ) {
+ console.log( "Building CDN package" );
+ var downloadBuilder = require( "download.jqueryui.com" ),
+ jqueryUi = new downloadBuilder.JqueryUi( path.resolve( "." ) ),
+ builder = new downloadBuilder.Builder( jqueryUi, ":all:" ),
+ packer = new downloadBuilder.ThemesPacker( builder, {
+ includeJs: true
+ }),
+ target = "../" + jqueryUi.pkg.name + "-" + jqueryUi.pkg.version + "-cdn.zip";
+
+ // Zip dir structure must be flat, override default base folder
+ packer.basedir = "";
+ packer.zipTo( target, function( error ) {
+ if ( error ) {
+ Release.abort( "Failed to zip CDN package", error );
+ }
+ callback();
+ });
+}
+
+Release.define({
+ issueTracker: "trac",
+ contributorReportId: 22,
+ changelogShell: function() {
+ var monthNames = [ "January", "February", "March", "April", "May", "June", "July",
+ "August", "September", "October", "November", "December" ],
+ now = new Date();
+ return "<script>{\n\t\"title\": \"jQuery UI " + Release.newVersion + " Changelog\"\n" +
+ "}</script>\n\nReleased on " + monthNames[ now.getMonth() ] + " " + now.getDate() + ", " + now.getFullYear() + "\n\n";
+ },
+ generateArtifacts: function( fn ) {
+ var manifestFiles;
+ function copyCdnFiles() {
+ var zipFile = shell.ls( "../jquery*-cdn.zip" )[ 0 ],
+ tmpFolder = "../tmp-zip-output",
+ unzipCommand = "unzip -o " + zipFile + " -d " + tmpFolder;
+
+ console.log( "Unzipping for dist/cdn copies" );
+ shell.mkdir( "-p", tmpFolder );
+ Release.exec({
+ command: unzipCommand,
+ silent: true
+ }, "Failed to unzip cdn files" );
+
+ shell.mkdir( "-p", "dist/cdn" );
+ shell.cp( tmpFolder + "/jquery-ui*.js", "dist/cdn" );
+ shell.cp( "-r", tmpFolder + "/themes", "dist/cdn" );
+ fn( manifestFiles );
+ }
+
+ Release.exec( "grunt manifest" );
+ manifestFiles = shell.ls( "*.jquery.json" );
+ if ( Release.preRelease ) {
+
+ // TODO no need to create a zip file here, just copy the needed files to dist/cdn
+ buildPreReleasePackage( copyCdnFiles );
+ } else {
+ buildCDNPackage( copyCdnFiles );
+ }
+ }
+});
+
+};
+
+module.exports.dependencies = [
+ "download.jqueryui.com@2.0.1",
+ "shelljs@0.2.6"
+];
+++ /dev/null
-#!/usr/bin/env node
-/* global cat:true, cd:true, echo:true, exec:true, exit:true */
-
-// Usage:
-// stable release: node release.js
-// pre-release: node release.js --pre-release {version}
-// test run: node release.js --remote={repo}
-// - repo: "/tmp/repo" (filesystem), "user/repo" (github), "http://mydomain/repo.git" (another domain)
-
-"use strict";
-
-var baseDir, downloadBuilder, repoDir, prevVersion, newVersion, nextVersion, tagTime, preRelease, repo,
- fs = require( "fs" ),
- path = require( "path" ),
- rnewline = /\r?\n/,
- branch = "master";
-
-walk([
- bootstrap,
-
- section( "setting up repo" ),
- cloneRepo,
- checkState,
-
- section( "calculating versions" ),
- getVersions,
- confirm,
-
- section( "building release" ),
- buildReleaseBranch,
- buildPackage,
-
- section( "pushing tag" ),
- confirmReview,
- pushRelease,
-
- section( "updating branch version" ),
- updateBranchVersion,
-
- section( "pushing " + branch ),
- confirmReview,
- pushBranch,
-
- section( "generating changelog" ),
- generateChangelog,
-
- section( "gathering contributors" ),
- gatherContributors,
-
- section( "updating trac" ),
- updateTrac,
- confirm
-]);
-
-
-
-
-
-function cloneRepo() {
- echo( "Cloning " + repo.cyan + "..." );
- git( "clone " + repo + " " + repoDir, "Error cloning repo." );
- cd( repoDir );
-
- echo( "Checking out " + branch.cyan + " branch..." );
- git( "checkout " + branch, "Error checking out branch." );
- echo();
-
- echo( "Installing dependencies..." );
- if ( exec( "npm install" ).code !== 0 ) {
- abort( "Error installing dependencies." );
- }
- echo();
-}
-
-function checkState() {
- echo( "Checking AUTHORS.txt..." );
- var result, lastActualAuthor,
- lastListedAuthor = cat( "AUTHORS.txt" ).trim().split( rnewline ).pop();
-
- result = exec( "grunt authors", { silent: true });
- if ( result.code !== 0 ) {
- abort( "Error getting list of authors." );
- }
- lastActualAuthor = result.output.split( rnewline ).splice( -4, 1 )[ 0 ];
-
- if ( lastListedAuthor !== lastActualAuthor ) {
- echo( "Last listed author is " + lastListedAuthor.red + "." );
- echo( "Last actual author is " + lastActualAuthor.green + "." );
- abort( "Please update AUTHORS.txt." );
- }
-
- echo( "Last listed author (" + lastListedAuthor.cyan + ") is correct." );
-}
-
-function getVersions() {
- // prevVersion, newVersion, nextVersion are defined in the parent scope
- var parts, major, minor, patch,
- currentVersion = readPackage().version;
-
- echo( "Validating current version..." );
- if ( currentVersion.substr( -3, 3 ) !== "pre" ) {
- echo( "The current version is " + currentVersion.red + "." );
- abort( "The version must be a pre version." );
- }
-
- if ( preRelease ) {
- newVersion = preRelease;
- // Note: prevVersion is not currently used for pre-releases.
- prevVersion = nextVersion = currentVersion;
- } else {
- newVersion = currentVersion.substr( 0, currentVersion.length - 3 );
- parts = newVersion.split( "." );
- major = parseInt( parts[ 0 ], 10 );
- minor = parseInt( parts[ 1 ], 10 );
- patch = parseInt( parts[ 2 ], 10 );
-
- if ( minor === 0 && patch === 0 ) {
- abort( "This script is not smart enough to handle major release (eg. 2.0.0)." );
- } else if ( patch === 0 ) {
- prevVersion = git( "for-each-ref --count=1 --sort=-authordate --format='%(refname:short)' refs/tags/" + [ major, minor - 1 ].join( "." ) + "*" ).trim();
- } else {
- prevVersion = [ major, minor, patch - 1 ].join( "." );
- }
-
- nextVersion = [ major, minor, patch + 1 ].join( "." ) + "pre";
- }
-
- echo( "We are going from " + prevVersion.cyan + " to " + newVersion.cyan + "." );
- echo( "After the release, the version will be " + nextVersion.cyan + "." );
-}
-
-function buildReleaseBranch() {
- var pkg;
-
- echo( "Creating " + "release".cyan + " branch..." );
- git( "checkout -b release", "Error creating release branch." );
- echo();
-
- echo( "Updating package.json..." );
- pkg = readPackage();
- pkg.version = newVersion;
- pkg.author.url = pkg.author.url.replace( "master", newVersion );
- pkg.licenses.forEach(function( license ) {
- license.url = license.url.replace( "master", newVersion );
- });
- writePackage( pkg );
-
- echo( "Generating manifest files..." );
- if ( exec( "grunt manifest" ).code !== 0 ) {
- abort( "Error generating manifest files." );
- }
- echo();
-
- echo( "Committing release artifacts..." );
- git( "add *.jquery.json", "Error adding manifest files to git." );
- git( "commit -am 'Tagging the " + newVersion + " release.'",
- "Error committing release changes." );
- echo();
-
- echo( "Tagging release..." );
- git( "tag " + newVersion, "Error tagging " + newVersion + "." );
- tagTime = git( "log -1 --format='%ad'", "Error getting tag timestamp." ).trim();
-}
-
-function buildPackage( callback ) {
- if( preRelease ) {
- return buildPreReleasePackage( callback );
- } else {
- return buildCDNPackage( callback );
- }
-}
-
-function buildPreReleasePackage( callback ) {
- var build, files, jqueryUi, packer, target, targetZip;
-
- echo( "Build pre-release Package" );
-
- jqueryUi = new downloadBuilder.JqueryUi( path.resolve( "." ) );
- build = new downloadBuilder.Builder( jqueryUi, ":all:" );
- packer = new downloadBuilder.Packer( build, null, {
- addTests: true,
- bundleSuffix: "",
- skipDocs: true,
- skipTheme: true
- });
- target = "../" + jqueryUi.pkg.name + "-" + jqueryUi.pkg.version;
- targetZip = target + ".zip";
-
- return walk([
- function( callback ) {
- echo( "Building release files" );
- packer.pack(function( error, _files ) {
- if( error ) {
- abort( error.stack );
- }
- files = _files.map(function( file ) {
-
- // Strip first path
- file.path = file.path.replace( /^[^\/]*\//, "" );
- return file;
-
- }).filter(function( file ) {
-
- // Filter development-bundle content only
- return (/^development-bundle/).test( file.path );
- }).map(function( file ) {
-
- // Strip development-bundle
- file.path = file.path.replace( /^development-bundle\//, "" );
- return file;
-
- });
- return callback();
- });
- },
- function() {
- downloadBuilder.util.createZip( files, targetZip, function( error ) {
- if ( error ) {
- abort( error.stack );
- }
- echo( "Built zip package at " + path.relative( "../..", targetZip ).cyan );
- return callback();
- });
- }
- ]);
-}
-
-function buildCDNPackage( callback ) {
- var build, output, target, targetZip,
- add = function( file ) {
- output.push( file );
- },
- jqueryUi = new downloadBuilder.JqueryUi( path.resolve( "." ) ),
- themeGallery = downloadBuilder.themeGallery( jqueryUi );
-
- echo( "Build CDN Package" );
-
- build = new downloadBuilder.Builder( jqueryUi, ":all:" );
- output = [];
- target = "../" + jqueryUi.pkg.name + "-" + jqueryUi.pkg.version + "-cdn";
- targetZip = target + ".zip";
-
- [ "AUTHORS.txt", "MIT-LICENSE.txt", "package.json" ].map(function( name ) {
- return build.get( name );
- }).forEach( add );
-
- // "ui/*.js"
- build.componentFiles.filter(function( file ) {
- return (/^ui\//).test( file.path );
- }).forEach( add );
-
- // "ui/*.min.js"
- build.componentMinFiles.filter(function( file ) {
- return (/^ui\//).test( file.path );
- }).forEach( add );
-
- // "i18n/*.js"
- build.i18nFiles.rename( /^ui\//, "" ).forEach( add );
- build.i18nMinFiles.rename( /^ui\//, "" ).forEach( add );
- build.bundleI18n.into( "i18n/" ).forEach( add );
- build.bundleI18nMin.into( "i18n/" ).forEach( add );
-
- build.bundleJs.forEach( add );
- build.bundleJsMin.forEach( add );
-
- walk( themeGallery.map(function( theme ) {
- return function( callback ) {
- var themeCssOnlyRe, themeDirRe,
- folderName = theme.folderName(),
- packer = new downloadBuilder.Packer( build, theme, {
- skipDocs: true
- });
- // TODO improve code by using custom packer instead of download packer (Packer)
- themeCssOnlyRe = new RegExp( "development-bundle/themes/" + folderName + "/jquery.ui.theme.css" );
- themeDirRe = new RegExp( "css/" + folderName );
- packer.pack(function( error, files ) {
- if ( error ) {
- abort( error.stack );
- }
- // Add theme files.
- files
- // Pick only theme files we need on the bundle.
- .filter(function( file ) {
- if ( themeCssOnlyRe.test( file.path ) || themeDirRe.test( file.path ) ) {
- return true;
- }
- return false;
- })
- // Convert paths the way bundle needs
- .map(function( file ) {
- file.path = file.path
-
- // Remove initial package name eg. "jquery-ui-1.10.0.custom"
- .split( "/" ).slice( 1 ).join( "/" )
-
- .replace( /development-bundle\/themes/, "css" )
- .replace( /css/, "themes" )
-
- // Make jquery-ui-1.10.0.custom.css into jquery-ui.css, or jquery-ui-1.10.0.custom.min.css into jquery-ui.min.css
- .replace( /jquery-ui-.*?(\.min)*\.css/, "jquery-ui$1.css" );
-
- return file;
- }).forEach( add );
- return callback();
- });
- };
- }).concat([function() {
- var crypto = require( "crypto" );
-
- // Create MD5 manifest
- output.push({
- path: "MANIFEST",
- data: output.sort(function( a, b ) {
- return a.path.localeCompare( b.path );
- }).map(function( file ) {
- var md5 = crypto.createHash( "md5" );
- md5.update( file.data );
- return file.path + " " + md5.digest( "hex" );
- }).join( "\n" )
- });
-
- downloadBuilder.util.createZip( output, targetZip, function( error ) {
- if ( error ) {
- abort( error.stack );
- }
- echo( "Built zip CDN package at " + path.relative( "../..", targetZip ).cyan );
- return callback();
- });
- }]));
-}
-
-function pushRelease() {
- echo( "Pushing release to GitHub..." );
- git( "push --tags", "Error pushing tags to GitHub." );
-}
-
-function updateBranchVersion() {
- // Pre-releases don't change the master version
- if ( preRelease ) {
- return;
- }
-
- var pkg;
-
- echo( "Checking out " + branch.cyan + " branch..." );
- git( "checkout " + branch, "Error checking out " + branch + " branch." );
-
- echo( "Updating package.json..." );
- pkg = readPackage();
- pkg.version = nextVersion;
- writePackage( pkg );
-
- echo( "Committing version update..." );
- git( "commit -am 'Updating the " + branch + " version to " + nextVersion + ".'",
- "Error committing package.json." );
-}
-
-function pushBranch() {
- // Pre-releases don't change the master version
- if ( preRelease ) {
- return;
- }
-
- echo( "Pushing " + branch.cyan + " to GitHub..." );
- git( "push", "Error pushing to GitHub." );
-}
-
-function generateChangelog() {
- if ( preRelease ) {
- return;
- }
-
- var commits,
- changelogPath = baseDir + "/changelog",
- changelog = cat( "build/release/changelog-shell" ) + "\n",
- fullFormat = "* %s (TICKETREF, [%h](http://github.com/jquery/jquery-ui/commit/%H))";
-
- changelog = changelog.replace( "{title}", "jQuery UI " + newVersion + " Changelog" );
-
- echo ( "Adding commits..." );
- commits = gitLog( fullFormat );
-
- echo( "Adding links to tickets..." );
- changelog += commits
- // Add ticket references
- .map(function( commit ) {
- var tickets = [];
- commit.replace( /Fixe[sd] #(\d+)/g, function( match, ticket ) {
- tickets.push( ticket );
- });
- return tickets.length ?
- commit.replace( "TICKETREF", tickets.map(function( ticket ) {
- return "[#" + ticket + "](http://bugs.jqueryui.com/ticket/" + ticket + ")";
- }).join( ", " ) ) :
- // Leave TICKETREF token in place so it's easy to find commits without tickets
- commit;
- })
- // Sort commits so that they're grouped by component
- .sort()
- .join( "\n" ) + "\n";
-
- echo( "Adding Trac tickets..." );
- changelog += trac( "/query?milestone=" + newVersion + "&resolution=fixed" +
- "&col=id&col=component&col=summary&order=component" ) + "\n";
-
- fs.writeFileSync( changelogPath, changelog );
- echo( "Stored changelog in " + changelogPath.cyan + "." );
-}
-
-function gatherContributors() {
- if ( preRelease ) {
- return;
- }
-
- var contributors,
- contributorsPath = baseDir + "/contributors";
-
- echo( "Adding committers and authors..." );
- contributors = gitLog( "%aN%n%cN" );
-
- echo( "Adding reporters and commenters from Trac..." );
- contributors = contributors.concat(
- trac( "/report/22?V=" + newVersion + "&max=-1" )
- .split( rnewline )
- // Remove header and trailing newline
- .slice( 1, -1 ) );
-
- echo( "Sorting contributors..." );
- contributors = unique( contributors ).sort(function( a, b ) {
- return a.toLowerCase() < b.toLowerCase() ? -1 : 1;
- });
-
- echo ( "Adding people thanked in commits..." );
- contributors = contributors.concat(
- gitLog( "%b%n%s" ).filter(function( line ) {
- return (/thank/i).test( line );
- }));
-
- fs.writeFileSync( contributorsPath, contributors.join( "\n" ) );
- echo( "Stored contributors in " + contributorsPath.cyan + "." );
-}
-
-function updateTrac() {
- echo( newVersion.cyan + " was tagged at " + tagTime.cyan + "." );
- if ( !preRelease ) {
- echo( "Close the " + newVersion.cyan + " Milestone." );
- }
- echo( "Create the " + newVersion.cyan + " Version." );
- echo( "When Trac asks for date and time, match the above. Should only change minutes and seconds." );
- echo( "Create a Milestone for the next minor release." );
-}
-
-
-
-
-
-// ===== HELPER FUNCTIONS ======================================================
-
-function git( command, errorMessage ) {
- var result = exec( "git " + command );
- if ( result.code !== 0 ) {
- abort( errorMessage );
- }
-
- return result.output;
-}
-
-function gitLog( format ) {
- var result = exec( "git log " + prevVersion + ".." + newVersion + " " +
- "--format='" + format + "'",
- { silent: true });
-
- if ( result.code !== 0 ) {
- abort( "Error getting git log." );
- }
-
- result = result.output.split( rnewline );
- if ( result[ result.length - 1 ] === "" ) {
- result.pop();
- }
-
- return result;
-}
-
-function trac( path ) {
- var result = exec( "curl -s 'http://bugs.jqueryui.com" + path + "&format=tab'",
- { silent: true });
-
- if ( result.code !== 0 ) {
- abort( "Error getting Trac data." );
- }
-
- return result.output;
-}
-
-function unique( arr ) {
- var obj = {};
- arr.forEach(function( item ) {
- obj[ item ] = 1;
- });
- return Object.keys( obj );
-}
-
-function readPackage() {
- return JSON.parse( fs.readFileSync( repoDir + "/package.json" ) );
-}
-
-function writePackage( pkg ) {
- fs.writeFileSync( repoDir + "/package.json",
- JSON.stringify( pkg, null, "\t" ) + "\n" );
-}
-
-function bootstrap( fn ) {
- getRemote(function( remote ) {
- if ( (/:/).test( remote ) || fs.existsSync( remote ) ) {
- repo = remote;
- } else {
- repo = "git@github.com:" + remote + ".git";
- }
- _bootstrap( fn );
- });
-}
-
-function getRemote( fn ) {
- var matches, remote;
-
- console.log( "Determining remote repo..." );
- process.argv.forEach(function( arg ) {
- matches = /--remote=(.+)/.exec( arg );
- if ( matches ) {
- remote = matches[ 1 ];
- }
- });
-
- if ( remote ) {
- fn( remote );
- return;
- }
-
- console.log();
- console.log( " !!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
- console.log( " !!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
- console.log( " !! !!" );
- console.log( " !! Using jquery/jquery-ui !!" );
- console.log( " !! !!" );
- console.log( " !!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
- console.log( " !!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
- console.log();
- console.log( "Press enter to continue, or ctrl+c to cancel." );
- prompt(function() {
- fn( "jquery/jquery-ui" );
- });
-}
-
-function _bootstrap( fn ) {
- console.log( "Determining release type..." );
- preRelease = process.argv.indexOf( "--pre-release" );
- if ( preRelease !== -1 ) {
- preRelease = process.argv[ preRelease + 1 ];
- console.log( "pre-release" );
- } else {
- preRelease = null;
- console.log( "stable release" );
- }
-
- console.log( "Determining directories..." );
- baseDir = process.cwd() + "/__release";
- repoDir = baseDir + "/repo";
-
- if ( fs.existsSync( baseDir ) ) {
- console.log( "The directory '" + baseDir + "' already exists." );
- console.log( "Aborting." );
- process.exit( 1 );
- }
-
- console.log( "Creating directory..." );
- fs.mkdirSync( baseDir );
-
- console.log( "Installing dependencies..." );
- require( "child_process" ).exec( "npm install shelljs colors download.jqueryui.com@1.10.8", function( error ) {
- if ( error ) {
- console.log( error );
- return process.exit( 1 );
- }
-
- require( "shelljs/global" );
- require( "colors" );
- downloadBuilder = require( "download.jqueryui.com" );
-
- fn();
- });
-}
-
-function section( name ) {
- return function() {
- echo();
- echo( "##" );
- echo( "## " + name.toUpperCase().magenta );
- echo( "##" );
- echo();
- };
-}
-
-function prompt( fn ) {
- process.stdin.once( "data", function( chunk ) {
- process.stdin.pause();
- fn( chunk.toString().trim() );
- });
- process.stdin.resume();
-}
-
-function confirm( fn ) {
- echo( "Press enter to continue, or ctrl+c to cancel.".yellow );
- prompt( fn );
-}
-
-function confirmReview( fn ) {
- echo( "Please review the output and generated files as a sanity check.".yellow );
- confirm( fn );
-}
-
-function abort( msg ) {
- echo( msg.red );
- echo( "Aborting.".red );
- exit( 1 );
-}
-
-function walk( methods ) {
- var method = methods.shift();
-
- function next() {
- if ( methods.length ) {
- walk( methods );
- }
- }
-
- if ( !method.length ) {
- method();
- next();
- } else {
- method( next );
- }
-}