+++ /dev/null
-#!/bin/sh
-
-base_dir="`pwd`/jquery-ui-release"
-repo_dir="$base_dir/jquery-ui"
-release_dir="$repo_dir/build/release"
-
-github_repo="git@github.com:jquery/jquery-ui.git"
-remote_cmd="ssh jqadmin@ui-dev.jquery.com /srv/dev.jqueryui.com/prepare-release"
-
-
-
-#
-# Setup environment
-#
-
-echo
-echo "--------------------------"
-echo "| SETTING UP ENVIRONMENT |"
-echo "--------------------------"
-echo
-
-mkdir $base_dir
-cd $base_dir
-
-echo "Cloning repo from $github_repo..."
-git clone $github_repo
-cd $repo_dir
-
-echo
-echo "Environment setup complete."
-echo
-
-
-
-#
-# Figure out which versions we're dealing with
-#
-
-echo
-echo "------------------------"
-echo "| CALCULATING VERSIONS |"
-echo "------------------------"
-echo
-
-# NOTE: this will be different for minor and major releases
-version=`$remote_cmd/get-latest-version`
-major_minor=${version%.*}
-point=${version##*.}
-version_new="${major_minor}.$(($point + 1))"
-version_next=`cat version.txt`
-
-echo "We are going from $version to $version_new."
-echo "version.txt will be set to $version_next when complete."
-echo "Press enter to continue, or ctrl+c to cancel."
-read
-
-
-#
-# Generate shell for changelog
-#
-
-echo
-echo "------------------------"
-echo "| GENERATING CHANGELOG |"
-echo "------------------------"
-echo
-
-echo "Creating shell for changelog..."
-changelog_url="http:\/\/docs.jquery.com\/action\/edit\/UI\/Changelog\/$version_new"
-`sed "s/CHANGELOG_URL/$changelog_url/" <$release_dir/changelog-shell >$base_dir/changelog`
-
-
-# find all commits
-echo "Adding commits to changelog..."
-format_ticket='[http://dev.jqueryui.com/ticket/XXXX #XXXX]'
-format_commit='[http://github.com/jquery/jquery-ui/commit/%H %h]'
-format_full="* %s ($format_ticket, $format_commit)"
-git whatchanged $version... --pretty=format:"$format_full" \
- -- ui themes demos build \
-| sed '/^:/ d' \
-| sed '/^$/ d' \
-| sed 's/\(Fixe[sd] #\)\([0-9][0-9]*\)\(.*\)\(XXXX #XXXX\)/Fixed #\2\3\2 #\2/' \
-| LC_ALL='C' sort -f \
->> $base_dir/changelog
-
-# find all fixed tickets
-echo "Adding Trac tickets to changelog..."
-$remote_cmd/generate-changelog >> $base_dir/changelog
-
-echo
-echo "Changelog complete."
-echo
-
-
-
-#
-# Generate list of contributors
-#
-
-echo
-echo "--------------------------"
-echo "| GATHERING CONTRIBUTORS |"
-echo "--------------------------"
-echo
-
-
-# find all committers and authors
-echo "Adding commiters and authors..."
-format_contributors='%aN%n%cN'
-git whatchanged $version... --pretty=format:"$format_contributors" \
-| sed '/^:/ d' \
-| sed '/^$/ d' \
-> $base_dir/thankyou
-
-# find all reporters and commenters from Trac
-echo "Adding reporters and commenters from Trac..."
-$remote_cmd/generate-contributors >> $base_dir/thankyou
-
-# sort names
-echo "Sorting contributors..."
-LC_ALL='C' sort -f $base_dir/thankyou | uniq > $base_dir/_thankyou
-mv $base_dir/_thankyou $base_dir/thankyou
-
-# find all people that were thanked
-echo "Adding people thanked in commits..."
-git whatchanged $version... \
-| grep -i thank \
->> $base_dir/thankyou
-
-echo
-echo "Find contributors from duplicates of fixed tickets and add them to:"
-echo "$base_dir/thankyou"
-echo "Press enter when done."
-read
-
-echo
-echo "Contributors list complete."
-echo
-
-
-
-#
-# Update version
-#
-
-echo
-echo "--------------------"
-echo "| UPDATING VERSION |"
-echo "--------------------"
-echo
-
-echo "Updating version.txt to $version_new..."
-echo $version_new > version.txt
-
-git commit -a -m "Tagging the $version_new release."
-version_new_time=`git log -1 --pretty=format:"%ad"`
-echo "Committed version.txt at $version_new_time..."
-
-echo "Tagging $version_new..."
-git tag $version_new
-
-echo "Updating version.txt to $version_next..."
-echo $version_next > version.txt
-
-git commit -a -m "Updating the master version to $version_next"
-echo "Committed version.txt..."
-
-echo
-echo "Version update complete."
-echo
-
-
-
-#
-# Push to GitHub
-#
-
-echo
-echo "---------------------"
-echo "| PUSHING TO GITHUB |"
-echo "---------------------"
-echo
-
-echo "Please review the output and generated files as a sanity check."
-echo "Press enter to continue or ctrl+c to abort."
-read
-
-git push
-git push --tags
-
-echo
-echo "Push to GitHub complete."
-echo
-
-
-
-#
-# Update Trac
-#
-
-echo
-echo "-----------------"
-echo "| UPDATING TRAC |"
-echo "-----------------"
-echo
-
-# TODO: automate this
-# NOTE: this will be different for minor and major releases
-milestone=`$remote_cmd/get-latest-milestone`
-
-# Create new milestrone and version
-echo "$version_new was tagged at $version_new_time."
-echo "Create and close the $version_new Milestone with the above date and time."
-echo "Create the $version_new Version with the above date and time."
-echo "Press enter when done."
-read
-
-# Update milestone for all fixed tickets
-echo "Change all $milestone fixed tickets to $version_new."
-echo "Press enter when done."
-read
-
-echo
-echo "Trac updates complete."
-echo
-
-
-
-#
-# Build jQuery UI
-#
-
-echo
-echo "----------------------"
-echo "| BUILDING JQUERY UI |"
-echo "----------------------"
-echo
-
-# check out the tagged version
-echo "Checking out $version_new..."
-git checkout $version_new
-cd build
-
-# Update the link to the docs (never contains the patch version)
-echo "Updating URL for API docs..."
-sed "s/UI\/API\/\${release\.version}/UI\/API\/$major_minor/" build.xml >build.xml.tmp
-mv build.xml.tmp build.xml
-
-# Run the build
-echo "Running build..."
-ant
-
-echo
-echo "Build complete."
-echo
-
-
-
-#
-# Upload zip to Google Code
-#
-
-echo
-echo "----------------------"
-echo "| UPDATE GOOGLE CODE |"
-echo "----------------------"
-echo
-
-echo "Upload zip to Google Code."
-echo " http://code.google.com/p/jquery-ui/downloads/entry"
-echo " Summary: jQuery UI $version_new (Source, demos, docs, themes, tests) STABLE"
-echo " Labels: Featured, Type-Source, OpSys-All"
-echo "Modify the previous release to no longer say STABLE at the end."
-echo "Remove the featured label from the previous release."
-echo "Press enter when done."
-read
-
-echo
-echo "Google Code update complete."
-echo
-
-
-
-#
-# Update SVN
-#
-
-echo
-echo "----------------"
-echo "| UPDATING SVN |"
-echo "----------------"
-echo
-
-cd $base_dir
-mkdir svn
-cd svn
-
-echo "Checking out SVN tags..."
-svn co --depth immediates https://jquery-ui.googlecode.com/svn/tags
-cd tags
-
-echo "Unzipping build into tags/$version_new..."
-unzip $repo_dir/build/dist/jquery-ui-$version_new.zip
-mv jquery-ui-$version_new $version_new
-
-echo "Adding files to SVN..."
-svn add $version_new
-
-echo "Setting svn:mime-type..."
-find $version_new -name \*.js -exec svn propset svn:mime-type text/javascript {} \;
-find $version_new -name \*.css -exec svn propset svn:mime-type text/css {} \;
-find $version_new -name \*.html -exec svn propset svn:mime-type text/html {} \;
-find $version_new -name \*.png -exec svn propset svn:mime-type image/png {} \;
-find $version_new -name \*.gif -exec svn propset svn:mime-type image/gif {} \;
-
-# TODO: commit
-echo
-echo "svn commit with the following message:"
-echo "Created $version_new tag from http://jquery-ui.googlecode.com/files/jquery-ui-$version_new.zip"
-echo "Press enter when done."
-read
-
-echo
-echo "SVN update complete."
-echo
-
-
-
-#
-# Generate themes
-#
-
-
-
-
-# ruby -e 'puts File.read("thankyou").split("\n").join(", ")' > thankyou2
--- /dev/null
+#!/usr/bin/env node
+
+var baseDir, repoDir, prevVersion, newVersion, nextVersion, tagTime,
+ fs = require( "fs" ),
+ rnewline = /\r?\n/,
+ repo = "git@github.com:jquery/jquery-ui.git",
+ branch = "master";
+
+walk([
+ bootstrap,
+
+ section( "setting up repo" ),
+ cloneRepo,
+ checkState,
+
+ section( "calculating versions" ),
+ getVersions,
+ confirm,
+
+ section( "tagging release" ),
+ tagRelease,
+ confirm,
+ pushRelease,
+
+ section( "updating branch version" ),
+ updateBranchVersion,
+ confirm,
+ pushBranch,
+
+ section( "generating changelog" ),
+ generateChangelog,
+
+ section( "gathering contributors" ),
+ gatherContributors,
+
+ section( "updating trac" ),
+ updateTrac,
+ confirm,
+
+ section( "building release" ),
+ buildRelease
+]);
+
+
+
+
+
+function cloneRepo() {
+ if ( test( "-d", baseDir ) ) {
+ abort( "The directory '" + baseDir + "' already exists." );
+ }
+
+ echo( "Cloning " + repo + "..." );
+ git( "clone " + repo + " " + repoDir, "Error cloning repo." );
+ cd( repoDir );
+
+ echo( "Checking out " + branch + " branch..." );
+ git( "checkout " + branch, "Error checking out branch." );
+
+ echo( "Installing dependencies..." );
+ if ( exec( "npm install" ).code !== 0 ) {
+ abort( "Error installing dependencies." );
+ }
+}
+
+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 + "." );
+ echo( "Last actual author is " + lastActualAuthor + "." );
+ abort( "Please update AUTHORS.txt." );
+ }
+
+ echo( "Last listed author (" + lastListedAuthor + ") 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 + "." );
+ abort( "The version must be a pre version." );
+ }
+
+ 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 );
+ prevVersion = patch === 0 ?
+ [ major, minor - 1, 0 ].join( "." ) :
+ [ major, minor, patch - 1 ].join( "." );
+ // TODO: Remove version hack after 1.9.0 release
+ if ( prevVersion === "1.8.0" ) {
+ prevVersion = "1.8";
+ }
+ nextVersion = [ major, minor, patch + 1 ].join( "." ) + "pre";
+
+ echo( "We are going from " + prevVersion + " to " + newVersion + "." );
+ echo( "After the release, the version will be " + nextVersion + "." );
+}
+
+function tagRelease() {
+ var pkg;
+
+ echo( "Creating release branch..." );
+ git( "checkout -b release", "Error creating release branch." );
+
+ echo( "Updating package.json..." );
+ pkg = readPackage();
+ pkg.version = 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( "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( "Tagging release..." );
+ git( "tag " + newVersion, "Error tagging " + newVersion + "." );
+ tagTime = git( "log -1 --format='%ad'", "Error getting tag timestamp." ).trim();
+
+ echo();
+ echo( "Please review the output and generated files as a sanity check." );
+}
+
+function pushRelease() {
+ echo( "Pushing release to GitHub..." );
+ git( "push --tags", "Error pushing tags to GitHub." );
+}
+
+function updateBranchVersion() {
+ var pkg;
+
+ echo( "Checking out " + branch + " 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." );
+
+ echo();
+ echo( "Please review the output and generated files as a sanity check." );
+}
+
+function pushBranch() {
+ echo( "Pushing " + branch + " to GitHub..." );
+ git( "push", "Error pushing to GitHub." );
+}
+
+function generateChangelog() {
+ var commits,
+ changelogPath = baseDir + "/changelog",
+ changelog = cat( "build/release/changelog-shell" ) + "\n",
+ fullFormat = "* %s (TICKETREF, [http://github.com/jquery/jquery-ui/commit/%H %h])";
+
+ echo ( "Adding commits..." );
+ commits = gitLog( fullFormat );
+
+ echo( "Adding links to tickets..." );
+ changelog += commits
+ // Add ticket references
+ .map(function( commit ) {
+ var tickets = [];
+ // TODO: Don't use .replace() since we're not actually replacing
+ commit.replace( /Fixe[sd] #(\d+)/g, function( match, ticket ) {
+ tickets.push( ticket );
+ });
+ return tickets.length ?
+ commit.replace( "TICKETREF", tickets.map(function( ticket ) {
+ return "[http://bugs.jqueryui.com/ticket/" + 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 + "." );
+}
+
+function gatherContributors() {
+ 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 )
+ .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 + "." );
+}
+
+function updateTrac() {
+ echo( newVersion + " was tagged at " + tagTime + "." );
+ echo( "Close the " + newVersion + " Milestone with the above date and time." );
+ echo( "Create the " + newVersion + " Version with the above date and time." );
+ echo( "Create a Milestone for the next minor release." );
+}
+
+function buildRelease() {
+ echo( "Checking out " + newVersion + "..." );
+ git( "checkout " + newVersion, "Error checking out " + newVersion + "." );
+
+ echo( "Building release..." );
+ if ( exec( "grunt release" ).code !== 0 ) {
+ abort( "Error building 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 ) {
+ require( "child_process" ).exec( "npm root -g", function( error, stdout ) {
+ if ( error ) {
+ console.log( error );
+ return process.exit( 1 );
+ }
+
+ var rootDir = stdout.trim();
+ require( rootDir + "/shelljs/global" );
+
+ baseDir = pwd() + "/__release";
+ repoDir = baseDir + "/repo";
+
+ fn();
+ });
+}
+
+function section( name ) {
+ var line = new Array( name.length + 5 ).join( "-" );
+ return function() {
+ echo();
+ // https://github.com/arturadib/shelljs/issues/20
+ console.log( line );
+ echo( "| " + name.toUpperCase() + " |" );
+ console.log( line );
+ 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." );
+ prompt( fn );
+}
+
+function abort( msg ) {
+ echo( msg );
+ echo( "Aborting." );
+ exit( 1 );
+}
+
+function walk( methods ) {
+ var method = methods.shift();
+
+ function next( error ) {
+ if ( methods.length ) {
+ walk( methods );
+ }
+ }
+
+ if ( !method.length ) {
+ method();
+ next();
+ } else {
+ method( next );
+ }
+}