Skip to content

Commit 9512576

Browse files
committed
Add github actions for releases + cleanup (#338)
* refactor request logic * move the retry logic to the http client * small cleanup + tests * remove invalid comment * add integration test support + IT for TmdbHttpClient * add github actions for releases + cleanup # Conflicts: # build.gradle.kts
1 parent b106179 commit 9512576

5 files changed

Lines changed: 162 additions & 59 deletions

File tree

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: build
1+
name: CI
22

33
on:
44
push:
@@ -9,6 +9,11 @@ on:
99
permissions:
1010
contents: read
1111

12+
# Cancel superseded runs on the same ref (e.g. rapid pushes or PR updates).
13+
concurrency:
14+
group: build-${{ github.ref }}
15+
cancel-in-progress: true
16+
1217
jobs:
1318
build:
1419
runs-on: ubuntu-latest
@@ -27,4 +32,4 @@ jobs:
2732
uses: gradle/actions/setup-gradle@v5
2833

2934
- name: Execute Gradle Build
30-
run: ./gradlew clean build --scan
35+
run: ./gradlew clean build

.github/workflows/release.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Release to Maven Central
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
- '!v*-SNAPSHOT' # snapshot tags are handled by the snapshot workflow
8+
workflow_dispatch:
9+
10+
permissions:
11+
contents: write # required to create the GitHub release
12+
13+
jobs:
14+
release:
15+
runs-on: ubuntu-latest
16+
17+
steps:
18+
- name: Checkout code
19+
uses: actions/checkout@v6
20+
21+
- name: Setup Java
22+
uses: actions/setup-java@v5
23+
with:
24+
java-version: 17
25+
distribution: corretto
26+
27+
- name: Setup Gradle
28+
uses: gradle/actions/setup-gradle@v5
29+
30+
- name: Publish to local staging repository
31+
run: ./gradlew clean publishMavenJavaPublicationToStagingRepository
32+
33+
- name: Deploy to Maven Central
34+
run: ./gradlew jreleaserDeploy
35+
env:
36+
JRELEASER_GPG_PUBLIC_KEY: ${{ secrets.GPG_PUBLIC_KEY }}
37+
JRELEASER_GPG_SECRET_KEY: ${{ secrets.GPG_SECRET_KEY }}
38+
JRELEASER_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
39+
JRELEASER_MAVENCENTRAL_USERNAME: ${{ secrets.MAVENCENTRAL_USERNAME }}
40+
JRELEASER_MAVENCENTRAL_PASSWORD: ${{ secrets.MAVENCENTRAL_PASSWORD }}
41+
42+
- name: Create GitHub release
43+
if: startsWith(github.ref, 'refs/tags/') # skip when running the workflow manually
44+
env:
45+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
46+
run: gh release create "${GITHUB_REF_NAME}" --generate-notes --verify-tag

.github/workflows/snapshot.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Publish Snapshot to Maven Central
2+
3+
on:
4+
push:
5+
tags: [ 'v*-SNAPSHOT' ]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
11+
jobs:
12+
snapshot:
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- name: Checkout code
17+
uses: actions/checkout@v6
18+
19+
- name: Setup Java
20+
uses: actions/setup-java@v5
21+
with:
22+
java-version: 17
23+
distribution: corretto
24+
25+
- name: Setup Gradle
26+
uses: gradle/actions/setup-gradle@v5
27+
28+
- name: Publish snapshot to Central Portal
29+
run: ./gradlew clean publishMavenJavaPublicationToCentralSnapshotsRepository
30+
env:
31+
MAVENCENTRAL_USERNAME: ${{ secrets.MAVENCENTRAL_USERNAME }}
32+
MAVENCENTRAL_PASSWORD: ${{ secrets.MAVENCENTRAL_PASSWORD }}

build.gradle.kts

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ plugins {
22
`java-library`
33
checkstyle
44
`maven-publish`
5-
signing
65
id("io.github.gradle-nexus.publish-plugin") version "2.0.0"
76
id("org.jreleaser") version "1.24.0"
87
}
@@ -22,7 +21,7 @@ dependencies {
2221
// testing
2322
testImplementation(platform("org.junit:junit-bom:6.1.0"))
2423
testImplementation("org.junit.jupiter:junit-jupiter")
25-
testRuntimeOnly("org.junit.platform:junit-platform-launcher") // gradle bundled version is incompatible with 5.12
24+
testRuntimeOnly("org.junit.platform:junit-platform-launcher") // pin launcher to junit-bom; Gradle's bundled one lags the JUnit version
2625

2726
testImplementation(platform("org.mockito:mockito-bom:5.23.0"))
2827
testImplementation("org.mockito:mockito-core")
@@ -42,10 +41,14 @@ dependencies {
4241
implementation("com.fasterxml.jackson.core:jackson-databind")
4342

4443
implementation("org.apache.commons:commons-lang3:3.20.0")
44+
4545
testImplementation("commons-io:commons-io:2.22.0")
4646
}
4747

4848
java {
49+
toolchain {
50+
languageVersion = JavaLanguageVersion.of(17)
51+
}
4952
withJavadocJar()
5053
withSourcesJar()
5154
}
@@ -99,14 +102,15 @@ publishing {
99102

100103
licenses {
101104
license {
102-
name = "BSD"
105+
name = "BSD-2-Clause"
103106
url = "https://github.com/c-eg/themoviedbapi/blob/master/LICENCE.txt"
104107
}
105108
}
106109

107110
scm {
108-
connection = "scm:git:github.com/c-eg/themoviedbapi.git"
109-
url = "https://github.com/c-eg/themoviedbapi.git"
111+
connection = "scm:git:https://github.com/c-eg/themoviedbapi.git"
112+
developerConnection = "scm:git:ssh://git@github.com/c-eg/themoviedbapi.git"
113+
url = "https://github.com/c-eg/themoviedbapi"
110114
}
111115

112116
developers {
@@ -126,9 +130,21 @@ publishing {
126130
}
127131
}
128132
repositories {
133+
// Local staging dir that JReleaser reads from for the signed release deploy.
129134
maven {
135+
name = "staging"
130136
url = uri(layout.buildDirectory.dir("staging-deploy"))
131137
}
138+
139+
// Central Portal snapshot repository.
140+
maven {
141+
name = "centralSnapshots"
142+
url = uri("https://central.sonatype.com/repository/maven-snapshots/")
143+
credentials {
144+
username = providers.environmentVariable("MAVENCENTRAL_USERNAME").orNull
145+
password = providers.environmentVariable("MAVENCENTRAL_PASSWORD").orNull
146+
}
147+
}
132148
}
133149
}
134150

@@ -137,9 +153,7 @@ jreleaser {
137153
pgp {
138154
active = org.jreleaser.model.Active.ALWAYS
139155
armored = true
140-
mode = org.jreleaser.model.Signing.Mode.FILE
141-
publicKey = "C:/gpg/public.pgp"
142-
secretKey = "C:/gpg/private.pgp"
156+
mode = org.jreleaser.model.Signing.Mode.MEMORY
143157
}
144158
}
145159
deploy {
@@ -155,20 +169,11 @@ jreleaser {
155169
}
156170
}
157171

158-
if (project.hasProperty("signing.keyId") && project.hasProperty("signing.password") && project.hasProperty("signing.secretKeyRingFile")) signing {
159-
sign(publishing.publications["mavenJava"])
160-
}
161-
162172
tasks.javadoc {
163-
if (JavaVersion.current().isJava9Compatible) {
164-
(options as StandardJavadocDocletOptions).addBooleanOption("html5", true)
165-
}
166-
}
167-
168-
tasks {
169-
javadoc {
170-
options {
171-
(this as CoreJavadocOptions).addBooleanOption("Xdoclint:none", true)
173+
options {
174+
(this as StandardJavadocDocletOptions).apply {
175+
addBooleanOption("Xdoclint:none", true)
176+
addBooleanOption("html5", true)
172177
}
173178
}
174179
}

devel_notes.md

Lines changed: 51 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,67 @@
11
# Developer Notes
2+
3+
Releases and snapshots are published automatically via GitHub Actions. The
4+
manual/local process is still possible and documented at the end as a fallback.
5+
26
## How to do a release?
37

4-
1. Make sure to increase version number in [build.gradle.kts](build.gradle.kts), commit and push the version to the `master` branch
8+
Releases are handled by the [Release to Maven Central](.github/workflows/release.yml)
9+
workflow, triggered by pushing a version tag.
10+
11+
1. Bump the version in [build.gradle.kts](build.gradle.kts) to the release value
12+
(e.g. `2.7.0`, **no** `-SNAPSHOT` suffix). Commit and push to `master`.
13+
14+
2. Create and push a matching `v<version>` tag:
15+
```bash
16+
git tag v2.7.0
17+
git push origin v2.7.0
18+
```
519

6-
2. Do the release on GitHub
20+
3. The workflow then automatically:
21+
- stages the artifacts,
22+
- GPG-signs them and deploys to Maven Central via JReleaser,
23+
- creates a GitHub release with auto-generated changelog notes.
724

8-
3. Make sure the prerequisites are met that are listed below
25+
4. Verify the deployment at the
26+
[Maven Central Repository](https://central.sonatype.com/publishing/deployments).
927

10-
4. Clean, publish and deploy
11-
```bash
12-
./gradlew clean && ./gradlew publish && ./gradlew jreleaserDeploy
13-
```
28+
> The git tag should match the version in `build.gradle.kts`. Snapshot-suffixed
29+
> tags (`v*-SNAPSHOT`) are ignored by this workflow and handled by the snapshot
30+
> workflow instead.
1431
15-
5. Go to [Maven Central Repository](https://central.sonatype.com/publishing/deployments) and verify the deployment was successful
32+
## How to publish a snapshot?
1633

34+
Snapshots are handled by the
35+
[Publish Snapshot to Maven Central](.github/workflows/snapshot.yml) workflow.
36+
They are deployed directly via `maven-publish` (no signing, no validation) to the
37+
[Central Portal snapshot repository](https://central.sonatype.com/repository/maven-snapshots/).
1738

18-
## Prerequisites
19-
### GPG & PGP Keys
20-
Make sure you have the following keys exist:
39+
1. Set the version in [build.gradle.kts](build.gradle.kts) to a `-SNAPSHOT` value
40+
(e.g. `2.7.0-SNAPSHOT`). Commit and push to `master`.
2141

22-
- `C:/gpg/private.pgp`
23-
- `C:/gpg/public.pgp`
24-
- `C:/gpg/secring.gpg`
42+
2. Trigger the workflow either by:
43+
- pushing a `v*-SNAPSHOT` tag (e.g. `v2.7.0-SNAPSHOT`), or
44+
- running it manually from the GitHub **Actions** tab (Run workflow).
2545

26-
### Gradle Properties
27-
Make sure you have the following in your global gradle.properties file `C:\Users\<user>\.gradle\gradle.properties`:
2846

29-
```properties
30-
signing.keyId = <value>
31-
signing.password = <value>
32-
signing.secretKeyRingFile = C:/gpg/secring.gpg
33-
```
47+
## Required GitHub repository secrets
3448

35-
### JReleaser Properties
36-
Make sure you have the following in your jreleaser.properties file `C:\Users\<user>\.jreleaser\config.properties`:
49+
The release and snapshot workflows read credentials from repository secrets
50+
(**Settings → Secrets and variables → Actions**):
3751

38-
```properties
39-
JRELEASER_GPG_PUBLIC_KEY = C:/gpg/public.pgp
40-
JRELEASER_GPG_SECRET_KEY = C:/gpg/private.pgp
41-
JRELEASER_GPG_PASSPHRASE = <value>
42-
JRELEASER_GITHUB_TOKEN = <value>
43-
JRELEASER_MAVENCENTRAL_SONATYPE_USERNAME = <value>
44-
JRELEASER_MAVENCENTRAL_SONATYPE_PASSWORD = <value>
45-
```
52+
| Secret | Used by | Description |
53+
|-------------------------|--------------------|------------------------------------------------------|
54+
| `GPG_PUBLIC_KEY` | release | ASCII-armored public key **contents** |
55+
| `GPG_SECRET_KEY` | release | ASCII-armored private key **contents** |
56+
| `GPG_PASSPHRASE` | release | Passphrase for the private key |
57+
| `MAVENCENTRAL_USERNAME` | release + snapshot | Sonatype Central Portal token username |
58+
| `MAVENCENTRAL_PASSWORD` | release + snapshot | Sonatype Central Portal token password |
4659

47-
Note: `JRELEASER_GITHUB_TOKEN` does not need a valid value, it just needs a non-empty value set.
60+
`GITHUB_TOKEN` is provided automatically by GitHub Actions; no secret needed.
4861

49-
If you are setting this up for the first time, you can verify your config is configured correctly with:
50-
```bash
51-
./gradlew jreleaserConfig
52-
```
62+
> Signing uses JReleaser **MEMORY** mode, so `GPG_PUBLIC_KEY` / `GPG_SECRET_KEY`
63+
> hold the armored key *contents*, not file paths. Export them with:
64+
> ```bash
65+
> gpg --armor --export <key-id> # -> GPG_PUBLIC_KEY
66+
> gpg --armor --export-secret-keys <key-id> # -> GPG_SECRET_KEY
67+
> ```

0 commit comments

Comments
 (0)