Releasinator

Problem

When automating an SDK release process, many teams and languages have different ideas. The release process is a hurdle that makes it hard for new project members to ramp up. One shouldn't have to read a release_process.md to release an open source SDK.

Solution

The releasinator corrects this by enforcing standard must-have release files, being configurable where necessary, and reducing the ramp-up hurdle.

Making it work

Install

  1. Clone this repo
  2. Run bundle install from terminal. It should download dependencies.

Setup

  1. Set the environment variable GITHUB_TOKEN with a generated personal access token with repo scope.

Usage

  1. cd to directory of the repo you'd like to release
  2. Run rake -t -f <path to releasinator>/Rakefile

Conventions

The releasinator enforces certain conventions. If a filename doesn't exactly match the convention, it is renamed to match, and automatically committed. The conventions are documented below:

  1. README.md
  2. LICENSE: See here for a relevant StackOverflow post on this discussion. This project has chosen to exclude the .txt extension to match other popular projects, and GitHub defaults.
  3. CONTRIBUTING.md: See a relevant GitHub blog post for relevant information. This project has chosen to include the .md extension, as these files can get a bit unwieldy without formatting.
  4. CHANGELOG.md - This file is the source of truth for the releasinator. The file should be organized with the most recent release on top, and formatted correctly. The latest release is the one used when the releasinator executes, so it is a precondition that the CHANGELOG.md has been edited and committed prior to releasing.
    1. Releases either are contained within an Alt-H2 (------) or ##H2 format. Any other format will be rejected.
    2. Each release MUST start with the release version, and may contain any following text, such as the date, and/or any release summary.

Behind the Scenes

Validations

  1. ✓ Validate git version.
  2. ✓ Validate git's cleanliness (no untracked, unstaged, or uncommitted files).
  3. ✓ Validate current git branch is up to date with the latest version on server.
  4. ✓ Validate current git branch is master (if no git flow), or develop or release/<Release number> if using git flow.
  5. ✓ Validate the presence of.gitignore, adding it if needed, and adding any needed lines.
  6. ✓ Validate the presence of the README.md file.
  7. ✓ Validate the presence of the CHANGELOG.md file.
  8. ✓ Validate the CHANGELOG.md file is properly formatted.
  9. ✓ Validate semver release number sequence in CHANGELOG.md. (Note: cannot detect duplicate versions, due to the underlying Hash implementation of the parsing library.)
  10. ✓ Validate the presence of LICENSE.
  11. ✓ Validate the presence of CONTRIBUTING.md.
  12. ✓ Validate the presence of .github/ISSUE_TEMPLATE.md.
  13. ✓ Validate LICENSE and CONTRIBUTING.md are referenced in README.md.
  14. ✓ Validate all submodules are up to date with the latest master version.
  15. ✓ Validate all files are committed to git (git ls-files --others --exclude-standard).
  16. ✓ Validate user has valid access_tokens as environment variables for all repos (public & enterprise). Public github requires GITHUB_TOKEN, while enterprise tokens add a modified version of their domain as a prefix. For example, github.example.com requires GITHUB_EXAMPLE_COM_GITHUB_TOKEN.
  17. ✓ Validate user has permissions to push to repo, and downstream repos.
  18. ✓ Validate anything as defined by the configuration. Examples:
    • Compiling with the right version of the platform.
    • Upstream library dependencies are the latest available.

Package manager credential management

  1. Validate permissions to publish to package manager
  2. If permissions are needed, retrieve them from the secret credential repo, and run any subsequent repo steps.

Performs internal-only tasks:

  1. ✓ Confirm user has completed all manual tasks (aka pre-release checklist).
  2. ✓ Confirm overwrite of local tags already matching version.
  3. ✓ Create local tag.
  4. ✓ Run build command, as specified in the config file.

Performs external-facing tasks:

  1. ✓ Clone/reset any downstream external distribution repos.
  2. ✓ Copy to destination repo:
* `README.md`
* `CHANGELOG.md`
* `LICENSE`
* `CONTRIBUTING.md`
* `.github/ISSUE_TEMPLATE.md`
* Any other distribution files.  This will be configured.
  1. ✓ Modify any dependency/versions in README.md, source, or sample apps to the latest version. The location and regex of these will be configured.
  2. ✓ Build code and/or Sample apps.

    • TODO If build fails, pause build and give developer a chance to fix the downstream build and retry without completely starting over.
  3. ✓ Push to appropriate package manager (nexus/cocoapods/composer/npm/nuget/rubygem/pypi).

  4. ✓ Confirm overwrite of remote tags already matching version.

  5. ✓ Create root and downstream repo tag and GitHub release. The name of the release is the tag, and the annotated description and GitHub release is the relevant section of the CHANGELOG.md.

  6. ✓ Create downstream GitHub branch.

  7. ✓ Correctly handle git flow branches and merging.

  8. ✓ Push to external repo (once live in external package manager).

  9. ✓ Create PRs into any downstream dependencies, including the release notes in the PR. Examples:

* Create a PR into Braintree when mSDK/OTC release.
* Create a PR into Cordova when mSDK release.
* Create a PR into any other framework that has a direct dependency on this repo.
  1. TODO add those same release notes within the release notes of the downstream repo.
  2. Assemble a draft of news, and publish (where possible, i.e. send email, tweet, whatever).

Open items:

Example build files