diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a6f769c4..8436c0a2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -84,13 +84,17 @@ jobs: #Deployment - name: Deploy - if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev' + if: github.ref == 'refs/heads/main' env: ORG_GRADLE_PROJECT_signingKey: ${{ secrets.MAVENCENTRAL_SIGNINGKEY }} ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.MAVENCENTRAL_SIGNINGPASS }} - ORG_GRADLE_PROJECT_user: ${{ secrets.MAVENCENTRAL_USER }} - ORG_GRADLE_PROJECT_password: ${{ secrets.MAVENCENTRAL_PASS }} + ORG_GRADLE_PROJECT_mavenCentralUser: ${{ github.actor == 'sebastian-peter' && secrets.MAVENCENTRAL_USER || + github.actor == 'danielfeismann' && secrets.MAVENCENTRAL_DANIEL_USER }} + ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ github.actor == 'sebastian-peter' && secrets.MAVENCENTRAL_PASS || + github.actor == 'danielfeismann' && secrets.MAVENCENTRAL_DANIEL_PASS }} + run: | + echo "Using MavenCentral Token of GitHub Actor: ${{ github.actor }}" if [ "${GITHUB_REF}" == "refs/heads/main" ]; then currentVersion=$(./gradlew -q currentVersion) else @@ -100,3 +104,18 @@ jobs: echo "currentVersion=$currentVersion" ./gradlew publish -PdeployVersion=$currentVersion + + + #MavenCentral Staging + - name: MavenCentral Staging + if: github.ref == 'refs/heads/main' + env: + ORG_GRADLE_PROJECT_signingKey: ${{ secrets.MAVENCENTRAL_SIGNINGKEY }} + ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.MAVENCENTRAL_SIGNINGPASS }} + ORG_GRADLE_PROJECT_mavenCentralUser: ${{ github.actor == 'sebastian-peter' && secrets.MAVENCENTRAL_USER || + github.actor == 'danielfeismann' && secrets.MAVENCENTRAL_DANIEL_USER }} + ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ github.actor == 'sebastian-peter' && secrets.MAVENCENTRAL_PASS || + github.actor == 'danielfeismann' && secrets.MAVENCENTRAL_DANIEL_PASS }} + + run: | + ./gradlew stagingAtMavenCentralPortal diff --git a/CHANGELOG.md b/CHANGELOG.md index 34c04fc8..0067862a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added Marius Staudt to list of reviewers [#516](https://github.com/ie3-institute/OSMoGrid/issues/501) - Create `CITATION.cff` [#531](https://github.com/ie3-institute/OSMoGrid/issues/531) - Implemented GitHub Actions Pipeline [#545](https://github.com/ie3-institute/OSMoGrid/issues/545) +- Added `mavenCentralPublish.gradle` to enable deployment to MavenCentral [#568](https://github.com/ie3-institute/OSMoGrid/issues/568) - Implementing auto-merge for dependabot PRs [#556](https://github.com/ie3-institute/OSMoGrid/issues/566) ### Changed diff --git a/build.gradle b/build.gradle index 2732c684..3652d75f 100644 --- a/build.gradle +++ b/build.gradle @@ -46,6 +46,8 @@ apply from: scriptsLocation + 'scoverage.gradle' // scoverage scala code coverag apply from: scriptsLocation + 'vcs.gradle' apply from: scriptsLocation + 'semVer.gradle' apply from: scriptsLocation + 'tscfg.gradle' +apply from: scriptsLocation + 'uploadToMavenCentralPortal.gradle' // upload for deploy +apply from: scriptsLocation + 'stagingAtMavenCentralPortal.gradle' // stage for deploy apply from: scriptsLocation + 'branchName.gradle' // checks naming scheme of branches configurations { @@ -146,9 +148,8 @@ tasks.withType(Javadoc){ options.encoding = 'UTF-8' } -task printVersion { +tasks.register("printVersion") { doLast { println project.version } } - diff --git a/gradle/scripts/stagingAtMavenCentralPortal.gradle b/gradle/scripts/stagingAtMavenCentralPortal.gradle new file mode 100644 index 00000000..3ed6a673 --- /dev/null +++ b/gradle/scripts/stagingAtMavenCentralPortal.gradle @@ -0,0 +1,39 @@ +tasks.register('stagingAtMavenCentralPortal') { + group = 'publishing' + description = 'Stages uploaded artifacts to Maven Central Portal for manual approval' + + doLast { + def username = project.getProperty('mavenCentralUser') + def password = project.getProperty('mavenCentralPassword') + def deployVersion = project.findProperty('deployVersion') ?: project.version + + if (!username || !password) { + throw new GradleException("Sonatype credentials not found. Set sonatypeUser and sonatypePassword properties or environment variables.") + } + + // Request API for repo key + def repositoryString = providers.exec { + commandLine 'curl', + '-u', "${username}:${password}", + 'https://ossrh-staging-api.central.sonatype.com/manual/search/repositories' + }.getStandardOutput().getAsText().get() + + def repositoryGroovy = new groovy.json.JsonSlurper().parseText(repositoryString) + def key = repositoryGroovy.repositories[0].key + + // Stage via curl + def stageResult = providers.exec { + ignoreExitValue true + commandLine 'curl', + '-u', "${username}:${password}", + '-i', '-X', 'POST', "https://ossrh-staging-api.central.sonatype.com/manual/upload/repository/$key" + } + + if (stageResult.result.get().exitValue == 0) { + println "✓ Staging successful!" + println "Check status at: https://central.sonatype.com/publishing/deployments" + } else { + throw new GradleException("Staging failed") + } + } +} \ No newline at end of file diff --git a/gradle/scripts/uploadToMavenCentralPortal.gradle b/gradle/scripts/uploadToMavenCentralPortal.gradle new file mode 100644 index 00000000..eeb68e2f --- /dev/null +++ b/gradle/scripts/uploadToMavenCentralPortal.gradle @@ -0,0 +1,107 @@ +/* Maven publish - start */ + +tasks.register("sourcesJar", Jar) { + archiveClassifier.set("sources") + from sourceSets.main.allJava +} + +tasks.register("javadocJar", Jar) { + dependsOn tasks.named("javadoc", Javadoc) + archiveClassifier.set("javadoc") + from { tasks.named("javadoc", Javadoc).get().destinationDir } +} + +if (project.hasProperty('mavenCentralUser') && project.hasProperty('mavenCentralPassword') && project.hasProperty('deployVersion')) { + + // snapshot version differs from normal version + String versionString = project.getProperty('deployVersion') + + publishing { + publications { + create("mavenJava", MavenPublication) { + + versionMapping { + // resolves dynamic versioning to current version number + usage('java-api') { + fromResolutionOf('runtimeClasspath') + } + usage('java-runtime') { + fromResolutionResult() + } + } + pom { + description = 'OSMoGrid - a tool to generate life like electrical grid models based on publicly available data, mainly OpenStreetMap.' + name = 'OSMoGrid' + url = 'https:github.com/ie3-institute/OSMoGrid' + organization { + name = 'Institute of Energy Systems, Energy Efficiency and Energy Economics (ie3)/TU Dortmund University' + url = 'https:www.ie3.tu-dortmund.de/' + } + issueManagement { + system = 'GitHub' + url = 'https:github.com/ie3-institute/OSMoGrid/issues' + } + licenses { + license { + name = 'BSD 3-Clause License' + url = 'https:github.com/ie3-institute/OSMoGrid/blob/master/LICENSE' + } + } + developers { + developer { + organization = "Institute of Energy Systems, Energy Efficiency and Energy Economics (ie3)/TU Dortmund University" + organizationUrl = "https:ie3.etit.tu-dortmund.de" + } + } + scm { + connection = 'scm:git:git:github.com/ie3-institute/OSMoGrid.git' + developerConnection = 'scm:git:ssh:github.com:ie3-institute/OSMoGrid.git' + url = 'https:github.com/ie3-institute/OSMoGrid' + } + } + + removeTestDependenciesFromPom(pom) + groupId = group + artifactId = 'OSMoGrid' + version = versionString + + from components.java + artifact sourcesJar + artifact javadocJar + } + } + repositories { + maven { + name = "MavenCentral" + url = "https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/" + credentials { + username = project.findProperty('mavenCentralUser') + password = project.findProperty('mavenCentralPassword') + } + } + } + signing { + useInMemoryPgpKeys( + findProperty('signingKey') as String, + findProperty('signingPassword') as String + ) + sign publications.mavenJava + } + } + + tasks.named("generatePomFileForMavenJavaPublication") { + destination = layout.buildDirectory.file("generated-pom.xml").get().asFile + } +} + +def removeTestDependenciesFromPom(pom) { + pom.withXml { + def root = asNode() + // eliminate test-scoped dependencies (no need in maven central POMs) + root.dependencies.removeAll { dep -> + dep.scope == "test" + } + } +} + +/* Maven publish - end */