From 813890b74e790b9e568ffb5b97aedb3ca7f282d4 Mon Sep 17 00:00:00 2001 From: Kira Evans Date: Fri, 17 Apr 2020 06:42:51 -0700 Subject: [PATCH] automate release process (#1138) * create auto-release script * update release guide * make requested changes * use outputs to capture body from file instead of bodyFromFile --- .github/workflows/make_release.yml | 66 ++++++++++++++++++++++++++++++ docs/developers/RELEASE.md | 61 ++++++++++----------------- 2 files changed, 88 insertions(+), 39 deletions(-) create mode 100644 .github/workflows/make_release.yml diff --git a/.github/workflows/make_release.yml b/.github/workflows/make_release.yml new file mode 100644 index 00000000000..6f990df1612 --- /dev/null +++ b/.github/workflows/make_release.yml @@ -0,0 +1,66 @@ +on: + push: + # Sequence of patterns matched against refs/tags + tags: + - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 + +name: Create Release + +jobs: + build: + name: Create Release + runs-on: ubuntu-latest + if: github.repository == 'napari/napari' + steps: + - name: Checkout code + uses: actions/checkout@master + - name: Install Python + uses: actions/setup-python@v1 + with: + python-version: 3.7 + - name: Install Dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + - name: Build Distribution + run: | + pip install wheel + python setup.py sdist bdist_wheel + - name: Find Release Notes + id: release_notes + run: | + TAG="${GITHUB_REF/refs\/tags\/v/}" # clean tag + VER="${TAG/rc*/}" # remove pre-release identifier + RELEASE_NOTES="$(cat docs/release/release_${VER//./_}.rst)" + # https://github.community/t5/GitHub-Actions/set-output-Truncates-Multiline-Strings/m-p/38372/highlight/true#M3322 + RELEASE_NOTES="${RELEASE_NOTES//'%'/'%25'}" + RELEASE_NOTES="${RELEASE_NOTES//$'\n'/'%0A'}" + RELEASE_NOTES="${RELEASE_NOTES//$'\r'/'%0D'}" + # https://help.github.com/en/actions/reference/workflow-commands-for-github-actions + echo "::set-env name=tag::$TAG" + echo "::set-output name=contents::$RELEASE_NOTES" + - name: Create Release + id: create_release + uses: actions/create-release@latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token + with: + tag_name: ${{ github.ref }} + release_name: ${{ env.tag }} + body: ${{ steps.release_notes.outputs.contents }} + draft: false + prerelease: ${{ contains(github.ref, 'rc') }} + - name: Upload Release Asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./dist/napari-${{ env.tag }}.tar.gz + asset_name: napari-${{ env.tag }}.tar.gz + asset_content_type: application/gzip + - name: Publish PyPI Package + uses: pypa/gh-action-pypi-publish@master + with: + user: __token__ + password: ${{ secrets.pypi_password }} diff --git a/docs/developers/RELEASE.md b/docs/developers/RELEASE.md index 348b29859de..cffc00bbb48 100644 --- a/docs/developers/RELEASE.md +++ b/docs/developers/RELEASE.md @@ -9,12 +9,22 @@ They will need to have a [PyPI](https://pypi.org) account with upload permission You will also need the additional `release` dependencies in `requirements/release.txt` to complete the release process. +> [`MANIFEST.in`](../MANIFEST.in) determines which non-Python files are included. +> Make sure to check that all necessary ones are listed before beginning the release process. + +The `napari/napari` repository must have a PyPI API token as a GitHub secret. +This likely has been done already, but if it has not, follow +[this guide](https://pypi.org/help/#apitoken) to gain a token and +[this guide](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets) +to add it as a secret. + ## determining the version The version of `napari` is automatically determined by [`versioneer`](https://github.com/warner/python-versioneer) from the latest [`git` tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging) beginning with `v`. Thus, you'll need to tag the [reference](https://git-scm.com/book/en/v2/Git-Internals-Git-References) with the new version number. It is likely something like `X.Y.Z`. Before making a release though we need to generate the release notes. + ## generating release notes 1. Review and cleanup ``docs/release/release_dev.md``. This may be empty if it has not been @@ -48,20 +58,20 @@ Thus, you'll need to tag the [reference](https://git-scm.com/book/en/v2/Git-Inte 8. Make and merge a PR with these release notes before moving onto the next steps. -## Tagging the new release candidate +## tagging the new release candidate First we will generate a release candidate, which will contain the letters `rc`. -Using release candidates allows us to test releases on PyPi without using up the actual +Using release candidates allows us to test releases on PyPI without using up the actual release number. -You should include a basic message with the tag `"Version X.Y.Zrc1"`: +You can tag the current source code as a release candidate with: ```bash -$ git tag -a vX.Y.Zrc1 -m "Version X.Y.Zrc1" master +$ git tag vX.Y.Zrc1 master ``` If the tag is meant for a previous version of master, simply reference the specific commit: ```bash -$ git tag -a vX.Y.Zrc1 -m "Version X.Y.Zrc1" abcde42 +$ git tag vX.Y.Zrc1 abcde42 ``` Note here how we are using `rc` for release candidate to create a version of our release we can test @@ -69,57 +79,30 @@ before making the real release. You can read more on tagging [here](https://git-scm.com/book/en/v2/Git-Basics-Tagging). -## creating the distribution - -Before creating a new distribution, make sure to delete any previous ones: -```bash -$ rm -rf dist build -``` +## testing the release candidate -Now you can build the distribution: +Our CI automatically makes a release, copying the release notes to the tag and uploading the distribution to PyPI. +You can trigger this by pushing the new tag to `napari/napari`: ```bash -$ python setup.py sdist bdist_wheel -``` - -[`MANIFEST.in`](../MANIFEST.in) determines which non-Python files are included. -Make sure to check that all necessary ones are listed before beginning the release process. - -## uploading the release candidate to PyPI - -Upload the release candidate with: -```bash -$ python -m twine upload dist/napari-X.Y.Zrc1.tar.gz +$ git push upstream --tags ``` The release candidate can then be tested with - ```bash $ pip install --pre napari ``` -or -```bash -$ pip install -U --pre napari -``` -if napari is already installed. +It is recommended that the release candidate is tested in a virtual environment in order to isolate dependencies. If the release candidate is not what you want, make your changes and repeat the process from the beginning but incrementing the number after `rc` on tag (e.g. `vX.Y.Zrc2`). Once you are satisfied with the release candidate it is time to generate the actual release. -## Generating the actual release +## generating the actual release To generate the actual release you will now repeat the processes above but now dropping the `rc`. For example: - -```bash -$ git tag -a vX.Y.Z -m "Version X.Y.Z" master -$ rm -rf dist build -$ python setup.py sdist bdist_wheel -$ python -m twine upload dist/napari-X.Y.Z.tar.gz -``` - -At the very end you should push the new tags to the repo. ```bash +$ git tag vX.Y.Z master $ git push upstream --tags ```