|
6 | 6 | branches: |
7 | 7 | - main |
8 | 8 |
|
| 9 | +permissions: |
| 10 | + contents: read |
| 11 | + pull-requests: read |
| 12 | + |
| 13 | +env: |
| 14 | + # Where releases go: streamRepo, central, or streamRepo,central. Central is a manual |
| 15 | + # escape hatch for a release that has to go out when the Stream repository cannot take it. |
| 16 | + PUBLISH_TARGETS: streamRepo |
| 17 | + |
9 | 18 | jobs: |
10 | 19 | Release: |
11 | 20 | name: 🚀 Release |
12 | 21 | if: github.event.pull_request.merged && startsWith(github.head_ref, 'release-') |
13 | 22 | runs-on: ubuntu-latest |
| 23 | + outputs: |
| 24 | + version: ${{ steps.version.outputs.version }} |
| 25 | + stream_repo: ${{ steps.version.outputs.stream_repo }} |
14 | 26 | steps: |
15 | | - - uses: actions/checkout@v3 |
| 27 | + - uses: actions/checkout@v4 |
16 | 28 | with: |
17 | 29 | fetch-depth: 0 |
18 | | - - uses: actions/setup-java@v3 |
| 30 | + - uses: actions/setup-java@v4 |
19 | 31 | with: |
20 | 32 | distribution: 'temurin' |
21 | 33 | java-version: '17' |
22 | | - - uses: actions/github-script@v5 |
23 | | - with: |
24 | | - script: | |
25 | | - const get_change_log_diff = require('./scripts/get_changelog_diff.js') |
26 | | - core.exportVariable('CHANGELOG', get_change_log_diff()) |
27 | 34 |
|
28 | | - // Getting the release version from the PR source branch |
29 | | - // Source branch looks like this: release-1.0.0 |
30 | | - const version = context.payload.pull_request.head.ref.split('-')[1] |
31 | | - core.exportVariable('VERSION', version) |
| 35 | + # Getting the release version (the tag) from the PR source branch |
| 36 | + # Source branch looks like this: release-v1.0.0 |
| 37 | + - name: Read the version |
| 38 | + id: version |
| 39 | + env: |
| 40 | + HEAD_REF: ${{ github.head_ref }} |
| 41 | + run: | |
| 42 | + echo "version=${HEAD_REF#release-}" >> "$GITHUB_OUTPUT" |
| 43 | + echo "stream_repo=${{ contains(env.PUBLISH_TARGETS, 'streamRepo') }}" >> "$GITHUB_OUTPUT" |
| 44 | +
|
| 45 | + - name: Write the signing keyring |
| 46 | + run: | |
| 47 | + sudo bash -c "echo '$GPG_KEY_CONTENTS' | base64 -d > '$SIGNING_SECRET_KEY_RING_FILE'" |
| 48 | + env: |
| 49 | + GPG_KEY_CONTENTS: ${{ secrets.GPG_KEY_CONTENTS }} |
| 50 | + SIGNING_SECRET_KEY_RING_FILE: ${{ secrets.SIGNING_SECRET_KEY_RING_FILE }} |
32 | 51 |
|
33 | 52 | - name: Build artifacts |
34 | 53 | run: ./gradlew jar javadocJar sourcesJar |
35 | 54 |
|
| 55 | + # An env var rather than -P, so a value with a space cannot split into a second argument. |
| 56 | + - name: Select publish targets |
| 57 | + run: echo "ORG_GRADLE_PROJECT_streamPublishTargets=$PUBLISH_TARGETS" >> "$GITHUB_ENV" |
| 58 | + |
| 59 | + # Stages a signed Maven-2 tree under build/staged-repo for the upload job. |
| 60 | + - name: Stage for the Stream repository |
| 61 | + if: ${{ contains(env.PUBLISH_TARGETS, 'streamRepo') }} |
| 62 | + run: ./gradlew publishReleasePublicationToStreamRepoStagingRepository --max-workers 1 |
| 63 | + env: |
| 64 | + STREAM_KEY: ${{ secrets.STREAM_KEY }} |
| 65 | + STREAM_SECRET: ${{ secrets.STREAM_SECRET }} |
| 66 | + STREAM_APP_ID: ${{ secrets.STREAM_APP_ID }} |
| 67 | + SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }} |
| 68 | + SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }} |
| 69 | + SIGNING_SECRET_KEY_RING_FILE: ${{ secrets.SIGNING_SECRET_KEY_RING_FILE }} |
| 70 | + |
36 | 71 | - name: Publish to MavenCentral |
37 | | - run: | |
38 | | - sudo bash -c "echo '$GPG_KEY_CONTENTS' | base64 -d > '$SIGNING_SECRET_KEY_RING_FILE'" |
39 | | - ./gradlew publishReleasePublicationToSonatypeRepository --max-workers 1 closeAndReleaseSonatypeStagingRepository |
| 72 | + if: ${{ contains(env.PUBLISH_TARGETS, 'central') }} |
| 73 | + run: ./gradlew publishReleasePublicationToSonatypeRepository --max-workers 1 closeAndReleaseSonatypeStagingRepository |
40 | 74 | env: |
41 | 75 | STREAM_KEY: ${{ secrets.STREAM_KEY }} |
42 | 76 | STREAM_SECRET: ${{ secrets.STREAM_SECRET }} |
43 | 77 | STREAM_APP_ID: ${{ secrets.STREAM_APP_ID }} |
44 | | - GPG_KEY_CONTENTS: ${{ secrets.GPG_KEY_CONTENTS }} |
45 | 78 | OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }} |
46 | 79 | OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} |
47 | 80 | SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }} |
48 | 81 | SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }} |
49 | 82 | SIGNING_SECRET_KEY_RING_FILE: ${{ secrets.SIGNING_SECRET_KEY_RING_FILE }} |
50 | 83 | SONATYPE_STAGING_PROFILE_ID: ${{ secrets.SONATYPE_STAGING_PROFILE_ID }} |
51 | 84 |
|
| 85 | + # Handed to a job that has never seen the signing key -- the reason Gradle stages to a |
| 86 | + # directory instead of writing to the bucket itself. |
| 87 | + - name: Hand the staged tree to the upload job |
| 88 | + if: ${{ contains(env.PUBLISH_TARGETS, 'streamRepo') }} |
| 89 | + uses: actions/upload-artifact@v4 |
| 90 | + with: |
| 91 | + name: stream-repo-staged |
| 92 | + path: build/staged-repo |
| 93 | + retention-days: 1 |
| 94 | + if-no-files-found: error |
| 95 | + |
| 96 | + # Separate job: secrets are injected per job, so this one holds the R2 credential and never the |
| 97 | + # signing key, and the Release job holds the signing key and never the R2 credential. |
| 98 | + Upload: |
| 99 | + name: ☁️ Upload to the Stream repository |
| 100 | + needs: Release |
| 101 | + if: ${{ needs.Release.outputs.stream_repo == 'true' }} |
| 102 | + runs-on: ubuntu-latest |
| 103 | + steps: |
| 104 | + - name: Download the staged tree |
| 105 | + uses: actions/download-artifact@v4 |
| 106 | + with: |
| 107 | + name: stream-repo-staged |
| 108 | + path: build/staged-repo |
| 109 | + |
| 110 | + - name: Publish to the Stream repository |
| 111 | + uses: GetStream/stream-build-conventions-android/.github/actions/publish-to-stream-repo@v1.0.1 |
| 112 | + with: |
| 113 | + staged-directory: build/staged-repo |
| 114 | + channel: releases |
| 115 | + endpoint: ${{ secrets.STREAM_REPO_ENDPOINT }} |
| 116 | + bucket: ${{ secrets.STREAM_REPO_BUCKET }} |
| 117 | + access-key-id: ${{ secrets.STREAM_REPO_ACCESS_KEY_ID }} |
| 118 | + secret-access-key: ${{ secrets.STREAM_REPO_SECRET_ACCESS_KEY }} |
| 119 | + |
| 120 | + # The tag and the GitHub release only once the artifact is actually resolvable: after the |
| 121 | + # upload when the Stream repository is a target, straight after publishing when it is not. |
| 122 | + GitHub-Release: |
| 123 | + name: 🏷️ Create the GitHub release |
| 124 | + needs: [Release, Upload] |
| 125 | + if: >- |
| 126 | + ${{ always() |
| 127 | + && needs.Release.result == 'success' |
| 128 | + && (needs.Upload.result == 'success' || needs.Upload.result == 'skipped') }} |
| 129 | + runs-on: ubuntu-latest |
| 130 | + permissions: |
| 131 | + # write is needed to create the tag and the GitHub release |
| 132 | + contents: write |
| 133 | + steps: |
| 134 | + - uses: actions/checkout@v4 |
| 135 | + |
| 136 | + - uses: actions/github-script@v7 |
| 137 | + with: |
| 138 | + script: | |
| 139 | + const get_change_log_diff = require('./scripts/get_changelog_diff.js') |
| 140 | + require('fs').writeFileSync('changes.md', get_change_log_diff()) |
| 141 | +
|
| 142 | + # Customers need a repository line to see a version that is not on Central. |
| 143 | + - name: Write the release notes |
| 144 | + env: |
| 145 | + TAG: ${{ needs.Release.outputs.version }} |
| 146 | + run: | |
| 147 | + VERSION="${TAG#v}" |
| 148 | + : > notes.md |
| 149 | + if [ "$PUBLISH_TARGETS" == "streamRepo" ]; then |
| 150 | + cat > notes.md <<EOF |
| 151 | + > [!IMPORTANT] |
| 152 | + > **\`io.getstream.client:stream-java:$VERSION\` is published to the Stream Maven repository, not Maven Central.** |
| 153 | + > |
| 154 | + > Gradle (\`build.gradle.kts\`): |
| 155 | + > \`\`\`kotlin |
| 156 | + > repositories { |
| 157 | + > mavenCentral() |
| 158 | + > maven("https://stream-io-repo.com") |
| 159 | + > } |
| 160 | + > \`\`\` |
| 161 | + > |
| 162 | + > Maven (\`pom.xml\`): |
| 163 | + > \`\`\`xml |
| 164 | + > <repositories> |
| 165 | + > <repository> |
| 166 | + > <id>stream</id> |
| 167 | + > <url>https://stream-io-repo.com</url> |
| 168 | + > </repository> |
| 169 | + > </repositories> |
| 170 | + > \`\`\` |
| 171 | +
|
| 172 | + EOF |
| 173 | + fi |
| 174 | + cat changes.md >> notes.md |
| 175 | +
|
52 | 176 | - name: Create release on GitHub |
53 | 177 | uses: ncipollo/release-action@v1 |
54 | 178 | with: |
55 | | - body: ${{ env.CHANGELOG }} |
56 | | - tag: ${{ env.VERSION }} |
| 179 | + bodyFile: notes.md |
| 180 | + tag: ${{ needs.Release.outputs.version }} |
| 181 | + commit: ${{ github.event.pull_request.merge_commit_sha }} |
57 | 182 | token: ${{ secrets.GITHUB_TOKEN }} |
0 commit comments