Skip to content

Commit 851ea6e

Browse files
authored
Merge pull request #85 from LibreSign/docs/release-process-actionable-steps
docs(release): replace future planning sections with actionable checklist steps
2 parents 3751930 + 271a720 commit 851ea6e

File tree

1 file changed

+238
-14
lines changed

1 file changed

+238
-14
lines changed

developer_manual/release-process.rst

Lines changed: 238 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,48 @@ Release process
44
Resuming the steps:
55

66
1. Identify the next version number of all releases.
7-
2. Create the changelog of all branches that will be released.
8-
You will need to create the changelog in the :code:`CHANGELOG.md` file from the :code:`main` branch and then backport it to the stable branches.
9-
3. Make the necessary changes into the codebase to prepare the release.
7+
2. Collect and validate PRs from the commits since the previous release.
8+
3. Create the changelog for all branches that will be released.
9+
Write entries in :code:`CHANGELOG.md` on :code:`main`, then backport to stable branches.
10+
4. Verify version consistency across configuration files (:code:`appinfo/info.xml`, :code:`package.json`, :code:`package-lock.json`).
11+
5. Apply the required release changes in the codebase.
1012

1113
.. note::
1214
You can use the :code:`[skip ci]` tag in the commit message to skip the CI checks for the backport PRs to make the process faster.
1315

14-
4. Create a pull request to the `main` branch with the changes that you made.
15-
5. After the CI finish with success and the PR is merged, backport the changes to the stable branches that will be released.
16-
6. After the backport PRs are merged, create the releases in GitHub.
17-
7. Verify that the GitHub Action that creates the packages and publish them in the Nextcloud App Store finish with success.
18-
8. Announce the release in the Telegram channel.
16+
.. important::
17+
18+
Release PRs must stay strictly scoped to the release itself.
19+
Do not mix release automation, workflow, Release Drafter, refactor,
20+
or any other maintenance changes in the same PR.
21+
The allowed changes in a release PR are the changelog section and the
22+
version bumps required for that release.
23+
24+
6. Open a pull request to :code:`main` with the release preparation changes.
25+
7. After CI passes and the PR is merged, backport the changes to the stable branches to be released.
26+
8. After the backport PRs are merged, perform a smoke test on all supported browsers.
27+
9. Create the GitHub release for the oldest stable version in the cycle first.
28+
10. Verify the GitHub Action for that release finished successfully and wait until the version is visible in the Nextcloud App Store.
29+
11. Repeat the same publication and validation flow for the next newer stable version, one by one.
30+
12. Announce the release in the Telegram channel.
31+
32+
.. important::
33+
34+
When publishing more than one stable release in the same cycle, never
35+
create the newer tag before the older release is fully published.
36+
The required order is:
37+
38+
1. publish the oldest stable release
39+
2. wait for the GitHub Action to succeed
40+
3. confirm the version is visible on https://apps.nextcloud.com/apps/libresign/
41+
4. only then publish the next newer stable release
42+
43+
.. note::
44+
45+
If you automate release creation with :code:`gh release create` or
46+
:code:`gh release edit`, prefer loading the notes from a file instead of
47+
inlining multiline markdown in the shell command. This avoids escaping
48+
issues in backticks, parentheses, and links.
1949

2050
Version numbers
2151
---------------
@@ -25,6 +55,118 @@ Version numbers
2555
- ``MINOR`` is used for LibreSign feature releases.
2656
- ``PATCH`` is used for bug fixes or small improvements.
2757

58+
Milestones
59+
----------
60+
61+
Every PR must be assigned to a milestone.
62+
63+
- PRs targeting :code:`main` must use the current **major milestone** for the
64+
Nextcloud server version supported by :code:`appinfo/info.xml` on :code:`main`.
65+
- PRs targeting stable branches must use the corresponding **patch milestone**
66+
for that server major, using the branch :code:`appinfo/info.xml` version as the
67+
source of truth.
68+
69+
Examples with the current branch model:
70+
71+
- :code:`main` with :code:`14.0.0-dev.*` maps to :code:`Next Major (34)`.
72+
- :code:`stable33` maps to :code:`Next Patch (33)`.
73+
- :code:`stable32` maps to :code:`Next Patch (32)`.
74+
75+
.. important::
76+
77+
A PR without milestone is not ready for review or merge.
78+
Before opening or updating a release PR, confirm the milestone is correct.
79+
80+
Identifying the previous release tag
81+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
82+
83+
Before starting the changelog, you need to identify the previous release tag for each stable branch:
84+
85+
.. code-block:: bash
86+
87+
# List all tags sorted by version (newest first)
88+
git tag -l "v*" --sort=-version:refname | head -20
89+
90+
# Or find the last tag for a specific branch
91+
git describe --tags --abbrev=0 stable22
92+
93+
This tag will be used in the commit log range when collecting PRs (e.g., ``v12.2.0..stable22``).
94+
95+
.. important::
96+
97+
The tag range is only the **raw input** for the changelog. On stable branches,
98+
it is possible to merge backports of already published hotfixes after the tag
99+
was created. Because of that, always cross-check the raw compare output with
100+
the existing published sections in :code:`CHANGELOG.md` and exclude entries
101+
that already shipped in previous patch releases.
102+
103+
Collecting PRs and changelog entries
104+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
105+
106+
For each release, collect merged PRs since the previous release tag.
107+
108+
**Method 1: git log (recommended)**
109+
110+
.. code-block:: bash
111+
112+
# Collect all merge commits from previous tag to stable branch
113+
git log --oneline --merges --first-parent <previous-tag>..stable<XX>
114+
115+
# Example for stable33 since v13.0.0
116+
git log --oneline --merges --first-parent v13.0.0..stable33
117+
118+
# Output format: merge commits with PR references (Merge pull request #XXXX)
119+
120+
To get PR numbers with backport titles directly (faster changelog drafting):
121+
122+
.. code-block:: bash
123+
124+
# Example: from merge commit of previous release to stable branch head
125+
for c in $(git rev-list --reverse --merges --first-parent <release-merge-commit>..stable<XX>); do
126+
pr=$(git show -s --format='%s' "$c" | sed -E 's/^Merge pull request #([0-9]+).*/\1/')
127+
title=$(git show -s --format='%b' "$c" | head -n 1)
128+
printf '%s|%s\n' "$pr" "$title"
129+
done
130+
131+
**Method 2: GitHub CLI (gh)**
132+
133+
.. code-block:: bash
134+
135+
# List merged PRs between two tags/branches
136+
gh pr list -B stable33 -S "merged:>$(git log -1 --format=%ai <previous-tag>)" --json number,title,mergedAt
137+
138+
# Or search for PRs merged after a specific date
139+
gh pr list -B stable33 --state merged --search "merged:>=2025-02-01" --json number,title
140+
141+
To list milestones with current GitHub CLI versions, prefer the API endpoint:
142+
143+
.. code-block:: bash
144+
145+
gh api repos/LibreSign/libresign/milestones?state=all\&per_page=100
146+
147+
**Important: Mapping backports to original PRs**
148+
149+
When collecting PR data for a release, you may encounter backport PRs. These should be mapped to the original PR for proper documentation:
150+
151+
- **Backport PRs** are created with a naming pattern like: ``Backport: fix: ...`` or on a backport branch
152+
- Look at the PR description or linked issues to find the **original PR number**
153+
- In the changelog, use the **backport PR number** (specific to the branch) but reference both
154+
155+
Also exclude PRs that are only part of the release process itself, for example:
156+
157+
- release-drafter alignment or release housekeeping PRs
158+
- follow-up lockfile repair PRs whose only purpose is to fix the backport branch
159+
- hotfix PRs that already generated a published patch release section
160+
161+
Example for handling backports:
162+
163+
- Original PR on main: #6944 "fix: docmdp first signature allow"
164+
- Backport PR on stable33: #6944 (same in this case) or #6945 on stable32
165+
- In changelog, list: ``#6944 fix: docmdp first signature allow`` (use the stable branch specific PR number)
166+
167+
Defining release version numbers
168+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
169+
28170
1. Go to Milestones in the LibreSign repository:
29171

30172
https://github.com/LibreSign/libresign/milestones
@@ -40,13 +182,54 @@ Version numbers
40182
2. To new features, increment with :code:`1` the ``MINOR`` version and reset ``PATCH`` to ``0``.
41183
3. To bug fixes, increment the ``PATCH`` version.
42184

185+
.. note::
186+
187+
The Release Drafter workflow can help by pre-filling the draft version from
188+
the stable branch history, but the final version decision is still validated
189+
during the changelog curation step.
190+
43191
Stable branches
44192
---------------
45193

46194
Each **stable branch** in LibreSign corresponds to a specific Nextcloud **MAJOR** version.
47195

48196
For example: ``stable21`` is compatible with Nextcloud 21.
49197

198+
Changelog format
199+
----------------
200+
201+
The :code:`CHANGELOG.md` file uses a specific format to document releases. Follow this pattern:
202+
203+
.. code-block:: markdown
204+
205+
## [13.0.1] (stable33) - 2025-02-18
206+
### Fixed
207+
- #6944 fix: docmdp first signature allow
208+
- #6945 fix: signature status propfind
209+
- #6940 fix: avoid empty crl engine default
210+
211+
## [12.2.1] (stable32) - 2025-02-18
212+
### Fixed
213+
- #6943 fix: docmdp first signature allow
214+
- #6946 fix: signature status propfind
215+
- #6939 fix: avoid empty crl engine default
216+
217+
**Key format rules:**
218+
219+
- Use semantic versioning: ``[MAJOR.MINOR.PATCH]``
220+
- Include the stable branch in parentheses: ``(stableXX)``
221+
- Add the release date: ``YYYY-MM-DD``
222+
- Group changes by type: ``Added``, ``Changed``, ``Fixed``, ``Removed``, etc.
223+
- List PR number with hash: ``#XXXX`` followed by a colon and description
224+
- Use lowercase for descriptions (following conventional commits)
225+
- For backport releases, use the **stable branch-specific PR number** even if it differs from the original
226+
- Always add new entries at the top (most recent first)
227+
- Prefer user-visible changes in the release notes; keep purely internal test/refactor/dependency entries only when they are relevant to support or compatibility.
228+
- Collapse dependency updates into a single changelog item (e.g. ``Bump dependencies``) instead of listing each maintenance PR.
229+
- Always include ``Update translations`` in the release changelog.
230+
- Do not include Dependabot-only commits in the final changelog section.
231+
- Treat GitHub generated release notes as a draft source only; rewrite the final section so it tells the release story instead of listing every backport PR individually.
232+
50233
Release checklist
51234
-----------------
52235

@@ -87,16 +270,28 @@ with the correct values as you progress through the steps.
87270
- [ ] Go to the main branch, pull the latest changes and create a new branch called `chore/changelog`
88271
- [ ] Add the changelog entries to the `CHANGELOG.md` file, following the pattern used in the file.
89272
- [ ] Make this to all releases that will be done in this process.
273+
- [ ] Assign the PR to the correct milestone
274+
- [ ] `main` uses the current `Next Major (XX)` milestone from `appinfo/info.xml`
275+
- [ ] each stable branch uses its matching `Next Patch (XX)` milestone
90276
- [ ] Create a PR against `main` branch at the `CHANGELOG.md` file with the changelog of all milestones that are subject to the release. Look the pattern used in the file and follow it.
91-
You can use the :code:`[skip ci]` tag in the commit message to skip the CI checks for the backport PRs to make the process faster.
277+
The **last commit** of every release PR must include :code:`[skip ci]`.
278+
This keeps the release train moving and avoids waiting for a full CI cycle
279+
right before the tag and publication steps.
280+
Do not use the release PR to change anything beyond changelog and version bumps.
92281
```
93282
name suggestions to commit and pull request:
94283
chore(release): Changelog for 20.1.9
95284
chore(release): Changelog for 20.1.9 and 20.1.8
96285
```
97286
- [ ] Merge the PR
287+
- [ ] **Version consistency check** (before backporting):
288+
- [ ] Verify :code:`appinfo/info.xml` has the correct version
289+
- [ ] Run: :code:`npm version --no-git-tag-version $(xmllint --xpath '/info/version/text()' appinfo/info.xml)`
290+
- [ ] Verify :code:`package.json` and :code:`package-lock.json` were updated correctly
291+
- [ ] Commit these changes together with the changelog PR if needed
98292
<!-- Duplicate the follow steps for each version that will be released, starting with the oldest version. -->
99293
<!-- Pay attention to start with the **oldest** version here, so the appstore and github releases show the newest version as "Last release" and them. -->
294+
<!-- Do not publish the newer release until the older release workflow is fully finished and validated in the App Store. -->
100295
<!-- Replace "XX" with the Nextcloud stable branch number e.g. "22" for "stable22" -->
101296
<!-- 1. Replace "20.1.9" with the version number e.g. "12.2.4" -->
102297
<!-- Replace "20.1.8" with the previous version number e.g. "12.2.3" -->
@@ -112,14 +307,27 @@ with the correct values as you progress through the steps.
112307
# Make sure the printed version matches the info.xml version
113308
npm version --no-git-tag-version $(xmllint --xpath '/info/version/text()' appinfo/info.xml)
114309
```
310+
- [ ] Make sure the final commit of the PR uses :code:`[skip ci]`
311+
- [ ] Confirm the PR only changes release files: `CHANGELOG.md`, `appinfo/info.xml`, `package.json`, `package-lock.json`
312+
- [ ] Assign the PR to the matching `Next Patch (XX)` milestone of the stable branch
115313
- [ ] Merge the backport
116-
- [ ] Do a quick smoke test signing documents with:
117-
- [ ] Chrome
118-
- [ ] Edge
119-
- [ ] Firefox
120-
- [ ] Safari
314+
- [ ] **Smoke test** - Sign a document in each supported browser:
315+
- [ ] Chrome (latest version)
316+
- [ ] Edge (latest version)
317+
- [ ] Firefox (latest version)
318+
- [ ] Safari (latest version)
319+
- [ ] Verify: Request signing, Add signature, Validate signature in AppStore/File Manager
320+
- [ ] **Final validation checks**:
321+
- [ ] Verify version number in :code:`appinfo/info.xml` matches release tag
322+
- [ ] Verify changelog in :code:`CHANGELOG.md` is correct and properly formatted
323+
- [ ] Check GitHub Actions status for the merged PR
324+
- [ ] Review AppStore entries for the stable branch (if available)
121325
- [ ] Create the new milestone
122326
- [ ] Rename milestone `💚 Next Patch (XX)` to `v20.1.9` in https://github.com/LibreSign/libresign/milestones
327+
- [ ] Confirm the milestone was correctly renamed before writing the release body:
328+
```sh
329+
gh api 'repos/LibreSign/libresign/milestones?state=open' --jq '.[] | "\(.number) \(.title)"'
330+
```
123331
Unless last release of the stable branch:
124332
- [ ] Create a follow up milestone for `💚 Next Patch (XX)` (Due date in ~4 weeks, ~4 days for beta/RC)
125333
- [ ] Move all open issuesfrom milestone `v20.1.9` to `💚 Next Patch (XX)`: https://github.com/LibreSign/libresign/issues?q=is%3Aissue%20state%3Aopen%20milestone%3Av20.1.9
@@ -128,9 +336,14 @@ with the correct values as you progress through the steps.
128336
- [ ] Archive all issues and PRs that were merged in this release
129337
- [ ] https://github.com/orgs/LibreSign/projects/2/views/4
130338
- [ ] Create a new release
339+
- [ ] Confirm the exact commit that will be tagged is the current head of the stable branch:
340+
```sh
341+
git ls-remote origin refs/heads/stable20 | awk '{print $1}'
342+
```
131343
- [ ] Prepare a (pre-)release in https://github.com/LibreSign/libresign/releases/new?tag=v20.1.9&target=stable20
132344
- [ ] Make sure that chosen tag is v20.1.9, target is stable20, and previous tag is v20.1.8
133345
- [ ] Add the content of respective `CHANGELOG.md` section from merged PR
346+
- [ ] In the release body, use the final closed milestone name `v20.1.9` after the milestone rename, never the previous `Next Patch (XX)` name
134347
- [ ] Use the **Generate release notes** button and wrap the output result into
135348
```
136349
## What's Changed
@@ -141,4 +354,15 @@ with the correct values as you progress through the steps.
141354
- [ ] Publish release
142355
- [ ] Check that the GitHub Action started: https://github.com/LibreSign/libresign/actions
143356
- [ ] Ensure that the GitHub Action finished successfully: https://github.com/LibreSign/libresign/actions
357+
- [ ] **Post-release validation**:
358+
- [ ] Verify the new version appears in AppStore: https://apps.nextcloud.com/apps/libresign
359+
- [ ] Check that the package was properly built and published
360+
- [ ] Verify changelog is visible on GitHub Releases page
361+
- [ ] Confirm no errors in GitHub Actions logs
362+
- [ ] If a publication fix is merged after the release tag is created, do not only rerun the old workflow
363+
- [ ] Delete the GitHub release and the tag
364+
- [ ] Recreate the tag from the updated stable branch head
365+
- [ ] Recreate the GitHub release so the workflow checks out the corrected commit
366+
- [ ] If there is another release to publish in the same cycle, stop here and wait for all checks above to be green before creating the next release tag
367+
- [ ] Only after the older release is visible and correct on https://apps.nextcloud.com/apps/libresign/, publish the next newer release
144368
- [ ] Post the changelog in [💬 LibreSign team public 👥](https://t.me/LibreSign)

0 commit comments

Comments
 (0)