Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automate release preparation process #1710

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/ISSUE_TEMPLATE/release_prep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: "Release prep (Admin only)"
description: Trigger release preparation workflow
title: "x.y.z"
labels: ["release-prep"]

body:
- type: markdown
attributes:
value: |
Replace the **title** with the version number of the release you are preparing (stick to the format `x.y.z`) and Submit the issue.

You can leave the body of the issue empty.
71 changes: 71 additions & 0 deletions .github/workflows/release-prep.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Prep Heat Release

on:
issues:
types: [opened]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using a workflow_dispatch trigger might be a better option.

  1. No need to create an issue. Workflow can be triggered manually with a button.
  2. Version number can be provided as input, no need to parse it from the title.
  3. No unnecessary action triggers every time an issue is created.

More on this: https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-workflow-runs/manually-running-a-workflow

env:
working_branch: workflows/release-prep

permissions:
contents: write
pull-requests: write

jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
with:
egress-policy: audit

- uses: actions/checkout@v3
- name: Extract Version Information
id: extract-version
if: contains(github.event.issue.labels.*.name, 'release-prep')
run: |
issue_title="${{ github.event.issue.title }}"
major=$(echo "$issue_title" | cut -d '.' -f 1)
minor=$(echo "$issue_title" | cut -d '.' -f 2)
micro=$(echo "$issue_title" | cut -d '.' -f 3)
echo "major=$major" >> $GITHUB_OUTPUT
echo "minor=$minor" >> $GITHUB_OUTPUT
echo "micro=$micro" >> $GITHUB_OUTPUT
- name: Delete Existing Version Update Branch
run: git push --delete origin ${{ env.working_branch }} || true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When is this branch created, or where does it come from?

- name: Create Release Branch
if: steps.extract-version.outputs.micro == 0
run: |
git checkout -b release/${{ steps.extract-version.outputs.major }}.${{ steps.extract-version.outputs.minor }}.x
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add an extra git checkout main; git pull to make sure we are branching of the most recent version of main.

git push origin release/${{ steps.extract-version.outputs.major }}.${{ steps.extract-version.outputs.minor }}.x
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In keeping with git-flow style branches, I would call this "pre-release/x.y.z". Based on this link, "main" is would be "release" in our case, "develop" is "main", and we could name "release/x.y.z" as "pre-release/x.y.z".

- name: Bump Version
if: always()
run: |
git fetch origin
git checkout release/${{ steps.extract-version.outputs.major }}.${{ steps.extract-version.outputs.minor }}.x
git checkout -b ${{ env.working_branch }}
git push origin ${{ env.working_branch }}
sed -i "s/major: int = \([0-9]\+\)/major: int = ${{ steps.extract-version.outputs.major }}/g" heat/core/version.py
sed -i "s/minor: int = \([0-9]\+\)/minor: int = ${{ steps.extract-version.outputs.minor }}/g" heat/core/version.py
sed -i "s/micro: int = \([0-9]\+\)/micro: int = ${{ steps.extract-version.outputs.micro }}/g" heat/core/version.py
sed -i "s/extension: str = .*/extension: str = None/g" heat/core/version.py
- name: Create PR from branch
uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5
with:
base: release/${{ steps.extract-version.outputs.major }}.${{ steps.extract-version.outputs.minor }}.x
branch: ${{ env.working_branch }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The base branch should be "release", and the branch should be our newly created branch, right? "pre-release/x.y.z"

delete-branch: true
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: Bump version to ${{ steps.extract-version.outputs.major }}.${{ steps.extract-version.outputs.minor }}.${{ steps.extract-version.outputs.micro }}
title: Prepare for Heat release ${{ steps.extract-version.outputs.major }}.${{ steps.extract-version.outputs.minor }}.${{ steps.extract-version.outputs.micro }}
body: |
Preparation steps before releasing a new version
Issue/s resolved: #${{ github.event.issue.number }}
TODO:
- [x] Update version.py
- [ ] update the Requirements section on README.md if needed
- [ ] Update CITATION.cff if needed
Auto-generated by [create-pull-request][1]
[1]: https://github.com/peter-evans/create-pull-request
labels: chore
draft: false
115 changes: 25 additions & 90 deletions RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,75 +3,32 @@
These are basic instructions for internal use. Will be expanded as the need arises.

### Table of Contents
- [Major or minor release](#major-or-minor-release)
- [Patch release](#patch-release)
- [GitHub and PyPi release](#github-and-pypi-release)
- [conda-forge build](#conda-forge-build)

### Major or minor release

(e.g. 1.4 --> 1.5, or 1.5 --> 2.0)

In the following, we assume we are about to release Heat v1.5.0.
### GitHub and PyPi release

**PRE-REQUISITES:**

- You need [PyPi](https://pypi.org/), [Test.PyPi](https://test.pypi.org/) account
- All intended PRs are merged, all tests have passed, and the `main` branch is ready for release.

1. We will release all new features in the development branch `main`. Branch off `main` to create a new release branch, e.g.:

```bash
git checkout main
git pull
git checkout -b release/1.5.x
```

2. Create a new branch off `release/1.5.x` and update the version number in `heat/core/version.py`:

```bash
git checkout release/1.5.x
git pull
git checkout -b workflows/version-update
```

- You have accounts on [PyPi](https://pypi.org/), [Test.PyPi](https://test.pypi.org/)
- All intended PRs are merged, all tests have passed.

1. Trigger the release preparation workflow by creating a new issue with the title `x.y.z` (stick to the format `x.y.z`), and label it with `release-prep`. You can use the "Release prep" template (TODO: ADD LINK).

Update `heat/core/version.py` like this:
Submit the issue. This will create a new PR with the version number updated in `heat/core/version.py`.

```python
"""This module contains Heat's version information."""

major: int = 1
"""Indicates Heat's main version."""
minor: int = 4 # <-- update to 5
"""Indicates feature extension."""
micro: int = 2 # <-- update to 0
"""Indicates revisions for bugfixes."""
extension: str = "dev" # <-- set to None
"""Indicates special builds, e.g. for specific hardware."""
```
2. Go through the checklist in the PR, get approval, and merge.

3. Commit and push new `version.py` in `workflows/version-update`.

4. If necessary, also update the Requirements section on README.md to reflect the latest version of the dependencies.

5. Update `CITATION.cff` if needed, i.e. add names of non-core contributors (they are included in the Release notes draft you just created). Push to `workflows/version-update`.

6. Create a pull request from `workflows/version-update` to `release/1.5.x`

- Remember to get a reviewers approval.
- Wait for the tests to finish.
- Squash and merge.

7. Draft release notes:
3. Draft release notes:

- Go to the GitHub repo's [Releases](https://github.com/helmholtz-analytics/heat/releases) page.
- The release notes draft is automated. Click on Edit Draft
- Select the new tag: v1.5.0. Modify Target branch: `release/1.5.x`
- Select the new tag and modify the target branch according to the release version (e.g. `release/1.5.x`)
- Edit release notes as needed (see older releases)
- Click on Save **but do not publish yet**

8. Build wheel in your local `heat/` directory, make sure you are on branch `release/1.5.x`.
4. Build wheel in your local `heat/` directory (make sure you are on the release branch, i.e. `release/1.5.x`!)

```bash
rm -f dist/*
Expand All @@ -80,26 +37,26 @@ extension: str = "dev" # <-- set to None

You might have to install the `build` package first (i.e. with `conda install -c conda-forge build` or `pip install build`)

9. Upload to Test PyPI and verify things look right. You need to install `twine` first.
5. Upload to Test PyPI and verify things look right (you may need to install `twine` first).

```bash
twine upload -r testpypi dist/*
```

`twine` will prompt for your username and password.

10. When everything works, upload to PyPI:
6. When you're sure everything works, release to PyPI:

```bash
twine upload dist/*
```

11. Go back to the Release Notes draft and publish them. The new release is out!
7. Go back to the Release Notes draft and publish them. The GitHub release is out!

- Make sure the CHANGELOG.md got updated, if not, call @JuanPedroGHM.
- Check our [Zenodo page](https://zenodo.org/doi/10.5281/zenodo.2531472) to make sure a DOI was created for the release.

12. On branch `main`, we want to modify the version so that `minor` is increased by 1, and `extension` is "dev". In this example we want the version on `main` to be:`1.6.0-dev`. We need to create a new branch from `main`:
8. On branch `main`, we want to modify the version so that `minor` is increased by 1, and `extension` is "dev". In this example we want the version on `main` to be:`1.6.0-dev`. We need to create a new branch from `main`:

```bash
git checkout main
Expand All @@ -110,40 +67,9 @@ extension: str = "dev" # <-- set to None

On branch `workflows/update-version-main`, modify `version.py` so that `minor` is increased by 1, and `extension` is `"dev"`. Commit and push the changes.

13. Create a PR with `main` as the base branch.

14. Get approval and merge. You're done! Except if you're a conda-forge maintainer, then see [conda-forge build](#conda-forge-build).


### Patch release

(e.g. 1.5.0 --> 1.5.1)

1. Check that all intended branches have been merged to the release branch you want to upgrade, in this example `release/1.5.x`. Create a new branch off `release/1.5.x`, e.g.:

```bash
git checkout release/1.5.x
git pull
git checkout -b workflows/version-update
```

2. Update `heat/core/version.py` like this:

```python
"""This module contains Heat's version information."""

major: int = 1
"""Indicates Heat's main version."""
minor: int = 5
"""Indicates feature extension."""
micro: int = 0 # <-- update to 1
"""Indicates revisions for bugfixes."""
extension: str = None
"""Indicates special builds, e.g. for specific hardware."""
```

3. Follow steps 3-14 from the [Major or minor release section](#major-or-minor-release).
9. Create a PR with `main` as the base branch.

10. Get approval and merge. You're done! Except if you're a conda-forge maintainer, then see [conda-forge build](#conda-forge-build).

## conda-forge build
After releasing, the conda-forge automation will create a new PR on https://github.com/conda-forge/heat-feedstock. It's normal if this takes hours. conda-forge maintainers will review the PR and merge it if everything is correct.
Expand All @@ -153,3 +79,12 @@ After releasing, the conda-forge automation will create a new PR on https://gith
- Make sure dependencies match.
- Once the PR is done, wait for the CI checks to finish and merge.
- Refer to the conda-forge docs if there are any issues: https://conda-forge.org/docs/maintainer/updating_pkgs.html#pushing-to-regro-cf-autotick-bot-branch

## easybuild @ JSC
TBD

## spack
TBD

## Docker
TBD