{ "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 `+` or `+,`\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 }