Skip to content

Commit fdd6c9b

Browse files
authored
feat: 1588 publish to maven central (#1596)
Added steps to publish_assets.yml to push to Sonatype. Modified gradle config to sign artefacts and push.
1 parent 85beb70 commit fdd6c9b

File tree

7 files changed

+201
-41
lines changed

7 files changed

+201
-41
lines changed

.github/workflows/publish_assets.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ name: Upload Release Assets
33
on:
44
release:
55
types: [ prereleased, released ]
6+
workflow_dispatch:
67

78
jobs:
89
upload-release-assets:
@@ -21,9 +22,11 @@ jobs:
2122
distribution: 'zulu'
2223

2324
- name: Generate CLI jar
25+
if: github.event_name == 'release'
2426
run: ./gradlew shadowJar
2527

2628
- name: Upload JAR Asset
29+
if: github.event_name == 'release'
2730
uses: actions/upload-release-asset@v1
2831
env:
2932
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -34,9 +37,11 @@ jobs:
3437
asset_content_type: application/java-archive
3538

3639
- name: Generate rules.json
40+
if: github.event_name == 'release'
3741
run: ./gradlew webClientRulesJSON
3842

3943
- name: Upload rules.json asset
44+
if: github.event_name == 'release'
4045
uses: actions/upload-release-asset@v1
4146
env:
4247
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -47,12 +52,15 @@ jobs:
4752
asset_content_type: application/json
4853

4954
- name: Generate JavaDocs
55+
if: github.event_name == 'release'
5056
run: ./gradlew aggregateJavadoc
5157

5258
- name: Zip JavaDocs
59+
if: github.event_name == 'release'
5360
run: zip -r javadocs.zip build/docs/aggregateJavadoc
5461

5562
- name: Upload zipped Javadocs
63+
if: github.event_name == 'release'
5664
uses: actions/upload-release-asset@v1
5765
env:
5866
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -62,3 +70,32 @@ jobs:
6270
asset_name: javadocs.zip
6371
asset_content_type: application/zip
6472

73+
# The following steps will publish artifacts to a sonatype staging repo with the aim of promoting them to maven central
74+
# Pretty much everything is done through gradle.
75+
# The version used will be according to the axion-release-plugin, meaning it will take a tag if present.
76+
# The tag should follow semantic versioning, e.g. v1.2.3. There could be a suffix, e.g. v1.2.3-TEST
77+
# gradle will build, sign then upload artifacts to a Sonatype staging repo.
78+
# See https://s01.oss.sonatype.org for accessing these repos.
79+
# At this point it should manually be closed, which will trigger acceptance tests for maven central (but not transfer yet)
80+
# Once closed, the repo is available for testing.
81+
# After testing, it can be manually promoted on the sonatype site, which will then publish to maven central.
82+
# Note than once in maven central a release cannot be removed or altered.
83+
84+
- name: Load secrets from 1Password
85+
id: onepw_secrets
86+
uses: 1password/[email protected]
87+
with:
88+
export-env: true # Export loaded secrets as environment variables
89+
env:
90+
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} # This is required to connect to the vault in our 1Password account.
91+
MAVEN_GPG_PRIVATE_KEY: "op://rbiv7rvkkrsdlpcrz3bmv7nmcu/yztcx47yzp4vizjyaq7ulvkgoi/Private Key"
92+
MAVEN_GPG_PASSPHRASE: "op://rbiv7rvkkrsdlpcrz3bmv7nmcu/yztcx47yzp4vizjyaq7ulvkgoi/password"
93+
94+
- name: Build and Publish to Sonatype
95+
run: |
96+
# The gradle java verifying plugin does not work with java 17.
97+
# Don't verify since it has already been done when the PR was created.
98+
./gradlew publish -x verifyGoogleJavaFormat
99+
env:
100+
SONATYPE_USERNAME: ${{secrets.SONATYPE_USERNAME}}
101+
SONATYPE_PASSWORD: ${{secrets.SONATYPE_PASSWORD}}

build.gradle

Lines changed: 113 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,21 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
16+
/*
17+
* A note about publishing and signing.
18+
* Maven central requires that artifacts be signed. And upload is done to Sonatype.
19+
* To publish you will need these environment variables defined:
20+
* SONATYPE_USERNAME
21+
* SONATYPE_PASSWORD
22+
* MAVEN_GPG_PRIVATE_KEY
23+
* MAVEN_GPG_PASSPHRASE
24+
* Suggestion is to put these in a shell script with restricted read permissions, then source it before calling
25+
* ./gradlew publish.
26+
*/
1727
plugins {
1828
id 'java'
29+
id 'maven-publish'
30+
id 'signing'
1931
id 'test-report-aggregation'
2032
id 'com.github.sherter.google-java-format' version '0.9'
2133
id "io.freefair.aggregate-javadoc" version "6.4.3"
@@ -24,7 +36,7 @@ plugins {
2436

2537
// Setup and configure properties that are consistent across all projects, including sub-modules.
2638
allprojects {
27-
group 'org.mobilitydata'
39+
group 'org.mobilitydata.gtfs-validator'
2840

2941
// Per the axion-release plugin, this computes the project version based
3042
// on the most recent tag in the repo.
@@ -66,6 +78,105 @@ allprojects {
6678
}
6779
}
6880

81+
subprojects {
82+
apply plugin: 'java'
83+
84+
// Cannot publish a SNAPSHOT. The provided sonatype url will not accept it.
85+
tasks.withType(PublishToMavenRepository).all { task ->
86+
task.onlyIf {
87+
if (project.version.toString().contains('SNAPSHOT')) {
88+
throw new GradleException("Publishing is not allowed for SNAPSHOT versions. Currently " + project.version)
89+
}
90+
true
91+
}
92+
}
93+
94+
task javadocJar(type: Jar) {
95+
archiveClassifier.set('javadoc')
96+
from javadoc
97+
}
98+
99+
task sourcesJar(type: Jar) {
100+
archiveClassifier.set('sources')
101+
from sourceSets.main.allSource
102+
}
103+
104+
// These modules require the same publishing configuration, apart from the name of the module
105+
// Also we want to limit artefact publishing to these modules.
106+
if (project.name == 'main' ||
107+
project.name == 'core' ||
108+
project.name == 'model') {
109+
def fullProjectName = 'gtfs-validator-' + project.name
110+
111+
afterEvaluate {
112+
publishing {
113+
repositories {
114+
// This is the sonatype staging repo for maven.
115+
// Once uploaded, the repo needs to be manually closed, which will trigger acceptance tests for
116+
// maven central (but not transfer yet).
117+
// Once successfully closed, the repo is available for testing.
118+
// After testing, it can be manually promoted on the sonatype site, which will then publish to maven central.
119+
maven {
120+
url = 'https://s01.oss.sonatype.org/service/local/staging/deploy/maven2'
121+
credentials {
122+
username System.getenv("SONATYPE_USERNAME")
123+
password System.getenv("SONATYPE_PASSWORD")
124+
}
125+
}
126+
}
127+
128+
publications {
129+
mavenJava(MavenPublication) {
130+
from components.java
131+
artifactId = fullProjectName
132+
133+
artifact sourcesJar
134+
artifact javadocJar
135+
136+
// Definition of the pom that will be included with the uploaded artifacts.
137+
pom {
138+
name = fullProjectName
139+
description = 'The ' + project.name + " artifacts from the gtfs validator"
140+
url = 'https://github.com/MobilityData/gtfs-validator'
141+
licenses {
142+
license {
143+
name = 'The Apache License, Version 2.0'
144+
url = 'https://github.com/MobilityData/gtfs-validator/blob/master/LICENSE'
145+
}
146+
}
147+
developers {
148+
developer {
149+
id = 'dev'
150+
name = 'Dev group'
151+
152+
}
153+
}
154+
scm {
155+
connection = 'scm:git:git://github.com/MobilityData/gtfs-validator.git'
156+
developerConnection = 'scm:git:ssh://github.com/MobilityData/gtfs-validator.git'
157+
url = 'https://github.com/MobilityData/gtfs-validator'
158+
}
159+
}
160+
}
161+
}
162+
}
163+
signing {
164+
useInMemoryPgpKeys(System.getenv('MAVEN_GPG_PRIVATE_KEY'), System.getenv('MAVEN_GPG_PASSPHRASE'))
165+
sign publishing.publications.mavenJava
166+
}
167+
}
168+
169+
}
170+
compileJava {
171+
options.compilerArgs << '-parameters'
172+
}
173+
174+
compileTestJava {
175+
options.compilerArgs << '-parameters'
176+
}
177+
178+
}
179+
69180
reporting {
70181
reports {
71182
// Necessary for unit test result aggregation.

core/build.gradle

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,13 @@
1717
plugins {
1818
id 'java'
1919
id 'maven-publish'
20+
id 'signing'
2021
}
2122

23+
//publishing {
24+
// publishing and signing are done in gtfs-validator build.gradle to minimize repetition
25+
//}
26+
2227
dependencies {
2328
implementation project(':model')
2429
annotationProcessor project(':processor:notices')
@@ -50,21 +55,3 @@ jar {
5055
'Implementation-Version': project.version)
5156
}
5257
}
53-
54-
publishing {
55-
publications {
56-
mavenJava(MavenPublication) {
57-
artifactId = 'gtfs-validator-core'
58-
59-
from components.java
60-
}
61-
}
62-
}
63-
64-
compileJava {
65-
options.compilerArgs << '-parameters'
66-
}
67-
68-
compileTestJava {
69-
options.compilerArgs << '-parameters'
70-
}

docs/RELEASE.md

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,43 @@ is:pr is:closed merged:>2020-07-28 base:master sort:updated-desc
3333

3434
💡 For more details on versioning, see [Understanding Maven Version Numbers](https://docs.oracle.com/middleware/1212/core/MAVEN/maven_version.htm#MAVEN8855).
3535

36-
### 3. Remove all `sha` Docker images added since last release
36+
### 4. Remove all `sha` Docker images added since last release
3737
1. Find the [list of Docker images for this project.](https://github.com/orgs/MobilityData/packages/container/gtfs-validator/versions)
3838
1. Delete all `sha`tagged Docker images added since last release.
3939
![grhc preview](https://user-images.githubusercontent.com/35747326/100006687-e1b5d080-2d98-11eb-846d-af12fbd7ca9f.png)
4040
**⚠️ Note: this manipulation can only be done by someone whose GitHub account has `Admin` access rights over the `gtfs-validator` package.**
4141

42-
### 3. Update the release number in the wiki
42+
### 5. Update the release number in the wiki
4343
By updating the version number in the project's wiki, users of the app will be advised to upgrade if their local version does not match.
4444
Update [this page](https://github.com/MobilityData/gtfs-validator/wiki/Current-Version) with the new version.
45+
46+
### 6. Publishing to Maven Central
47+
* Maven central is a repository used by developers to download libraries that can be used in their own development.
48+
* We upload some jars (currently gtfs-validator-main, gtfs-validator-core and gtfs-validator-model) there to make them available.
49+
Uploaded artefacts have versions.
50+
* Publication to Maven Central requires some manual operations.
51+
52+
* Typically when doing a release the publish_assets.yml Github action is automatically run.
53+
This will upload some assets
54+
to be available on the release page itself (see for example [Release 4.1.0 assets](https://github.com/MobilityData/gtfs-validator/releases/tag/v4.1.0#:~:text=7%20other%20contributors-,Assets,-6))
55+
56+
57+
* This Github action also publishes to Sonatype. This is used as a staging area before making the arftefacts available via Maven Central.
58+
* See [Sonatype Staging Repositories](https://s01.oss.sonatype.org/#stagingRepositories) (login required)
59+
* There should be a repository in the list with name orgmobilitydata-####. This is automatically created by Sonatype when files are uploaded.
60+
61+
![image](https://github.com/MobilityData/gtfs-validator/assets/106176106/f08a24ec-addb-4d63-840d-24297c505822)
62+
63+
64+
* You can browse the repo content to make sure everything is there. In particular there should be the jars for the code, jars for javadoc, for sources, and files for the maven pom.
65+
* Everything should be signed, as evidenced by the presence of files with extension .sha1, .sha256, .sha512 etc.
66+
* Also make sure the version is correct.
67+
* You then need to manually close the repo. Doing this will trigger acceptance tests for Maven Central.
68+
69+
![image](https://github.com/MobilityData/gtfs-validator/assets/106176106/1d8916c6-a640-43cf-9658-82193d127b1d)
70+
71+
* Once the repository is closed it becomes available for inclusion in projects for testing. The URL to use as repository in your gradle or maven configuration files can be found in the summary for the repo.
72+
![image](https://github.com/MobilityData/gtfs-validator/assets/106176106/c809c1ca-67d7-4c45-bfa5-47441e163d2f)
73+
74+
* Once satisfied with the testing, the repo can be released to Maven Central.
75+
* Note that once a release is deployed on Maven Central, it cannot be removed or modified. If problems are detected after this stage, a new release with a different version has to be created.

main/build.gradle

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,12 @@
1717
plugins {
1818
id 'java'
1919
id 'maven-publish'
20+
id 'signing'
2021
}
2122

22-
publishing {
23-
publications {
24-
mavenJava(MavenPublication) {
25-
artifactId = 'gtfs-validator-main'
26-
27-
from components.java
28-
}
29-
}
30-
}
23+
//publishing {
24+
// publishing and signing are done in gtfs-validator build.gradle to minimize repetition
25+
//}
3126

3227
dependencies {
3328
annotationProcessor project(':processor:notices')

model/build.gradle

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
plugins {
22
id 'java'
3+
id 'maven-publish'
4+
id 'signing'
35
}
46

7+
//publishing {
8+
// publishing and signing are done in gtfs-validator build.gradle to minimize repetition
9+
//}
10+
11+
512
dependencies {
613
annotationProcessor 'com.google.auto.value:auto-value:1.7.4'
714
compileOnly 'com.google.auto.value:auto-value-annotations:1.7.4'
815
implementation 'org.jetbrains:annotations:20.1.0'
916
implementation 'com.google.code.findbugs:jsr305:3.0.2'
1017
}
11-
12-
compileJava {
13-
options.compilerArgs << '-parameters'
14-
}
15-
16-
compileTestJava {
17-
options.compilerArgs << '-parameters'
18-
}

model/src/main/java/org/mobilitydata/gtfsvalidator/annotation/CurrencyAmount.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
package org.mobilitydata.gtfsvalidator.annotation;
1818

1919
/**
20-
* Generates a {@link org.mobilitydata.gtfsvalidator.notice.InvalidCurrencyAmountNotice} for a
21-
* currency amount value that does not match the specification of its currency code.
20+
* Generates a InvalidCurrencyAmountNotice for a currency amount value that does not match the
21+
* specification of its currency code.
2222
*
2323
* <p>Example.
2424
*

0 commit comments

Comments
 (0)