.. _developers_releases: Release flow ============ Open Forms periodically releases new versions - feature releases and/or bugfix releases. This document is intended for release managers preparing and pushing out a new release. .. _developers_releases_versioning: Versioning policy ----------------- Open Forms follows `semantic versioning `_. This means that we have versions ``MAJOR.minor.patch``, optionally suffixed with a pre-release identifier such as ``-beta.0`` or ``-rc.1``. Note that Open Forms itself has a version, and the API provided by Open Forms has its own version. API changes must also be judged based on semver and result in a matching version number change. This is tracked in the ``API_VERSION`` setting. See also the :ref:`developers_versioning`. Preparing a release ------------------- For new releases, a release branch is created, named: ``release/``. For minor and major releases, checkout from ``main``. For patch releases, checkout from ``stable/..x``. All release-related actions are concentrated in this branch. **Updating translation strings** Messages are localized/translated as part of the release process. There exists a wrapper script that automates this as much as possible: .. code-block:: bash ./bin/makemessages.sh This extracts the backend translations in the appropriate ``.po`` files and the JavaScript translations into the ``src/openforms/js/lang/[locale].json`` files. For the backend translations, you can use `Django Rosetta `_, which is located at ``http://localhost:8000/admin/rosetta``. You can filter on untranslated labels and add a translation. Make sure to also filter on 'fuzzy' and check if the generated translations make sense. Adjust them if needed and deselect the fuzzy checkbox when they are checked. Note that the translations in ``src/openforms/js/lang/formio/[locale].json`` cannot be automatically extracted and requires tedious manual checking and adding translations. **Re-recording the VCR cassettes** (Stable) minor and major releases must re-record the VCR cassettes to ensure that any feature that interacts with external APIs still works properly. Re-recording the cassettes forces the tests to talk to the real services again instead of replaying the recorded mock data, which can give a false sense of security. You may have to run subsets of the test suite separately, due to different integrations all configured on the same obfuscated URL (e.g. ``http://localhost:8080``), for example: .. code-block:: bash python src/manage.py test openforms.authentication.contrib.digid .. note:: One example of this is in appointments - ``mitmproxy`` is used and exposes the external service on ``http://localhost:8080``, but the Camunda tests also expect this URL to be available. The Camunda tests would fail here because the returned data is not compatible with the Camunda API at all. Camunda tests are skipped by default if the test code cannot connect to ``localhost:8080``, so you don't run into this issue usually. Instructions and (pointers to) credentials are documented in our internal Taiga. Delete the existing/recorded cassettes and then commit the results/changes. .. note:: Setting ``VCR_RECORD_MODE=all`` in your environment appends new episodes instead of overwriting them, which is not the desired result. **Updating the changelog** ``CHANGELOG.rst`` contains a summary of changes compared to the previous release. Use the new version followed by the (planned) release data as section title. You may group the changes in logical groups like "New features", "Bug fixes" etc. to enhance readability. Breaking changes should include a ``.. warning::`` section indicating any possibly manual actions required. Breaking (API) changes MUST result in a major version bump. Make sure to include references to the related Github issues. These *should* already be in the commit messages. Cheat sheet: get the commits since the previous version, which can be a starting point for the changelog entry: .. code-block:: bash git log ...HEAD \ --date=format:"%Y-%m-%d" \ --cherry \ --decorate=auto \ --pretty=format:"* %s %d" --reverse **Bumping the version** Use ``bump-my-version`` on the command line to manage the version number. It manages all files containing the version number. You can always see which options are available with: .. code-block:: bash bump-my-version show-bump Examples: .. code-block:: bash :caption: Bugfix release bump-my-version bump patch .. code-block:: bash :caption: Backwards compatible feature release bump-my-version bump minor .. code-block:: bash :caption: Backwards incompatible release bump-my-version bump major .. code-block:: bash :caption: Bump alpha -> beta -> release candidate bump-my-version bump pre_l .. code-block:: bash :caption: Bump build (alpha/beta/rc only) bump-my-version bump pre_n After bumping the version, verify and commit the changes: .. code-block:: bash git commit -am ":bookmark: Bumped version to " **Create a pull request** Push the release branch to Github, create a pull request and assign a peer for review. Publishing a release -------------------- Once the PR has been reviewed and approved, merge it to: * the ``main`` branch for minor and major releases * the ``stable/..x`` branch for patch releases. Then proceed to tagging the release. **Maintenance + Docker Hub preparation (new minor versions)** When a new minor version is released, the matching ``stable/..x`` needs to be created and pushed to Github. Any bugfixes that require backporting are done to these stable branches. Additionally, you need to register the stable branch in ``docker/ci/config.json`` under the ``supportedTags`` key, which is used as input for the Docker Hub README generation. **Tag the release** Git tags are crucial to the release and build process - any pushed git tag results in a build artifact with the same tag. Treat tags as immutable snapshots! Release managers should configure their environment to sign tags using GPG, see the `github documentation `_. Example: .. code-block:: bash git tag -s Make sure to add a meaningful annotation - the safest bet is to copy the changelog entry. This ensures the changes are also visible from the Github releases page. The CI workflow will ensure that a Docker image with the same release tag is published. **Create a PR with the changelog entries for the main branch** After publishing the release make sure to create a PR to the main branch with the newly added changelogs entries. **Announce the release in communication channels** This is to be fleshed out more, but some existing channels are: * Common Ground slack * commonground.nl * possible email subscribers **Forward port changelog for patch releases** For patch releases only, update the ``CHANGELOG.rst`` on the main branch with the new summary of changes. Order the entries by date (most recent first). If multiple patch versions are done on the same day, order them by version (most recent first). Stable releases and on-going development ---------------------------------------- Open Forms follows the one-flow branching model: the ``main`` branch is the main branch. Features and bugfixes are developed in separate branches (e.g. ``feature/foo`` and ``issue/bar``) with a pull request to ``main``. Supported stable (and upcoming) releases have their own branch following the pattern ``stable/..x``. Conforming to the :ref:`developers_releases_versioning`, bugfixes merged into ``main`` must be backported to the respective release branch(es). Pull requests with bugfixes must be tagged with the **needs-backport** label. The release branches are tested in CI as well. The person merging the pull request is responsible for making sure the fix ends up in the appropriate release branch as well. This can be done via: * cherry-picking the relevant commit(s) on the release branch and pushing to the release branch * creating a branch to cherry-pick the commit(s) on and make a pull request to the release branch The person merging the pull request is responsible for making sure the build on the release branch (still) passes. When backporting commits, please add tags to the resulting (cherry-picked) commits to cross reference everything. This should look something like: .. code-block:: none :bug: [#123] -- Fixed a Very Nasty bug Backport-Of: open-formulieren/open-forms#987 ...so that it points to the original bugfix PR. In the original bugfix PR, add a comment with the resulting backport commit hashes. You can decide to rebase multiple backport commits into a single one - as long as everything is linked together this is okay. Bundling of SDK inside Open Forms backend image ----------------------------------------------- The Open Forms backend image includes a version of the SDK for ease of deployment under the ``/static/sdk/`` prefix. The particular SDK version should be aligned with the backend version, which can be controlled through docker build args. To produce a backend image build of Open Forms version ``x.y.z`` with SDK version ``a.b.c``, the following steps must be performed in the right order: 1. Build the SDK version ``a.b.c.`` and ensure it is pushed to Docker Hub or otherwise available to the backend build environment. 2. Update the file ``.sdk-release`` in the backend repository with the version ``a.b.c`` 3. Specify ``--build-arg RELEASE=x.y.z`` and ``--build-arg SDK_RELEASE=a.b.c.`` for the backend image build. On CI, this happens automatically. 4. Build, tag and push the backend image. By default ``RELEASE`` and ``SDK_RELEASE`` are set to ``latest``, and if the SDK image is not available on the local filesystem, it will be pulled from Docker Hub. On CI, if the backend release is ``latest``, SDK release ``latest`` will be included. Otherwise, the release in the file ``.sdk-release`` is used. .. todo:: Set up the SDK and backend version compatibility matrix