release.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. #!/usr/bin/env node
  2. /*
  3. * jQuery Core Release Management
  4. */
  5. // Debugging variables
  6. var debug = false,
  7. skipRemote = false;
  8. var fs = require("fs"),
  9. child = require("child_process"),
  10. path = require("path"),
  11. which = require("which").sync;
  12. var releaseVersion,
  13. nextVersion,
  14. finalFiles,
  15. isBeta,
  16. pkg,
  17. branch,
  18. scpURL = "jqadmin@code.origin.jquery.com:/var/www/html/code.jquery.com/",
  19. cdnURL = "http://code.origin.jquery.com/",
  20. repoURL = "git@github.com:dmethvin/jquery.git",
  21. //repoURL = "git@github.com:jquery/jquery.git",
  22. // Windows needs the .cmd version but will find the non-.cmd
  23. // On Windows, ensure the HOME environment variable is set
  24. gruntCmd = process.platform === "win32" ? "grunt.cmd" : "grunt",
  25. devFile = "dist/jquery.js",
  26. minFile = "dist/jquery.min.js",
  27. releaseFiles = {
  28. "jquery-VER.js": devFile,
  29. "jquery-VER.min.js": minFile,
  30. "jquery.js": devFile,
  31. "jquery-latest.js": devFile,
  32. "jquery.min.js": minFile,
  33. "jquery-latest.min.js": minFile
  34. };
  35. steps(
  36. initialize,
  37. checkGitStatus,
  38. tagReleaseVersion,
  39. gruntBuild,
  40. makeReleaseCopies,
  41. setNextVersion,
  42. uploadToCDN,
  43. pushToGithub,
  44. exit
  45. );
  46. function initialize( next ) {
  47. if ( process.argv[2] === "-d" ) {
  48. process.argv.shift();
  49. debug = true;
  50. console.warn("=== DEBUG MODE ===" );
  51. }
  52. // First arg should be the version number being released
  53. var newver, oldver,
  54. rversion = /^(\d)\.(\d+)\.(\d)((?:a|b|rc)\d|pre)?$/,
  55. version = ( process.argv[3] || "" ).toLowerCase().match( rversion ) || {},
  56. major = version[1],
  57. minor = version[2],
  58. patch = version[3],
  59. xbeta = version[4];
  60. branch = process.argv[2];
  61. releaseVersion = process.argv[3];
  62. isBeta = !!xbeta;
  63. if ( !branch || !major || !minor || !patch ) {
  64. die( "Usage: " + process.argv[1] + " branch releaseVersion" );
  65. }
  66. if ( xbeta === "pre" ) {
  67. die( "Cannot release a 'pre' version!" );
  68. }
  69. if ( !(fs.existsSync || path.existsSync)( "package.json" ) ) {
  70. die( "No package.json in this directory" );
  71. }
  72. pkg = JSON.parse( fs.readFileSync( "package.json" ) );
  73. console.log( "Current version is " + pkg.version + "; generating release " + releaseVersion );
  74. version = pkg.version.match( rversion );
  75. oldver = ( +version[1] ) * 10000 + ( +version[2] * 100 ) + ( +version[3] )
  76. newver = ( +major ) * 10000 + ( +minor * 100 ) + ( +patch );
  77. if ( newver < oldver ) {
  78. die( "Next version is older than current version!" );
  79. }
  80. nextVersion = major + "." + minor + "." + ( isBeta ? patch : +patch + 1 ) + "pre";
  81. next();
  82. }
  83. function checkGitStatus( next ) {
  84. child.execFile( "git", [ "status" ], {}, function( error, stdout, stderr ) {
  85. var onBranch = (stdout.match( /On branch (\S+)/ ) || [])[1];
  86. if ( onBranch !== branch ) {
  87. die( "Branches don't match: Wanted " + branch + ", got " + onBranch );
  88. }
  89. if ( /Changes to be committed/i.test( stdout ) ) {
  90. die( "Please commit changed files before attemping to push a release." );
  91. }
  92. if ( /Changes not staged for commit/i.test( stdout ) ) {
  93. die( "Please stash files before attempting to push a release." );
  94. }
  95. next();
  96. });
  97. }
  98. function tagReleaseVersion( next ) {
  99. updatePackageVersion( releaseVersion );
  100. git( [ "commit", "-a", "-m", "Tagging the " + releaseVersion + " release." ], function(){
  101. git( [ "tag", releaseVersion ], next);
  102. });
  103. }
  104. function gruntBuild( next ) {
  105. exec( gruntCmd, [], next );
  106. }
  107. function makeReleaseCopies( next ) {
  108. finalFiles = {};
  109. Object.keys( releaseFiles ).forEach(function( key ) {
  110. var builtFile = releaseFiles[ key ],
  111. releaseFile = key.replace( /VER/g, releaseVersion );
  112. // Beta releases don't update the jquery-latest etc. copies
  113. if ( !isBeta || key !== releaseFile ) {
  114. copy( builtFile, releaseFile );
  115. finalFiles[ releaseFile ] = builtFile;
  116. }
  117. });
  118. next();
  119. }
  120. function setNextVersion( next ) {
  121. updatePackageVersion( nextVersion );
  122. git( [ "commit", "-a", "-m", "Updating the source version to " + nextVersion ], next );
  123. }
  124. function uploadToCDN( next ) {
  125. var cmds = [];
  126. Object.keys( finalFiles ).forEach(function( name ) {
  127. cmds.push(function( x ){
  128. exec( "scp", [ name, scpURL ], x, skipRemote );
  129. });
  130. cmds.push(function( x ){
  131. exec( "curl", [ cdnURL + name + "?reload" ], x, skipRemote );
  132. });
  133. });
  134. cmds.push( next );
  135. steps.apply( this, cmds );
  136. }
  137. function pushToGithub( next ) {
  138. git( [ "push", "--tags", repoURL, branch ], next, skipRemote );
  139. }
  140. //==============================
  141. function steps() {
  142. var cur = 0,
  143. steps = arguments;
  144. (function next(){
  145. var step = steps[ cur++ ];
  146. step( next );
  147. })();
  148. }
  149. function updatePackageVersion( ver ) {
  150. console.log( "Updating package.json version to " + ver );
  151. pkg.version = ver;
  152. if ( !debug ) {
  153. fs.writeFileSync( "package.json", JSON.stringify( pkg, null, "\t" ) + "\n" );
  154. }
  155. }
  156. function copy( oldFile, newFile ) {
  157. console.log( "Copying " + oldFile + " to " + newFile );
  158. if ( !debug ) {
  159. fs.writeFileSync( newFile, fs.readFileSync( oldFile, "utf8" ) );
  160. }
  161. }
  162. function git( args, fn, skip ) {
  163. exec( "git", args, fn, skip );
  164. }
  165. function exec( cmd, args, fn, skip ) {
  166. if ( debug || skip ) {
  167. console.log( "# " + cmd + " " + args.join(" ") );
  168. fn();
  169. } else {
  170. console.log( cmd + " " + args.join(" ") );
  171. child.execFile( cmd, args, { env: process.env },
  172. function( err, stdout, stderr ) {
  173. if ( err ) {
  174. die( stderr || stdout || err );
  175. }
  176. fn();
  177. }
  178. );
  179. }
  180. }
  181. function die( msg ) {
  182. console.error( "ERROR: " + msg );
  183. process.exit( 1 );
  184. }
  185. function exit() {
  186. process.exit( 0 );
  187. }