| 1 | <!-- Last updated during [v0.40.0 release](https://github.com/ipfs/kubo/issues/11008) --> |
| 2 | |
| 3 | # ✅ Release Checklist (vX.Y.Z[-rcN]) |
| 4 | |
| 5 | **Release types:** RC (Release Candidate) | FINAL | PATCH |
| 6 | |
| 7 | ## Prerequisites |
| 8 | |
| 9 | - [ ] [GPG signature](https://docs.github.com/en/authentication/managing-commit-signature-verification) configured in local git and GitHub |
| 10 | - [ ] [Docker](https://docs.docker.com/get-docker/) installed on your system |
| 11 | - [ ] [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) installed on your system |
| 12 | - [ ] kubo repository cloned locally |
| 13 | - [ ] **non-PATCH:** Upgrade Go in CI to latest patch from <https://go.dev/dl/> |
| 14 | |
| 15 | ## 1. Prepare Release Branch |
| 16 | |
| 17 | - [ ] Fetch latest changes: `git fetch origin master release` |
| 18 | - [ ] Create branch `release-vX.Y.Z` (base from: `master` if Z=0 for new minor/major, `release` if Z>0 for patch) |
| 19 | - [ ] **RC1 only:** Switch to `master` branch and prepare for next release cycle: |
| 20 | - [ ] Update [version.go](https://github.com/ipfs/kubo/blob/master/version.go) to `vX.Y+1.0-dev` (⚠️ double-check Y+1 is correct) ([example PR](https://github.com/ipfs/kubo/pull/9305)) |
| 21 | - [ ] Create `./docs/changelogs/vX.Y+1.md` and add link in [CHANGELOG.md](https://github.com/ipfs/kubo/blob/master/CHANGELOG.md) |
| 22 | - [ ] Switch to `release-vX.Y.Z` branch and update [version.go](https://github.com/ipfs/kubo/blob/master/version.go) to `vX.Y.Z(-rcN)` (⚠️ double-check Y matches release) ([example](https://github.com/ipfs/kubo/pull/9394)) |
| 23 | - [ ] Create draft PR: `release-vX.Y.Z` → `release` ([example](https://github.com/ipfs/kubo/pull/9306)) |
| 24 | - [ ] Cherry-pick commits from `master` into `release-vX.Y.Z`: `git cherry-pick -x <commit>` ([example](https://github.com/ipfs/kubo/pull/10636/commits/033de22e3bc6191dbb024ad6472f5b96b34e3ccf)) |
| 25 | - ⚠️ **NOTE:** `-x` flag records original commit SHA for traceability and cleaner merge history |
| 26 | - [ ] Verify all CI checks on the PR are passing |
| 27 | - [ ] **FINAL only:** Replace `Changelog` and `Contributors` sections in `release-vX.Y.Z` with `./bin/mkreleaselog` stdout (do **NOT** copy stderr) |
| 28 | - [ ] **FINAL only:** Merge PR (`release-vX.Y.Z` → `release`) using `Create a merge commit` |
| 29 | - ⚠️ do **NOT** use `Squash and merge` nor `Rebase and merge`; we want the releaser's GPG signature on the merge commit |
| 30 | - ⚠️ do **NOT** delete the `release-vX.Y.Z` branch (needed for future patch releases and git history) |
| 31 | |
| 32 | ## 2. Tag & Publish |
| 33 | |
| 34 | ### Create Tag |
| 35 | ⚠️ **POINT OF NO RETURN:** once pushed, tags trigger automatic Docker/NPM publishing that cannot be undone! |
| 36 | If you're making a release for the first time, do pair programming and have the release reviewer verify all commands. |
| 37 | |
| 38 | - [ ] **RC:** From `release-vX.Y.Z` branch: `git tag -s vX.Y.Z-rcN -m 'Prerelease X.Y.Z-rcN'` |
| 39 | - [ ] **FINAL:** After PR merge, from `release` branch: `git tag -s vX.Y.Z -m 'Release X.Y.Z'` |
| 40 | - [ ] ⚠️ Verify tag is signed and correct: `git show vX.Y.Z(-rcN)` |
| 41 | - [ ] Push tag: `git push origin vX.Y.Z(-rcN)` |
| 42 | - ⚠️ do **NOT** use `git push --tags` (pushes every local tag, cluttering the repo) |
| 43 | - [ ] **STOP:** Wait for [Docker build](https://github.com/ipfs/kubo/actions/workflows/docker-image.yml) to complete before proceeding |
| 44 | |
| 45 | ### Publish Artifacts |
| 46 | |
| 47 | > **Parallelism:** Docker and dist.ipfs.tech only depend on the pushed tag and can be started in parallel. |
| 48 | > NPM and GitHub Release both depend on dist.ipfs.tech completing first. |
| 49 | |
| 50 | - [ ] **Docker:** Verify [docker-image CI](https://github.com/ipfs/kubo/actions/workflows/docker-image.yml) passed and image is available on [Docker Hub → tags](https://hub.docker.com/r/ipfs/kubo/tags) |
| 51 | - [ ] **dist.ipfs.tech:** Publish to [dist.ipfs.tech](https://dist.ipfs.tech) |
| 52 | - [ ] Check out [ipfs/distributions](https://github.com/ipfs/distributions) |
| 53 | - [ ] Create branch: `git checkout -b release-kubo-X.Y.Z(-rcN)` |
| 54 | - [ ] Verify `.tool-versions` golang matches [Kubo's CI](https://github.com/ipfs/kubo/blob/master/.github/workflows/gotest.yml) `go-version:` (update if needed) |
| 55 | - [ ] Run: `./dist.sh add-version kubo vX.Y.Z(-rcN)` ([usage](https://github.com/ipfs/distributions#usage)) |
| 56 | - [ ] Create and merge PR (updates `dists/kubo/versions`, **FINAL** also updates `dists/kubo/current` - [example](https://github.com/ipfs/distributions/pull/1125)) |
| 57 | - [ ] Wait for [CI workflow](https://github.com/ipfs/distributions/actions/workflows/main.yml) triggered by merge |
| 58 | - [ ] Verify release on [dist.ipfs.tech](https://dist.ipfs.tech/#kubo) |
| 59 | - [ ] **NPM:** Publish to [NPM](https://www.npmjs.com/package/kubo?activeTab=versions) |
| 60 | - [ ] Manually dispatch [Release to npm](https://github.com/ipfs/npm-kubo/actions/workflows/main.yml) workflow if not auto-triggered |
| 61 | - [ ] Verify release on [NPM](https://www.npmjs.com/package/kubo?activeTab=versions) |
| 62 | - [ ] **GitHub Release:** Publish to [GitHub](https://github.com/ipfs/kubo/releases) |
| 63 | - [ ] [Create release](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository#creating-a-release) ([RC example](https://github.com/ipfs/kubo/releases/tag/v0.36.0-rc1), [FINAL example](https://github.com/ipfs/kubo/releases/tag/v0.35.0)) |
| 64 | - [ ] Use tag `vX.Y.Z(-rcN)` |
| 65 | - [ ] Link to release issue |
| 66 | - [ ] **RC:** Link to changelog, check `This is a pre-release` |
| 67 | - [ ] **FINAL:** Copy changelog content (without header), do **NOT** check pre-release |
| 68 | - [ ] Run [sync-release-assets](https://github.com/ipfs/kubo/actions/workflows/sync-release-assets.yml) workflow (requires dist.ipfs.tech) |
| 69 | - [ ] Verify assets are attached to the GitHub release |
| 70 | |
| 71 | ## 3. Post-Release |
| 72 | |
| 73 | ### Technical Tasks |
| 74 | |
| 75 | - [ ] **FINAL only:** Merge `release` → `master` |
| 76 | - [ ] Create branch `merge-release-vX.Y.Z` from `release` |
| 77 | - [ ] Merge `master` to `merge-release-vX.Y.Z` first, and resolve conflict in `version.go` |
| 78 | - ⚠️ **NOTE:** keep the `-dev` version from `master` in [version.go](https://github.com/ipfs/kubo/blob/master/version.go), discard version from `release` |
| 79 | - [ ] Create and merge PR from `merge-release-vX.Y.Z` to `master` using `Create a merge commit` |
| 80 | - ⚠️ do **NOT** use `Squash and merge` nor `Rebase and merge`; only `Create a merge commit` preserves commit history and the audit trail of what was merged where |
| 81 | - [ ] Update [ipshipyard/waterworks-infra](https://github.com/ipshipyard/waterworks-infra) |
| 82 | - [ ] Update Kubo staging environment ([Running Kubo tests on staging](https://www.notion.so/Running-Kubo-tests-on-staging-488578bb46154f9bad982e4205621af8)) |
| 83 | - [ ] **RC:** Test last release against current RC |
| 84 | - [ ] **FINAL:** Latest release on both boxes |
| 85 | - [ ] **FINAL:** Update collab cluster boxes to the tagged release |
| 86 | - [ ] **FINAL:** Update libp2p bootstrappers to the tagged release |
| 87 | - [ ] Update [ipfs-desktop](https://github.com/ipfs/ipfs-desktop) |
| 88 | - [ ] Create PR updating kubo version in `package.json` and `package-lock.json` |
| 89 | - [ ] Smoke test with [IPFS Companion Browser Extension](https://docs.ipfs.tech/install/ipfs-companion/) against the PR build |
| 90 | - [ ] **FINAL:** Merge PR and ship new ipfs-desktop release |
| 91 | - [ ] **FINAL only:** Update [docs.ipfs.tech](https://docs.ipfs.tech/): run [update-on-new-ipfs-tag.yml](https://github.com/ipfs/ipfs-docs/actions/workflows/update-on-new-ipfs-tag.yml) workflow and merge the PR |
| 92 | |
| 93 | ### Promotion |
| 94 | |
| 95 | - [ ] Create [IPFS Discourse](https://discuss.ipfs.tech) topic ([RC example](https://discuss.ipfs.tech/t/kubo-v0-38-0-rc2-is-out/19772), [FINAL example](https://discuss.ipfs.tech/t/kubo-v0-38-0-is-out/19795)) |
| 96 | - [ ] Title: `Kubo vX.Y.Z(-rcN) is out!`, tag: `kubo` |
| 97 | - [ ] Use title as heading (`##`) in description |
| 98 | - [ ] Include: GitHub release link, IPNS binaries, docker pull command, release notes |
| 99 | - [ ] Pin topic globally (make banner if no existing banner) |
| 100 | - [ ] Verify bot posted to [#ipfs-chatter](https://discord.com/channels/669268347736686612/669268347736686615) (Discord) or [#ipfs-chatter:ipfs.io](https://matrix.to/#/#ipfs-chatter:ipfs.io) (Matrix) |
| 101 | - [ ] **RC only:** Comment on release issue mentioning early testers ([example](https://github.com/ipfs/kubo/issues/9319#issuecomment-1311002478)) |
| 102 | - [ ] **FINAL only:** Comment on release issue with link ([example](https://github.com/ipfs/kubo/issues/9417#issuecomment-1400740975)) |
| 103 | - [ ] **FINAL only:** Create [blog.ipfs.tech](https://blog.ipfs.tech) entry ([example](https://github.com/ipfs/ipfs-blog/commit/32040d1e90279f21bad56b924fe4710bba5ba043)) |
| 104 | - [ ] **FINAL non-PATCH:** (optional) Post on social media ([bsky](https://bsky.app/profile/ipshipyard.com/post/3ltxcsrbn5s2k), [x.com](https://x.com/ipshipyard/status/1944867893226635603), [Reddit](https://www.reddit.com/r/ipfs/comments/1lzy6ze/release_v0360_ipfskubo/)) |
| 105 | |
| 106 | ### Final Steps |
| 107 | |
| 108 | - [ ] **FINAL non-PATCH:** Create dependency update PR |
| 109 | - [ ] Review direct dependencies from root `go.mod` (⚠️ do **NOT** run `go get -u` as it will upgrade indirect dependencies which may cause problems) |
| 110 | - [ ] Run `make mod_tidy` |
| 111 | - [ ] Create PR with `go.mod` and `go.sum` updates |
| 112 | - [ ] Add PR to next release milestone |
| 113 | - [ ] **FINAL non-PATCH:** Create next release issue ([example](https://github.com/ipfs/kubo/issues/10816)) |
| 114 | - [ ] **FINAL only:** Close release issue |