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

docs: revise RELEASE_PROCESS.md #1086

Merged
299 changes: 232 additions & 67 deletions RELEASE_PROCESS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,86 +3,241 @@
## General Information

In the Open Component Model organization, the *main development* is done on the
`main` branch. Thus, the `main` branch is used to generate minor releases. The
*patch development* is done on dedicated release branches created for a
particular minor release.
`main` branch. Thus, the `main` branch is used to develop on the latest minor
version.

A release is generated by calling a specific `release` GitHub action. It is
The release process focuses on the creation of `release/<major>.<minor>` release
branches and the generation
of release tags based on these branches. Every release branch is used to
permanently track the development of a specific
minor release of the OCM project. Whenever there is a critical issue for a
specific minor release, a patch is `cherry-picked`
into the release branch and a new patch release for that given minor version is
created.

The release branches are initially created from the `main` branch via the GitHub
action [`Release Branch Creation`](./.github/workflows/release-branch.yaml).

A release is generated by calling a specific [
`release`](./.github/workflows/release.yaml) GitHub Action. It is
executed on the branch which should be released - regardless whether it is a
patch or a minor release. Based on the content of the branch, the release action
decides what has to be done (for further details, read the release workflow
section).
patch or a minor release.

In any case, a pre-release may be created by specifying a pre-release suffix for
the release action execution.
the release action execution. This will lead (for most use cases) to the
creation of a "Release Candidate" which can be tested
and delivered to end users willing to test the new release.

## Release Workflow

The content of a branch can be released by the GitHub `release` action. The name
of the release is based on the content of the file [`VERSION`](./VERSION) which
### Diagram

```mermaid
gitGraph TB:
commit id: "VERSION 0.17.0-dev"
commit id: "feat: some feature"
branch "releases/v0.17"
commit tag: "v0.17.0-rc.1" type: REVERSE
checkout main
commit id: "fix: hotfix bug" type: HIGHLIGHT
checkout releases/v0.17
cherry-pick id: "fix: hotfix bug"
commit tag: "v0.17.0-rc.2"
branch "releases/v0.17.0"
checkout "releases/v0.17.0"
commit id: "VERSION 0.17.0" tag:"v0.17.0"
checkout main
commit id: "VERSION 0.18.0-dev"
commit id: "fix: another hotfix" type: HIGHLIGHT
checkout releases/v0.17
cherry-pick id: "fix: another hotfix"
commit tag: "v0.17.1-rc.1"
branch "releases/v0.17.1"
checkout "releases/v0.17.1"
commit id: "VERSION 0.17.1" tag:"v0.17.1"
checkout main
commit id: "feat: another feature"
branch "releases/v0.18"
commit tag: "v0.18.0-rc.1"
```

### The Release Branch Creation / Cutoff

Every minor release starts with the creation of a release branch through [
`Release Branch Creation`](./.github/workflows/release-branch.yaml).

The version / minor of the release is based on the content of the file [
`VERSION`](./VERSION) which
is updated automatically said `release` action. During development, the
content of this file is the complete release name of the release currently under
development and the suffix `-dev` (e.g. `0.1.0-dev`). The content of this file
is used for generating the version information compiled into the ocm
executables.

If a release is created, the `-dev`-suffix is removed and an optional
pre-release suffix is appended to generate the name of the release (e.g. `0.1.0`
or `0.1.0-alpha1`) and to prepare a commit for the release which is used to
create a release tag.

Additionally, this commit will also add a new release note file
under [./docs/releasenotes](./docs/releasenotes). It is generated from the
appropriate draft release with the basic release name (e.g. `0.1.0`). After the
release is done, for final releases, a new commit is created to prepare the
development of the next release by adapting the [`VERSION`](./VERSION) file
again. Thereby, if the patch level is `0` (e.g. `0.1.0`), the minor version
number is increased (e.g. `0.2.0`). If the patch level is not zero (e.g.
`0.1.1`), the patch level is increased (e.g. `0.1.2`). This commit is pushed to
the branch for which you created the release, and it therefore contains the
release commit in its history.

When creating a minor release, it is possible to optionally create a patch
branch. In this case, a new branch with the name `releases/<release-name>` is
created. This branch is prepared with a commit which adjusts the patch level in
the [`VERSION`](./VERSION) file to `1` (e.g. for release `0.1.0`, the patch
branch is prepared with `0.1.1`).

## Creating a Release

A release is created for a branch - typically, the main branch or a patch
branch - by executing the GitHub action `release`. Therefore, you have to
specify the branch to release, and you can optionally indicate to create a patch
branch or to create a pre-release by specifying a pre-release name.

By default one should always create a draft release first (as a Release Candidate),
open it up for testing (by communicating the new release candidate as available to stakeholders),
and after a grace period, promote the draft release to a full release. It is usually worth to always create
a release branch, since it is a good practice to have a stable branch for each release that can be separated from main
and tested and cherry-picked on separately.

## Preparing a Patch Release

There are 2 possibilities to create and release patches.

1) If during the creation of a minor release the option to create patch branch
has been selected, there is already a patch branch `releases/<minor-release>`
which can be used to prepare commits to be released.
2) If no patch branch has been created in advance for any existing minor
release, a patch branch can be created using the GitHub action
`release-branch`. Therefore, you have to select the tag of the intended
release. As a result, the patch branch `releases/<minor-release>` is prepared
with the appropriate version file (containing `x.<minor-release>.1-dev`).

> **NOTE**:
> If this is not possible because the release is older than the latest
version of the release action, then you have to
> manually specify the intended tag in the input field of the action.

On the patch branch (like on the main branch), new commits can be added using
pull requests. Once a patch should be released, the release action is executed
on the patch branch (theoretically, for patches, pre-releases are also
possible).
The release branch is then created with the following steps:

1. `main` is checked out and the [`VERSION`](./VERSION) file is read.
2. The combination of `<major>.<minor>` is read from [`VERSION`](./VERSION) and used to create
the branch name, e.g. `release/0.17`.
3. The branch is created and pushed to the repository.
4. A Pull Request is created by a bot to bump the [`VERSION`](./VERSION) file on `main` to
the next minor version, e.g. `0.18.0-dev`.

At this point in time we call the minor release `0.17` cut-off.

This means that:

- We no longer accept features for the development of this branch
- We no longer accept breaking changes for the development of this branch
- Any change that is not a bug fix or a documentation change must be approved by
the release manager
- Any bug fix that is not deemed critical must be approved by the release
manager
jakobmoellerdev marked this conversation as resolved.
Show resolved Hide resolved
- Any bug fix must first be merged to main and then [
`cherry-picked`](https://git-scm.com/docs/git-cherry-pick) to the release
branch.

At this point in time, any release targeted on this branch will have this minor
version as a base.

### Preparing a Minor release candidate

After the cut-off, the release manager will usually prepare a release candidate.
This is done by creating a pre-release on the release branch, that goes along
with a qualifying suffix.

Currently we only use one form of suffixed, pre-release, the
`Release Candidate`: Any Release Candidate
is testable by users and signalled in the form of
`<major>.<minor>.<patch>-rc.<rc-number>`.

If a release candidate is created, the `-dev`-suffix is removed and the suffix
`-rc.<rc-number>` is appended to generate the name of the release.

During the release, just before creating the git tag for a release,
the [VERSION](./VERSION) file is changed to include this new suffix.
The transformation thus looks like

```text
<major>.<minor>.<patch>-dev -> <major>.<minor>.<patch>-rc.<rc-number>
```

TODO: Currently all releases are created via tag only, so the VERSION bump
that is needed for the release is done through a dangling commit (a commit
that is not part of the history of any branch in the repository). This is not
ideal and should be changed in the future.
See [this issue](https://github.com/open-component-model/ocm/issues/1099)
for details.

### Creating a Minor release

Once a release candidate is seen as sufficiently tested, the release manager can
frewilhelm marked this conversation as resolved.
Show resolved Hide resolved
promote the release candidate to a full release.

By default one should always create a draft release first (as a Release
Candidate),
open it up for testing (by communicating the new release candidate as available
to stakeholders),
and after a grace period, promote the draft release to a full release.

This promotion is currently effectively a full rebuild from the release branch,
with the difference that the `-rc.<rc-number>` suffix is removed.

After the build, instead of finishing, the [
`release`](./.github/workflows/release.yaml) GitHub Action will also publish the
release.

This publishing to package registries (such as brew) is delegated to [
`publish-to-other-than-github`](./.github/workflows/publish-to-other-than-github.yaml)

After the official release on a release branch was successful, the version is considered `burned`.
This means that, even if bugs are found for that release in the future, a
`patch` release will be created for that release branch.

Concretely this means that the following additional steps are taken:

1. The release is tagged with the version number from the [`VERSION`](./VERSION)
file, *without* the `-rc.<rc-number>` suffix.
2. The release is published on GitHub as the latest release, not as a
pre-release.
3. The release is published to the package registries.
4. The [`VERSION`](./VERSION) is bumped in the release branch to the next <patch>,
e.g. `0.17.0-dev` becomes `0.17.1-dev` via Pull Request.

### Creating a Patch release

The process to creating a patch release is almost equivalent to the process of
creating a minor release.

Whenever a patch release in the form of `<major>.<minor>.<patch>` is needed, the
branch `releases/<major>.<minor>` is used to prepare the release.
The only difference is that now the VERSION file should contain the suffix
`<major>.<minor>.<patch>-dev`
(which should have automatically been bumped on the last release).

This means that creating candidates for the patch or creating the release is
equivalent by using the [`release`](./.github/workflows/release.yaml) GitHub
Action.
hilmarf marked this conversation as resolved.
Show resolved Hide resolved
Make sure that all patched commits have been cherry-picked from main.

*NOTE: It is not valid to create a fresh commit on a patch branch without a
corresponding cherry-pick from main.*

#### How to cherry-pick a commit from `main` to a `releases/x.y` branch

To cherry-pick a commit from `main` to a patch branch, the following steps are
necessary:

1. Checkout the release branch for the patch, e.g. `releases/0.17` for a patch
release of `0.17.0` towards `0.17.1`.
2. Cherry-pick the commit from `main` to the patch branch, e.g.
`git cherry-pick <commit-hash>`. Resolve conflicts as necessary.
3. Create a Pull-Request for the cherry-picked commit to the branch,
and prefix the title with `[releases/<major>.<minor>]` (in this case
`[releases/0.17]`)
to signal that this is a patch commit, e.g. with `gh`:

```shell
gh pr create \
--title "[releases/0.17] cherry-pick: <Original PR or Commit>" \
--body "Cherry-pick of <Original PR or Commit> from main to releases/0.17" \
--base releases/0.17 \
--draft
```

4. Merge the Pull-Request to the patch branch.

### How Release Notes are managed

For every release branch there is a Github Action
called [Release Drafter](./.github/workflows/release-drafter.yaml).
This workflow interprets the Pull Requests merged against main and the release
branches and generates a draft release
in Github which can be formed and edited.

Note that when you are updating the branches, the release notes currently get
overwritten from scratch so any edits get lost.
In case you want to permanently change the release notes, you will have to carry
them through all release candidates manually.
(TODO: this needs improvement by allowing us to do "append-only" style release
jakobmoellerdev marked this conversation as resolved.
Show resolved Hide resolved
notes, see [this issue](https://github.com/open-component-model/ocm/issues/1097) for details)

When a release is created, the release notes are copied to
the [./docs/releasenotes](./docs/releasenotes) folder in that branch
with a dedicated commit. If the release notes for that branch already exist in
the folder, the release notes are taken from the file
instead of the draft notes from GitHub. This means that you can also create a
Pull Request to the branch with the corresponding release notes
and it will be used for the release.
(TODO: Currently we have not decided if we want to permanently keep the notes
and thus need a PR to main to append them, or if we want to drop them in the
future. That's because they are currently needed to correctly manage notes
over multiple release candidates, see
[this issue](https://github.com/open-component-model/ocm/issues/1097)
for details.)

By default, this file is generated from the
appropriate draft release with the basic release name (e.g. `v0.1.0-rc.1.md`).

## What is part of a release?

Expand All @@ -96,3 +251,13 @@ various package managers (e.g. brew, debian or chocolatey) are created and
uploaded to the respective package repositories. All currently supported
installation methods are described
[here](https://github.com/open-component-model/ocm?tab=readme-ov-file#installation).

### Addendum

This release process got rewritten as of 0.19.0 and thus earlier releases
followed another model where release branches
were kept in the form of `releases/<major>.<minor>.<patch>` and the release
branches were created on demand.
This model has now largely been replaced by the model we see in
this document. However you might still encounter leftovers form the old model
and you are encouraged to create issues regarding inconsistencies.
Loading