1# Releasing LeakCanary 2 3## Preparing the release environment 4 5### Set up your Sonatype OSSRH account 6 7* Create a [Sonatype OSSRH JIRA account](https://issues.sonatype.org/secure/Signup!default.jspa). 8* Create a ticket to request access to the `com.squareup.leakcanary` project. Here's an example: [OSSRH-54959](https://issues.sonatype.org/browse/OSSRH-54959). 9* Then ask someone with deployer role from the LeakCanary team to confirm access. 10 11### Set up your signing key 12 13```bash 14# Create a new key 15gpg --gen-key 16# List local keys. Key id is last 8 characters 17gpg -K 18cd ~/.gnupg 19# Export key locally 20gpg --export-secret-keys -o secring.gpg 21# Upload key to Ubuntu servers 22gpg --send-keys --keyserver keyserver.ubuntu.com <KEY ID> 23# Confirm the key can now be found 24gpg --recv-keys --keyserver keyserver.ubuntu.com <KEY ID> 25``` 26 27### Set up your home gradle.properties 28 29Add this to your `~/.gradle/gradle.properties`: 30 31``` 32signing.keyId=<KEY ID> 33signing.password=<KEY PASSWORD> 34signing.secretKeyRingFile=/Users/YOUR_USERNAME_/.gnupg/secring.gpg 35SONATYPE_NEXUS_USERNAME=<SONATYPE_USERNAME> 36SONATYPE_NEXUS_PASSWORD=<SONATYPE_PASSWORD> 37``` 38 39### Set up the Google Analytics docs key 40 41Add this to your `~/.bashrc`: 42 43```bash 44export LEAKCANARY_GOOGLE_ANALYTICS_KEY="UA-142834539-1" 45``` 46 47### Set up GitHub CLI 48 49Install GitHub CLI 50 51```bash 52brew install gh 53``` 54 55Install jq, a CLI Json processor 56 57```bash 58brew install jq 59``` 60 61Set up aliases for milestone management: 62 63```bash 64gh alias set listOpenMilestones "api graphql -F owner=':owner' -F name=':repo' -f query=' 65 query ListOpenMilestones(\$name: String\!, \$owner: String\!) { 66 repository(owner: \$owner, name: \$name) { 67 milestones(first: 100, states: OPEN) { 68 nodes { 69 title 70 number 71 description 72 dueOn 73 url 74 state 75 closed 76 closedAt 77 updatedAt 78 } 79 } 80 } 81 } 82'" 83 84gh alias set --shell createMilestone "gh api --method POST repos/:owner/:repo/milestones --input - | jq '{ html_url: .html_url, state: .state, created_at: .created_at }'" 85 86gh alias set --shell closeMilestone "echo '{\"state\": \"closed\"}' | gh api --method PATCH repos/:owner/:repo/milestones/\$1 --input - | jq '{ html_url: .html_url, state: .state, closed_at: .closed_at }'" 87``` 88 89### Install or update the doc generation dependencies 90 91```bash 92pip3 install --requirement docs/requirements.txt 93``` 94 95## Releasing 96 97* Create a local release branch from `main` 98```bash 99git checkout main && \ 100git pull && \ 101git checkout -b release_{{ leak_canary.next_release }} 102``` 103 104* Update `VERSION_NAME` in `gradle.properties` (remove `-SNAPSHOT`) 105```gradle 106sed -i '' 's/VERSION_NAME={{ leak_canary.next_release }}-SNAPSHOT/VERSION_NAME={{ leak_canary.next_release }}/' gradle.properties 107``` 108 109* Update the current version and next version in `mkdocs.yml` 110```bash 111sed -i '' 's/{{ leak_canary.next_release }}/NEXT/' mkdocs.yml 112sed -i '' 's/{{ leak_canary.release }}/{{ leak_canary.next_release }}/' mkdocs.yml 113``` 114 115* Create the release 116```bash 117git commit -am "Prepare {{ leak_canary.next_release }} release" && \ 118./gradlew clean && \ 119./gradlew build && \ 120git tag v{{ leak_canary.next_release }} && \ 121git push origin v{{ leak_canary.next_release }} && \ 122./gradlew publish --no-daemon --no-parallel && \ 123./gradlew closeAndReleaseRepository && \ 124./gradlew shark-cli:distZip 125``` 126 127Note: if anything goes wrong, you can manually drop the release at https://s01.oss.sonatype.org/ 128 129* Merge back to main 130```bash 131git checkout main && \ 132git pull && \ 133git merge --no-ff release_{{ leak_canary.next_release }} 134``` 135* Update `VERSION_NAME` in `gradle.properties` (increase version and add `-SNAPSHOT`) 136```gradle 137sed -i '' 's/VERSION_NAME={{ leak_canary.next_release }}/VERSION_NAME=NEXT-SNAPSHOT/' gradle.properties 138``` 139 140* Generate the Dokka docs 141```bash 142rm -rf docs/api && ./gradlew siteDokka 143``` 144 145* Update the changelog ([commit list](https://github.com/square/leakcanary/compare/v{{ leak_canary.release }}...main)) 146``` 147mate docs/changelog.md 148``` 149 150* Deploy the docs locally then [open the changelog](http://127.0.0.1:8000/leakcanary/changelog/) and check everything looks good 151```bash 152mkdocs serve 153``` 154 155* Finish up the release 156 157```bash 158git commit -am "Prepare for next development iteration" && \ 159git push && \ 160gh listOpenMilestones | jq '.data.repository.milestones.nodes[0].number' | xargs gh closeMilestone && \ 161echo '{ 162 "title": "REPLACE_WITH_NEXT_VERSION_NUMBER", 163 "state": "open", 164 "description": "" 165}' | gh createMilestone && \ 166mkdocs gh-deploy 167gh release create v{{ leak_canary.next_release }} ./shark-cli/build/distributions/shark-cli-{{ leak_canary.next_release }}.zip --title v{{ leak_canary.next_release }} --notes 'See [Change Log](https://square.github.io/leakcanary/changelog)' 168``` 169 170* Open the [v{{ leak_canary.next_release }} release](https://github.com/square/leakcanary/releases/tag/v{{ leak_canary.next_release }}) to confirm everything looks good. 171 172* Upload shark-cli to [brew](https://brew.sh/): 173```bash 174brew bump-formula-pr --url https://github.com/square/leakcanary/releases/download/v{{ leak_canary.next_release }}/shark-cli-{{ leak_canary.next_release }}.zip leakcanary-shark 175``` 176 177* Wait for the release to be available [on Maven Central](https://repo1.maven.org/maven2/com/squareup/leakcanary/leakcanary-android/). 178* Tell your friends, update all of your apps, and tweet the new release. As a nice extra touch, mention external contributions. 179