Skip to content

Instantly share code, notes, and snippets.

@scottgonzalez
Last active December 15, 2015 06:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scottgonzalez/5215627 to your computer and use it in GitHub Desktop.
Save scottgonzalez/5215627 to your computer and use it in GitHub Desktop.
Proposal for grunt release process

The following is pseudo-code for a proposed grunt release task.

The task assumes that you're using git and the default remote is where the release should be pushed to.

There are safety checks to ensure a clean release, and the custom checks can be added by the project using the release task.

None of the following is a suggestion on naming, this is purely an overview of the way I think the release task should work.

The word "task" is heavily abused in the comments. These may not be tasks as defined in Grunt.

task( "release", function() {
  // Process the `version` option
  // Can be: major, minor, patch, build, or an explicit version number
  var version = option( "newversion" );
  
  // Determine the release type
  // This may be useful for custom tasks
  // For example, you want to perform different tasks for major and minor releases
  var releaseType = isSemver( version ) ? "explicit" : version;
  
  // Determine current version number
  // Useful for tasks like generating a changelog
  var prevVersion = getCurrentVersion();
  
  // Determine the new version number
  var newVersion = releaseType === "explicit" ? version : bumpVersion( prevVersion );
  
  // Create an object of release-related properties to pass to all tasks
  var settings = {
    previous: prevVersion,
    version: version,
    releaseType: releaseType
  };
  
  // Verify the repo is in a clean state
  // A release should only occur from a clean checkout
  if ( dirtyCheckout() ) {
    die();
  }
  
  // Run a task that verifies the status of the repo
  // This is async and defaults to a success state
  // If this fails, the whole process stops
  optionalHelper( "checkStatus", settings, cb );
  
  // Update package.json version
  // This should be smart and inspect package.json for indentation style
  updatePackageJson( version );
  
  // Run a task that performs any custom actions prior to the release
  // This is async and defaults to doing nothing
  // If this fails, the whole process stops
  // NOTE: package.json has the new version at this point, which is
  // useful if any other tasks will be reading from that instead of `settings`
  optionalHelper( "preprocessRelease", settings, cb );
  
  // Commit all changed files, use the version number as the message
  // Don't be stingy, `preprocessRelease` may have modified files as well.
  // Add all new/modified files.
  commitFilesToGit({ message: version });
  
  // Tag the release, use the version number, with the "v" prefix
  // This should be an annotated tag, not a lightweight tag
  // `npm version` will check npm config to determine if the tag should be signed,
  // this could do something similar, but at a minimum it should be annotated
  tag( "v" + version );
  
  // Push to the default remote
  push();
  pushTags();
  
  // Publish to npm, but only if requested
  if ( option( "npm" ) ) {
    publishToNpm();
  }
  
  // Display version info
  // Example: Version <version> was tagged at <date>
  showDetails();

Examples of checkStatus:

  • Linting
  • Running tests
  • Verifying status of AUTHORS.txt

Examples of preprocessRelease:

  • Generating changelog
  • Updating README

There should be a grunt-contrib plugin built on top of this which defines the common tasks for grunt-contrib-* plugins. For example, all contrib plugins should generate changelogs in the same format. Ideally contrib plugins would be able to load this higher-level plugin and get a release task with no configuration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment