Apipie/apipie-rails

View on GitHub
rel-eng/gem_release.ipynb

Summary

Maintainability
Test Coverage
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Release of apipie-rails gem\n",
    "\n",
    "### Requirements\n",
    "- push access to https://github.com/Apipie/apipie-rails\n",
    "- push access to rubygems.org for apipie-rails\n",
    "- sudo yum install python-slugify asciidoc\n",
    "- ensure neither the `git push` or `gem push` don't require interactive auth. If you can't use api key or ssh key to auth skip these steps and run them form the shell manually\n",
    "- ensure all checks have passed on the branch you're about to release\n",
    "\n",
    "### Release process\n",
    "- Follow the steps with `<Shift>+<Enter>` or `<Ctrl>+<Enter>,<Down>`\n",
    "- If anything fails, fix it and re-run the step if applicable\n",
    "\n",
    "### Release settings"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%autosave 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%cd .."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Update the following notebook settings"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "NEW_VERSION = '0.5.20'\n",
    "LAST_VERSION = '0.5.19'\n",
    "GIT_REMOTE_UPSTREAM = 'origin'\n",
    "STABLE_RELEASE = False\n",
    "WORK_BRANCH = 'stable' if STABLE_RELEASE else 'master'\n",
    "# Array of strings, e.g. [\"21cbsc214g3\", \"21casc214g3\"]\n",
    "CHERRY_PICKS = []\n",
    "GEMFILE='Gemfile.rails61'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ensure the repo is up to date"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! git checkout {WORK_BRANCH}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! git fetch {GIT_REMOTE_UPSTREAM}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! git rebase {GIT_REMOTE_UPSTREAM}/{WORK_BRANCH}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Cherry picks for stable release"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "if STABLE_RELEASE:\n",
    "    for cp in CHERRY_PICKS:\n",
    "        ! git cherry-pick -x {cp}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Run tests locally if your setup allows, otherwise ensure the HEAD is green"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! BUNDLE_GEMFILE=gemfiles/{GEMFILE} bundle update"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "! BUNDLE_GEMFILE=gemfiles/{GEMFILE} bundle exec rspec"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Update release related stuff"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! sed -i 's/VERSION = .*/VERSION = \"{NEW_VERSION}\"/' lib/apipie/version.rb"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Parse git changelog\n",
    "from IPython.display import Markdown as md\n",
    "from subprocess import check_output\n",
    "from shlex import split\n",
    "import re\n",
    "\n",
    "def format_log_entry(entry):\n",
    "    author = re.search(r'author:(.*)', entry).group(1)\n",
    "    entry = re.sub(r'author:(.*)', '', entry)\n",
    "    entry = re.sub(r'([fF]ixes|[rR]efs)[^-]*-\\s*(.*)', r'\\2', entry)\n",
    "    entry = '* ' + entry.capitalize()\n",
    "    entry = re.sub(r'\\(#([0-9]+)\\)', r'[#\\1](https://github.com/Apipie/apipie-rails/pull/\\1)', entry)\n",
    "    entry = entry + f'({author})'\n",
    "    return entry\n",
    "\n",
    "def skip(entry):\n",
    "    if re.match(r'Merge pull', entry) or \\\n",
    "      re.match(r'^i18n', entry) or \\\n",
    "      re.match(r'^Bump to version', entry):\n",
    "        return True\n",
    "    else:\n",
    "        return False \n",
    "git_log_cmd = 'git log --pretty=format:\"%%s author:%%an\" v%s..HEAD' % LAST_VERSION\n",
    "log = check_output(split(git_log_cmd)).decode('utf8').split('\\n')\n",
    "change_log = [format_log_entry(e) for e in log if not skip(e)]\n",
    "md('\\n'.join(change_log))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Write release notes\n",
    "from datetime import datetime\n",
    "import fileinput\n",
    "import sys\n",
    "\n",
    "fh = fileinput.input('CHANGELOG.md', inplace=True)  \n",
    "for line in fh:  \n",
    "    print(line.rstrip())\n",
    "    if re.match(r'========', line):\n",
    "        print('## [v%s](https://github.com/Apipie/apipie-rails/tree/v%s) (%s)' % (NEW_VERSION, NEW_VERSION, datetime.today().strftime('%Y-%m-%d')))\n",
    "        print('[Full Changelog](https://github.com/Apipie/apipie-rails/compare/v%s...v%s)' % (LAST_VERSION, NEW_VERSION))\n",
    "        for entry in change_log:\n",
    "            print(entry)\n",
    "        print('')\n",
    "fh.close()  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Manual step: Update deps in the gemspec if necessary"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Check what is going to be committed"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "! git add -u\n",
    "! git status"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "! git diff --cached"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Commit changes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "! git commit -m \"Bump to {NEW_VERSION}\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Tag new version"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! git tag {NEW_VERSION}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Build the gem"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! BUNDLE_GEMFILE=gemfiles/{GEMFILE} bundle exec rake build"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! gem push pkg/apipie-rails-{NEW_VERSION}.gem"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### PUSH the changes upstream If everything is correct"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! git push {GIT_REMOTE_UPSTREAM} {WORK_BRANCH}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! git push --tags {GIT_REMOTE_UPSTREAM} {WORK_BRANCH}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Now the new release is in upstream repo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Some manual steps follow to improve the UX\n",
    "\n",
    "#### New release on GitHub\n",
    "\n",
    "Copy the following changelog lines to the description in form on link below\n",
    "The release title is the new version."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('\\n')\n",
    "print('\\n'.join(change_log))\n",
    "print('\\n\\nhttps://github.com/Apipie/apipie-rails/releases/new?tag=%s' % NEW_VERSION)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Congratulations\n",
    "\n",
    "Release is public now."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}