diff options
| author | Brian Gan <brgan@google.com> | 2026-10-27 00:01:58 +0000 |
|---|---|---|
| committer | gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com <gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2026-10-27 12:29:45 -0700 |
| commit | c5340585b8175f91a483d6d0fe30724e6b277c0b (patch) | |
| tree | 1deaf14c1cc478bb6ca7d027c36c708f80ecc128 | |
| parent | 86a7bec83d5ce714359eb251c191955e9dac2a08 (diff) | |
| download | git-repo-main.tar.gz | |
docs: release: update release process to match current practicemain
The documented process has drifted from how releases are actually done:
* Releases are now cut weekly by an automated pipeline, so the manual
steps are only a fallback, and for rollbacks.
* Releases are tested (both updating an existing checkout and a fresh
init) before pushing anything.
* The tag is pushed & announced first, and only promoted to stable after
a day.
* Direct pushes to the stable branch are rejected, so it has to be
deleted & recreated via the Gerrit REST API instead.
Bug: 575551885
Change-Id: Ib36df07811c225558aba1a925b9703f3b2017e6f
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/649984
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Brian Gan <brgan@google.com>
Commit-Queue: Brian Gan <brgan@google.com>
| -rw-r--r-- | docs/release-process.md | 98 |
1 files changed, 54 insertions, 44 deletions
diff --git a/docs/release-process.md b/docs/release-process.md index 165bf84fc..ae69c98e8 100644 --- a/docs/release-process.md +++ b/docs/release-process.md | |||
| @@ -5,11 +5,19 @@ related topics and flows. | |||
| 5 | 5 | ||
| 6 | [TOC] | 6 | [TOC] |
| 7 | 7 | ||
| 8 | ## Schedule | 8 | ## Schedule {#schedule} |
| 9 | |||
| 10 | Releases are automated. | ||
| 11 | Every Tuesday morning [US PT], a pipeline checks if any new commits have landed | ||
| 12 | since last release. | ||
| 13 | If so, it tags & tests the latest `main`, pushes & announces the tag, and then | ||
| 14 | promotes it to `stable` a day later. | ||
| 15 | The release is skipped if there's a holiday or [production freeze](#freeze) | ||
| 16 | that week. | ||
| 17 | Maintainers can also trigger it by hand. | ||
| 18 | The [manual steps](#manual) below are only needed as a fallback, or to roll | ||
| 19 | back a release. | ||
| 9 | 20 | ||
| 10 | There is no specific schedule for when releases are made. | ||
| 11 | Usually it's more along the lines of "enough minor changes have been merged", | ||
| 12 | or "there's a known issue the maintainers know should get fixed". | ||
| 13 | If you find a fix has been merged for an issue important to you, but hasn't been | 21 | If you find a fix has been merged for an issue important to you, but hasn't been |
| 14 | released after a week or so, feel free to [contact] us to request a new release. | 22 | released after a week or so, feel free to [contact] us to request a new release. |
| 15 | 23 | ||
| @@ -48,6 +56,11 @@ Whenever major changes are made to the launcher script, you should increment the | |||
| 48 | At runtime, repo will check this to see if it needs to be updated (and notify | 56 | At runtime, repo will check this to see if it needs to be updated (and notify |
| 49 | the user automatically). | 57 | the user automatically). |
| 50 | 58 | ||
| 59 | When `VERSION` changes, the release pipeline publishes the new launcher to the | ||
| 60 | `git-repo-downloads` Google Cloud Storage bucket. | ||
| 61 | To publish it by hand, run `./release/sign-launcher.py`, which signs the | ||
| 62 | launcher and prints the commands to upload it. | ||
| 63 | |||
| 51 | ## Key management | 64 | ## Key management |
| 52 | 65 | ||
| 53 | Every release has a git tag that is signed with a key that repo recognizes. | 66 | Every release has a git tag that is signed with a key that repo recognizes. |
| @@ -96,8 +109,8 @@ If that tag is valid, then repo will warn and use that commit instead. | |||
| 96 | 109 | ||
| 97 | If that tag cannot be verified, it gives up and forces the user to resolve. | 110 | If that tag cannot be verified, it gives up and forces the user to resolve. |
| 98 | 111 | ||
| 99 | If env variable `REPO_SKIP_SELF_UPDATE` is defined, this will | 112 | If the env variable `REPO_SKIP_SELF_UPDATE` is set to anything other than `0`, |
| 100 | bypass the self update algorithm. | 113 | `repo sync` will bypass the self update algorithm. |
| 101 | 114 | ||
| 102 | ### Force an update | 115 | ### Force an update |
| 103 | 116 | ||
| @@ -110,29 +123,20 @@ All development happens on the `main` branch and should generally be stable. | |||
| 110 | 123 | ||
| 111 | Since the repo launcher defaults to tracking the `stable` branch, it is not | 124 | Since the repo launcher defaults to tracking the `stable` branch, it is not |
| 112 | normally updated until a new release is available. | 125 | normally updated until a new release is available. |
| 113 | If something goes wrong with a new release, an older release can be force pushed | 126 | If something goes wrong with a new release, `stable` can be pointed back at an |
| 114 | and clients will automatically downgrade. | 127 | older release and clients will automatically downgrade. |
| 115 | |||
| 116 | The `maint` branch is used to track the previous major release of repo. | ||
| 117 | It is not normally meant to be used by people as `stable` should be good enough. | ||
| 118 | Once a new major release is pushed to the `stable` branch, then the previous | ||
| 119 | major release can be pushed to `maint`. | ||
| 120 | For example, when `stable` moves from `v1.10.x` to `v1.11.x`, then the `maint` | ||
| 121 | branch will be updated from `v1.9.x` to `v1.10.x`. | ||
| 122 | 128 | ||
| 123 | We don't have parallel release branches/series. | 129 | We don't have parallel release branches/series. |
| 124 | Typically all tags are made against the `main` branch and then pushed to the | 130 | Typically all tags are made against the `main` branch and then promoted to the |
| 125 | `stable` branch to make it available to the rest of the world. | 131 | `stable` branch to make it available to the rest of the world. |
| 126 | Since repo doesn't typically see a lot of changes, this tends to be OK. | 132 | Since repo doesn't typically see a lot of changes, this tends to be OK. |
| 127 | 133 | ||
| 128 | ## Creating a new release | 134 | ## Creating a new release {#manual} |
| 129 | 135 | ||
| 130 | When you want to create a new release, you'll need to select a good version and | 136 | Releases are normally created automatically (see [Schedule](#schedule)). |
| 137 | If you need to create one by hand, you'll need to select a good version and | ||
| 131 | create a signed tag using a key registered in repo itself. | 138 | create a signed tag using a key registered in repo itself. |
| 132 | Typically we just tag the latest version of the `main` branch. | 139 | Typically we just tag the latest version of the `main` branch. |
| 133 | The tag could be pushed now, but it won't be used by clients normally (since the | ||
| 134 | default `repo-rev` setting is `stable`). | ||
| 135 | This would allow some early testing on systems who explicitly select `main`. | ||
| 136 | 140 | ||
| 137 | ### Creating a signed tag | 141 | ### Creating a signed tag |
| 138 | 142 | ||
| @@ -147,10 +151,10 @@ internal processes for accessing the restricted keys. | |||
| 147 | 151 | ||
| 148 | ```sh | 152 | ```sh |
| 149 | # Pick the new version. | 153 | # Pick the new version. |
| 150 | $ t=v2.30 | 154 | $ t=v2.XX |
| 151 | 155 | ||
| 152 | # Create a new signed tag with the current HEAD. | 156 | # Create a new signed tag of the latest main branch. |
| 153 | $ ./release/sign-tag.py $t | 157 | $ ./release/sign-tag.py $t origin/main |
| 154 | 158 | ||
| 155 | # Verify the signed tag. | 159 | # Verify the signed tag. |
| 156 | $ git show $t | 160 | $ git show $t |
| @@ -158,43 +162,49 @@ $ git show $t | |||
| 158 | 162 | ||
| 159 | ### Push the new release | 163 | ### Push the new release |
| 160 | 164 | ||
| 161 | Once you're ready to make the release available to everyone, push it to the | 165 | First push the tag, [announce](#announce) it, and wait a day to get feedback |
| 162 | `stable` branch. | 166 | from people testing new releases early. |
| 163 | |||
| 164 | Make sure you never push the tag itself to the stable branch! | ||
| 165 | Only push the commit -- note the use of `^0` below. | ||
| 166 | 167 | ||
| 167 | ```sh | 168 | ```sh |
| 168 | $ git push https://gerrit-review.googlesource.com/git-repo $t | 169 | $ git push https://gerrit-review.googlesource.com/git-repo $t |
| 169 | $ git push https://gerrit-review.googlesource.com/git-repo $t^0:stable | ||
| 170 | ``` | 170 | ``` |
| 171 | 171 | ||
| 172 | If something goes horribly wrong, you can force push the previous version to the | 172 | Then make the release available to everyone by updating the `stable` branch. |
| 173 | `stable` branch and people should automatically recover. | 173 | Direct pushes to it are rejected, so it has to be deleted & recreated via the |
| 174 | Again, make sure you never push the tag itself! | 174 | authenticated [Gerrit REST API] (see [go/repo-release] for maintainers). |
| 175 | |||
| 176 | Make sure you never point the stable branch at the tag itself! | ||
| 177 | Only use the commit -- note the use of `^0` below. | ||
| 178 | The commit is resolved before deleting anything so that a bad `$t` can't leave | ||
| 179 | `stable` missing. | ||
| 175 | 180 | ||
| 176 | ```sh | 181 | ```sh |
| 177 | $ oldrev="whatever-old-commit" | 182 | $ api=https://gerrit-review.googlesource.com/a/projects/git-repo/branches/stable |
| 178 | $ git push https://gerrit-review.googlesource.com/git-repo $oldrev:stable --force | 183 | $ rev=$(git rev-parse --verify "$t^0") && \ |
| 184 | curl --fail -X DELETE "$api" && \ | ||
| 185 | curl --fail -X PUT -H 'Content-Type: application/json' \ | ||
| 186 | -d "{\"revision\":\"$rev\"}" "$api" | ||
| 179 | ``` | 187 | ``` |
| 180 | 188 | ||
| 181 | ### Announce the release | 189 | If something goes horribly wrong, run the same commands with the previous |
| 190 | release (e.g. `t=$(git describe --abbrev=0 $t^0~)`) and people should | ||
| 191 | automatically recover. | ||
| 192 | |||
| 193 | ### Announce the release {#announce} | ||
| 182 | 194 | ||
| 183 | Once you do push a new release to `stable`, make sure to announce it on the | 195 | Once you push a new release, make sure to announce it on the |
| 184 | [repo-discuss@googlegroups.com] group. | 196 | [repo-discuss@googlegroups.com] group, and follow up once it's on `stable`. |
| 185 | Here is an [example announcement]. | 197 | Here is an [example announcement]. |
| 186 | 198 | ||
| 187 | You can create a short changelog using the command: | 199 | You can create a short changelog since the previous release using the command: |
| 188 | 200 | ||
| 189 | ```sh | 201 | ```sh |
| 190 | # If you haven't pushed to the stable branch yet, you can use origin/stable. | 202 | $ git log --format="%h (%aN) %s" --no-merges \ |
| 191 | # If you have pushed, change origin/stable to the previous release tag. | 203 | $(git describe --abbrev=0 $t^0~)..$t |
| 192 | # This assumes "main" is the current tagged release. If it's newer, change it | ||
| 193 | # to the current release tag too. | ||
| 194 | $ git log --format="%h (%aN) %s" --no-merges origin/stable..main | ||
| 195 | ``` | 204 | ``` |
| 196 | 205 | ||
| 197 | [contact]: ../README.md#contact | 206 | [contact]: ../README.md#contact |
| 198 | [example announcement]: https://groups.google.com/d/topic/repo-discuss/UGBNismWo1M/discussion | 207 | [example announcement]: https://groups.google.com/d/topic/repo-discuss/UGBNismWo1M/discussion |
| 199 | [repo-discuss@googlegroups.com]: https://groups.google.com/forum/#!forum/repo-discuss | 208 | [repo-discuss@googlegroups.com]: https://groups.google.com/forum/#!forum/repo-discuss |
| 200 | [go/repo-release]: https://goto.google.com/repo-release | 209 | [go/repo-release]: https://goto.google.com/repo-release |
| 210 | [Gerrit REST API]: https://gerrit-review.googlesource.com/Documentation/rest-api-projects.html#branch-endpoints | ||
