libjxl

FORK: libjxl patches used on blog
git clone https://git.neptards.moe/blog/libjxl.git
Log | Files | Refs | Submodules | README | LICENSE

release.md (15075B)


      1 # libjxl release process
      2 
      3 This guide documents the release process for the libjxl project.
      4 
      5 libjxl follows the [semantic versioning](https://semver.org/spec/v2.0.0.html)
      6 specification for released versions. Releases are distributed as tags in the git
      7 repository with the semantic version prefixed by the letter "v". For example,
      8 release version "0.3.7" will have a git tag "v0.3.7".
      9 
     10 The public API is explicitly defined as C headers in the `lib/include`
     11 directory, normally installed in your include path. All other headers are
     12 internal API and are not covered by the versioning rules.
     13 
     14 ## Development and release workflow
     15 
     16 New code development is performed on the `main` branch of the git repository.
     17 Pre-submit checks enforce minimum build and test requirements for new patches
     18 that balance impact and test latency, but not all checks are performed before
     19 pull requests are merged. Several slower checks only run *after* the code has
     20 been merged to `main`, resulting in some errors being detected hours after the
     21 code is merged or even days after in the case of fuzzer-detected bugs.
     22 
     23 Release tags are cut from *release branches*. Each MAJOR.MINOR version has its
     24 own release branch, for example releases `0.7.0`, `0.7.1`, `0.7.2`, ... would
     25 have tags `v0.7.0`, `v0.7.1`, `v0.7.2`, ... on commits from the `v0.7.x` branch.
     26 `v0.7.x` is a branch name, not a tag name, and doesn't represent a released
     27 version since semantic versioning requires that the PATCH is a non-negative
     28 number. Released tags don't each one have their own release branch, all releases
     29 from the same MAJOR.MINOR version will share the same branch. The first commit
     30 after the branch-off points between the main branch and the release branch
     31 should be tagged with the suffix `-snapshot` and the name of the next
     32 MAJOR.MINOR version, in order to get meaningful output for `git describe`.
     33 
     34 The main purpose of the release branch is to stabilize the code before a
     35 release. This involves including fixes to existing bugs but **not** including
     36 new features. New features often come with new bugs which take time to fix, so
     37 having a release branch allows us to cherry-pick *bug fixes* from the `main`
     38 branch into the release branch without including the new *features* from `main`.
     39 For this reason it is important to make small commits in `main` and separate bug
     40 fixes from new features.
     41 
     42 After the initial minor release (`MAJOR.MINOR.PATCH`, for example `0.5.0`) the
     43 release branch is used to continue to cherry-pick fixes to be included in a
     44 patch release, for example a version `0.5.1` release. Patch fixes are only meant
     45 to fix security bugs or other critical bugs that can't wait until the next major
     46 or minor release.
     47 
     48 Release branches *may* continue to be maintained even after the next minor or
     49 major version has been released to support users that can't update to a newer
     50 minor release. In that case, the same process applies to all the maintained
     51 release branches.
     52 
     53 A release branch with specific cherry-picks from `main` means that the release
     54 code is actually a version of the code that never existed in the `main` branch,
     55 so it needs to be tested independently. Pre-submit and post-submit tests run on
     56 release branches (branches matching `v*.*.x`) but extra manual checks should be
     57 performed before a release, specially if multiple bug fixes interact with each
     58 other. Take this into account when selecting which commits to include in a
     59 release. The objective is to have a stable version that can be used without
     60 problems for months. Having the latest improvements at the time the release tag
     61 is created is a non-goal.
     62 
     63 ## Creating a release branch
     64 
     65 A new release branch is needed before creating a new major or minor release,
     66 that is, a new release where the MAJOR or MINOR numbers are increased. Patch
     67 releases, where only the PATCH number is increased, reuse the branch from the
     68 previous release of the same MAJOR and MINOR numbers.
     69 
     70 The following instructions assume that you followed the recommended [libjxl git
     71 setup](developing_in_github.md) where `origin` points to the upstream
     72 libjxl/libjxl project, otherwise use the name of your upstream remote repository
     73 instead of `origin`.
     74 
     75 The release branch is normally created from the latest work in `main` at the
     76 time the branch is created, but it is possible to create the branch from an
     77 older commit if the current `main` is particularly unstable or includes commits
     78 that were not intended to be included in the release. The following example
     79 creates the branch `v0.5.x` from the latest commit in main (`origin/main`), if a
     80 different commit is to be used then replace `origin/main` with the SHA of that
     81 commit. Change the `v0.5.x` branch name to the one you are creating.
     82 
     83 ```bash
     84 git fetch origin main
     85 git push git@github.com:libjxl/libjxl.git origin/main:refs/heads/v0.5.x
     86 ```
     87 
     88 Here we use the SSH URL explicitly since you are pushing to the `libjxl/libjxl`
     89 project directly to a branch there. If you followed the guide `origin` will have
     90 the HTTPS URL which wouldn't normally let you push since you wouldn't be
     91 authenticated. The `v*.*.x` branches are [GitHub protected
     92 branches](https://docs.github.com/en/github/administering-a-repository/defining-the-mergeability-of-pull-requests/about-protected-branches)
     93 in our repository, however you can push to a protected branch when *creating* it
     94 but you can't directly push to it after it is created. To include more changes
     95 in the release branch see the "Cherry-picking fixes to a release" section below.
     96 
     97 ## Creating a merge label
     98 
     99 We use GitHub labels in Pull Requests to keep track of the changes that should
    100 be merged into a given release branch. For this purpose create a new label for
    101 each new MAJOR.MINOR release branch called `merge-MAJOR.MINOR`, for example,
    102 `merge-0.5`.
    103 
    104 In the [edit labels](https://github.com/libjxl/libjxl/issues/labels) page, click
    105 on "New label" and create the label. Pick your favorite color.
    106 
    107 Labels are a GitHub-only concept and are not represented in git. You can add the
    108 label to a Pull Request even after it was merged, whenever it is decided that
    109 the Pull Request should be included in the given release branch. Adding the
    110 label doesn't automatically merge it to the release branch.
    111 
    112 ## Update the versioning number
    113 
    114 The version number (as returned by `JxlDecoderVersion`) in the source code in
    115 `main` must match the semantic versioning of a release. After the release
    116 branch is created the code in `main` will only be included in the next major
    117 or minor release. Right after a release branch update the version targeting the
    118 next release. Artifacts from `main` should include the new (unreleased) version,
    119 so it is important to update it. For example, after the `v0.5.x` branch is
    120 created from main, you should update the version on `main` to `0.6.0`.
    121 
    122 To help update it, run this helper command (in a Debian-based system):
    123 
    124 ```bash
    125 ./ci.sh bump_version 0.6.0
    126 ```
    127 
    128 This will update the version in the following files:
    129 
    130  * `lib/CMakeLists.txt`
    131  * `lib/lib.gni`, automatically updated with
    132    `tools/scripts/build_cleaner.py --update`.
    133  * `debian/changelog` to create the Debian package release with the new version.
    134    Debian changelog shouldn't repeat the library changelog, instead it should
    135    include changes to the packaging scripts.
    136  * `.github/workflows/conformance.yml`
    137 
    138 If there were incompatible API/ABI changes, make sure to also adapt the
    139 corresponding section in
    140 [CMakeLists.txt](https://github.com/libjxl/libjxl/blob/main/lib/CMakeLists.txt#L12).
    141 
    142 ## Cherry-pick fixes to a release
    143 
    144 After a Pull Request that should be included in a release branch has been merged
    145 to `main` it can be cherry-picked to the release branch. Before cherry-picking a
    146 change to a release branch it is important to check that it doesn't introduce
    147 more problems, in particular it should run for some time in `main` to make sure
    148 post-submit tests and the fuzzers run on it. Waiting for a day is a good idea.
    149 
    150 Most of the testing is done on the `main` branch, so be careful with what
    151 commits are cherry-picked to a branch. Refactoring code is often not a good
    152 candidate to cherry-pick.
    153 
    154 To cherry-pick a single commit to a release branch (in this example to `v0.5.x`)
    155 you can run:
    156 
    157 ```bash
    158 git fetch origin
    159 git checkout origin/v0.5.x -b merge_to_release
    160 git cherry-pick -x SHA_OF_MAIN_COMMIT
    161 # -x will annotate the cherry-pick with the original SHA_OF_MAIN_COMMIT value.
    162 # If not already mentioned in the original commit, add the original PR number to
    163 # the commit, for example add "(cherry picked from PR #NNNN)".
    164 git commit --amend
    165 ```
    166 
    167 The `SHA_OF_MAIN_COMMIT` is the hash of the commit as it landed in main. Use
    168 `git log origin/main` to list the recent main commits and their hashes.
    169 
    170 Making sure that the commit message on the cherry-picked commit contains a
    171 reference to the original pull request (like `#NNNN`) is important. It creates
    172 an automatic comment in the original pull request notifying that it was
    173 mentioned in another commit, helping keep track of the merged pull requests. If
    174 the original commit was merged with the "Squash and merge" policy it will
    175 automatically contain the pull request number on the first line, if this is not
    176 the case you can amend the commit message of the cherry-pick to include a
    177 reference.
    178 
    179 Multiple commits can be cherry-picked and tested at once to save time. Continue
    180 running `git cherry-pick` and `git commit --amend` multiple times for all the
    181 commits you need to cherry-pick, ideally in the same order they were merged on
    182 the `main` branch. At the end you will have a local branch with multiple commits
    183 on top of the release branch.
    184 
    185 To update the version number, for example from v0.8.0 to v0.8.1 run this helper
    186 command (in a Debian-based system):
    187 
    188 ```bash
    189 ./ci.sh bump_version 0.8.1
    190 ```
    191 
    192 as described above and commit the changes.
    193 
    194 Finally, upload your changes to *your fork* like normal, except that when
    195 creating a pull request select the desired release branch as a target:
    196 
    197 ```bash
    198 git push myfork merge_to_release
    199 ```
    200 
    201 If you used the [guide](developing_in_github.md) `myfork` would be `origin` in
    202 that example. Click on the URL displayed, which will be something like
    203 
    204   `https://github.com/mygithubusername/libjxl/pull/new/merge_to_release`
    205 
    206 In the "Open a pull request" page, change the drop-down base branch from
    207 "base: main" (the default) to the release branch you are targeting.
    208 
    209 The pull request approval and pre-submit rules apply as with normal pull
    210 requests to the `main` branch.
    211 
    212 **Important:** When merging multiple cherry-picks use "Rebase and merge" policy,
    213 not the squash one since otherwise you would discard the individual commit
    214 message references from the git history in the release branch.
    215 
    216 ## Publishing a release
    217 
    218 Once a release tag is created it must not be modified, so you need to prepare
    219 the changes before creating the release. Make sure you checked the following:
    220 
    221  * The semantic version number in the release branch (see `lib/CMakeLists.txt`)
    222    matches the number you intend to release, all three MAJOR, MINOR and PATCH
    223    should match. Otherwise send a pull request to the release branch to
    224    update them.
    225 
    226  * The GitHub Actions checks pass on the release branch. Look for the green
    227    tick next to the last commit on the release branch. This should be visible
    228    on the branch page, for example: https://github.com/libjxl/libjxl/tree/v0.5.x
    229 
    230  * There no open fuzzer-found bugs for the release branch. The most effective
    231    way is to [run the fuzzer](fuzzing.md) on the release branch for a while. You
    232    can seed the fuzzer with corpus generated by oss-fuzz by [downloading
    233    it](https://google.github.io/oss-fuzz/advanced-topics/corpora/#downloading-the-corpus),
    234    for example `djxl_fuzzer` with libFuzzer will use:
    235    gs://libjxl-corpus.clusterfuzz-external.appspot.com/libFuzzer/libjxl_djxl_fuzzer
    236 
    237  * Manually check that images encode/decode ok.
    238 
    239  * Manually check that downstream projects compile with our code. Sometimes
    240    bugs on build scripts are only detected when other projects try to use our
    241    library. For example, test compiling
    242    [imagemagick](https://github.com/ImageMagick/ImageMagick) and Chrome.
    243 
    244 A [GitHub
    245 "release"](https://docs.github.com/en/github/administering-a-repository/releasing-projects-on-github/about-releases)
    246 consists of two different concepts:
    247 
    248  * a git "tag": this is a name (`v` plus the semantic version number) with a
    249    commit hash associated, defined in the git repository. Most external projects
    250    will use git tags or HTTP URLs to these tags to fetch the code.
    251 
    252  * a GitHub "release": this is a GitHub-only concept and is not represented in
    253    git other than by having a git tag associated with the release. A GitHub
    254    release has a given source code commit SHA associated (through the tag) but
    255    it *also* contains release notes and optional binary files attached to the
    256    release.
    257 
    258 Releases from the older GitLab repository only have a git tag in GitHub, while
    259 newer releases have both a git tag and a release entry in GitHub.
    260 
    261 To publish a release open the [New Release
    262 page](https://github.com/libjxl/libjxl/releases/new) and follow these
    263 instructions:
    264 
    265  * Set the "Tag version" as "v" plus the semantic version number.
    266 
    267  * Select the "Target" as your release branch. For example for a "v0.7.1"
    268    release tag you should use the "v0.7.x" branch.
    269 
    270  * Use the version number as the release title.
    271 
    272  * Copy-paste the relevant section of the [CHANGELOG.md](../CHANGELOG.md) to the
    273    release notes into the release notes. Add any other information pertaining
    274    the release itself that are not included in the CHANGELOG.md, although prefer
    275    to include those in the CHANGELOG.md file. You can switch to the Preview tab
    276    to see the results.
    277 
    278  * Finally click "Publish release" and go celebrate with the team. 🎉
    279 
    280  * The branch v0.7.x will be pushed to gitlab automatically, but make sure to
    281    manually push the *tag* of the release also to
    282    https://gitlab.com/wg1/jpeg-xl, by doing
    283 
    284 ```bash
    285 git push gitlab v0.7.1
    286 ```
    287 where `gitlab` is the remote `git@gitlab.com:wg1/jpeg-xl.git`. 
    288 
    289 ### How to build downstream projects
    290 
    291 ```bash
    292 docker run -it debian:bookworm /bin/bash
    293 
    294 apt update
    295 apt install -y clang cmake git libbrotli-dev nasm pkg-config ninja-build
    296 export CC=clang
    297 export CXX=clang++
    298 
    299 mkdir -p /src
    300 cd /src
    301 
    302 git clone --recurse-submodules --depth 1 -b v0.9.x \
    303   https://github.com/libjxl/libjxl.git
    304 git clone --recurse-submodules --depth 1 \
    305   https://github.com/ImageMagick/ImageMagick.git
    306 git clone --recurse-submodules --depth 1 \
    307   https://github.com/FFmpeg/FFmpeg.git
    308 
    309 cd /src/libjxl
    310 cmake -B build -G Ninja .
    311 cmake --build build -j`nproc`
    312 cmake --install build --prefix="/usr"
    313 
    314 cd /src/ImageMagick
    315 ./configure --with-jxl=yes
    316 # check for "JPEG XL --with-jxl=yes yes"
    317 make -j `nproc`
    318 ./utilities/magick -version
    319 
    320 cd /src/FFmpeg
    321 ./configure --disable-all --disable-debug --enable-avcodec --enable-avfilter \
    322   --enable-avformat --enable-libjxl --enable-encoder=libjxl \
    323   --enable-decoder=libjxl --enable-ffmpeg
    324 # check for libjxl decoder/encoder support
    325 make -j `nproc`
    326 ldd ./ffmpeg
    327 ./ffmpeg -version
    328 ```