summaryrefslogtreecommitdiff
path: root/media/libjxl/src/doc/release.md
diff options
context:
space:
mode:
Diffstat (limited to 'media/libjxl/src/doc/release.md')
-rw-r--r--media/libjxl/src/doc/release.md266
1 files changed, 266 insertions, 0 deletions
diff --git a/media/libjxl/src/doc/release.md b/media/libjxl/src/doc/release.md
new file mode 100644
index 0000000000..b1b903bb27
--- /dev/null
+++ b/media/libjxl/src/doc/release.md
@@ -0,0 +1,266 @@
+# libjxl release process
+
+This guide documents the release process for the libjxl project.
+
+libjxl follows the [semantic versioning](https://semver.org/spec/v2.0.0.html)
+specification for released versions. Releases are distributed as tags in the git
+repository with the semantic version prefixed by the letter "v". For example,
+release version "0.3.7" will have a git tag "v0.3.7".
+
+The public API is explicitly defined as C headers in the `lib/include`
+directory, normally installed in your include path. All other headers are
+internal API and are not covered by the versioning rules.
+
+## Development and release workflow
+
+New code development is performed on the `main` branch of the git repository.
+Pre-submit checks enforce minimum build and test requirements for new patches
+that balance impact and test latency, but not all checks are performed before
+pull requests are merged. Several slower checks only run *after* the code has
+been merged to `main`, resulting in some errors being detected hours after the
+code is merged or even days after in the case of fuzzer-detected bugs.
+
+Release tags are cut from *release branches*. Each MAJOR.MINOR version has its
+own release branch, for example releases `0.5`, `0.5.1`, `0.5.2`, ... would have
+tags `v0.5`, `v0.5.1`, `v0.5.2`, ... on commits from the `v0.5.x` branch.
+`v0.5.x` is a branch name, not a tag name, and doesn't represent a released
+version since semantic versioning requires that the PATCH is a non-negative
+number. Released tags don't each one have their own release branch, all releases
+from the same MAJOR.MINOR version will share the same branch.
+
+The main purpose of the release branch is to stabilize the code before a
+release. This involves including fixes to existing bugs but **not** including
+new features. New features often come with new bugs which take time to fix, so
+having a release branch allows us to cherry-pick *bug fixes* from the `main`
+branch into the release branch without including the new *features* from `main`.
+For this reason it is important to make small commits in `main` and separate bug
+fixes from new features.
+
+After the initial minor release (`M.N`, for example `0.5.0` or just `0.5`) the
+release branch is used to continue to cherry-pick fixes to be included in a
+patch release, for example a version `0.5.1` release. Patch fixes are only meant
+to fix security bugs or other critical bugs that can't wait until the next major
+or minor release.
+
+Release branches *may* continue to be maintained even after the next minor or
+major version has been released to support users that can't update to a newer
+minor release. In that case, the same process applies to all the maintained
+release branches.
+
+A release branch with specific cherry-picks from `main` means that the release
+code is actually a version of the code that never existed in the `main` branch,
+so it needs to be tested independently. Pre-submit and post-submit tests run on
+release branches (branches matching `v*.*.x`) but extra manual checks should be
+performed before a release, specially if multiple bug fixes interact with each
+other. Take this into account when selecting which commits to include in a
+release. The objective is to have a stable version that can be used without
+problems for months. Having the latest improvements at the time the release tag
+is created is a non-goal.
+
+## Creating a release branch
+
+A new release branch is needed before creating a new major or minor release,
+that is, a new release where the MAJOR or MINOR numbers are increased. Patch
+releases, where only the PATCH number is increased, reuse the branch from the
+previous release of the same MAJOR and MINOR numbers.
+
+The following instructions assume that you followed the recommended [libjxl git
+setup](developing_in_github.md) where `origin` points to the upstream
+libjxl/libjxl project, otherwise use the name of your upstream remote repository
+instead of `origin`.
+
+The release branch is normally created from the latest work in `main` at the
+time the branch is created, but it is possible to create the branch from an
+older commit if the current `main` is particularly unstable or includes commits
+that were not intended to be included in the release. The following example
+creates the branch `v0.5.x` from the latest commit in main (`origin/main`), if a
+different commit is to be used then replace `origin/main` with the SHA of that
+commit. Change the `v0.5.x` branch name to the one you are creating.
+
+```bash
+git fetch origin main
+git push git@github.com:libjxl/libjxl.git origin/main:refs/heads/v0.5.x
+```
+
+Here we use the SSH URL explicitly since you are pushing to the `libjxl/libjxl`
+project directly to a branch there. If you followed the guide `origin` will have
+the HTTPS URL which wouldn't normally let you push since you wouldn't be
+authenticated. The `v*.*.x` branches are [GitHub protected
+branches](https://docs.github.com/en/github/administering-a-repository/defining-the-mergeability-of-pull-requests/about-protected-branches)
+in our repository, however you can push to a protected branch when *creating* it
+but you can't directly push to it after it is created. To include more changes
+in the release branch see the "Cherry-picking fixes to a release" section below.
+
+## Creating a merge label
+
+We use GitHub labels in Pull Requests to keep track of the changes that should
+be merged into a given release branch. For this purpose create a new label for
+each new MAJOR.MINOR release branch called `merge-MAJOR.MINOR`, for example,
+`merge-0.5`.
+
+In the [edit labels](https://github.com/libjxl/libjxl/issues/labels) page, click
+on "New label" and create the label. Pick your favorite color.
+
+Labels are a GitHub-only concept and are not represented in git. You can add the
+label to a Pull Request even after it was merged, whenever it is decided that
+the Pull Request should be included in the given release branch. Adding the
+label doesn't automatically merge it to the release branch.
+
+## Update the versioning number
+
+The version number (as returned by `JxlDecoderVersion`) in the source code in
+`main` must match the semantic versioning of a release. After the release
+branch is created the code in `main` will only be included in the next major
+or minor release. Right after a release branch update the version targeting the
+next release. Artifacts from `main` should include the new (unreleased) version,
+so it is important to update it. For example, after the `v0.5.x` branch is
+created from main, you should update the version on `main` to `0.6`.
+
+To help update it, run this helper command (in a Debian-based system):
+
+```bash
+./ci.sh bump_version 0.6
+```
+
+This will update the version in the following files:
+
+ * `lib/CMakeLists.txt`
+ * `lib/lib.gni`, automatically updated with `tools/build_cleaner.py --update`.
+ * `debian/changelog` to create the Debian package release with the new version.
+ Debian changelog shouldn't repeat the library changelog, instead it should
+ include changes to the packaging scripts.
+
+If there were incompatible API/ABI changes, make sure to also adapt the
+corresponding section in
+[CMakeLists.txt](https://github.com/libjxl/libjxl/blob/main/lib/CMakeLists.txt#L12).
+
+## Cherry-pick fixes to a release
+
+After a Pull Request that should be included in a release branch has been merged
+to `main` it can be cherry-picked to the release branch. Before cherry-picking a
+change to a release branch it is important to check that it doesn't introduce
+more problems, in particular it should run for some time in `main` to make sure
+post-submit tests and the fuzzers run on it. Waiting for a day is a good idea.
+
+Most of the testing is done on the `main` branch, so be careful with what
+commits are cherry-picked to a branch. Refactoring code is often not a good
+candidate to cherry-pick.
+
+To cherry-pick a single commit to a release branch (in this example to `v0.5.x`)
+you can run:
+
+```bash
+git fetch origin
+git checkout origin/v0.5.x -b merge_to_release
+git cherry-pick -x SHA_OF_MAIN_COMMIT
+# -x will annotate the cherry-pick with the original SHA_OF_MAIN_COMMIT value.
+# If not already mentioned in the original commit, add the original PR number to
+# the commit, for example add "(cherry picked from PR #NNNN)".
+git commit --amend
+```
+
+The `SHA_OF_MAIN_COMMIT` is the hash of the commit as it landed in main. Use
+`git log origin/main` to list the recent main commits and their hashes.
+
+Making sure that the commit message on the cherry-picked commit contains a
+reference to the original pull request (like `#NNNN`) is important. It creates
+an automatic comment in the original pull request notifying that it was
+mentioned in another commit, helping keep track of the merged pull requests. If
+the original commit was merged with the "Squash and merge" policy it will
+automatically contain the pull request number on the first line, if this is not
+the case you can amend the commit message of the cherry-pick to include a
+reference.
+
+Multiple commits can be cherry-picked and tested at once to save time. Continue
+running `git cherry-pick` and `git commit --amend` multiple times for all the
+commits you need to cherry-pick, ideally in the same order they were merged on
+the `main` branch. At the end you will have a local branch with multiple commits
+on top of the release branch.
+
+Finally, upload your changes to *your fork* like normal, except that when
+creating a pull request select the desired release branch as a target:
+
+```bash
+git push myfork merge_to_release
+```
+
+If you used the [guide](developing_in_github.md) `myfork` would be `origin` in
+that example. Click on the URL displayed, which will be something like
+
+ `https://github.com/mygithubusername/libjxl/pull/new/merge_to_release`
+
+In the "Open a pull request" page, change the drop-down base branch from
+"base: main" (the default) to the release branch you are targeting.
+
+The pull request approval and pre-submit rules apply as with normal pull
+requests to the `main` branch.
+
+**Important:** When merging multiple cherry-picks use "Rebase and merge" policy,
+not the squash one since otherwise you would discard the individual commit
+message references from the git history in the release branch.
+
+## Publishing a release
+
+Once a release tag is created it must not be modified, so you need to prepare
+the changes before creating the release. Make sure you checked the following:
+
+ * The semantic version number in the release branch (see `lib/CMakeLists.txt`)
+ matches the number you intend to release, all three MAJOR, MINOR and PATCH
+ should match. Otherwise send a pull request to the release branch to
+ update them.
+
+ * The GitHub Actions checks pass on the release branch. Look for the green
+ tick next to the last commit on the release branch. This should be visible
+ on the branch page, for example: https://github.com/libjxl/libjxl/tree/v0.5.x
+
+ * There no open fuzzer-found bugs for the release branch. The most effective
+ way is to [run the fuzzer](fuzzing.md) on the release branch for a while. You
+ can seed the fuzzer with corpus generated by oss-fuzz by [downloading
+ it](https://google.github.io/oss-fuzz/advanced-topics/corpora/#downloading-the-corpus),
+ for example `djxl_fuzzer` with libFuzzer will use:
+ gs://libjxl-corpus.clusterfuzz-external.appspot.com/libFuzzer/libjxl_djxl_fuzzer
+
+ * Manually check that images encode/decode ok.
+
+ * Manually check that downstream projects compile with our code. Sometimes
+ bugs on build scripts are only detected when other projects try to use our
+ library. For example, test compiling
+ [imagemagick](https://github.com/ImageMagick/ImageMagick) and Chrome.
+
+A [GitHub
+"release"](https://docs.github.com/en/github/administering-a-repository/releasing-projects-on-github/about-releases)
+consists of two different concepts:
+
+ * a git "tag": this is a name (`v` plus the semantic version number) with a
+ commit hash associated, defined in the git repository. Most external projects
+ will use git tags or HTTP URLs to these tags to fetch the code.
+
+ * a GitHub "release": this is a GitHub-only concept and is not represented in
+ git other than by having a git tag associated with the release. A GitHub
+ release has a given source code commit SHA associated (through the tag) but
+ it *also* contains release notes and optional binary files attached to the
+ release.
+
+Releases from the older GitLab repository only have a git tag in GitHub, while
+newer releases have both a git tag and a release entry in GitHub.
+
+To publish a release open the [New Release
+page](https://github.com/libjxl/libjxl/releases/new) and follow these
+instructions:
+
+ * Set the "Tag version" as "v" plus the semantic version number. Omit the ".0"
+ when the PATCH version is 0, for example use "v0.5" or "v0.5.1" but not
+ "v0.5.0".
+
+ * Select the "Target" as your release branch. For a "v0.5" release tag you
+ would use the "v0.5.x" branch.
+
+ * Use the version number as the release title.
+
+ * Copy-paste the relevant section of the [CHANGELOG.md](../CHANGELOG.md) to the
+ release notes into the release notes. Add any other information pertaining
+ the release itself that are not included in the CHANGELOG.md, although prefer
+ to include those in the CHANGELOG.md file. You can switch to the Preview tab
+ to see the results.
+
+ * Finally click "Publish release" and go celebrate with the team. 🎉