-
Notifications
You must be signed in to change notification settings - Fork 125
Expand file tree
/
Copy pathbuild.gradle.kts
More file actions
644 lines (567 loc) · 26.5 KB
/
build.gradle.kts
File metadata and controls
644 lines (567 loc) · 26.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
import com.diffplug.gradle.spotless.SpotlessTask
import com.github.jk1.license.filter.LicenseBundleNormalizer
import com.github.jk1.license.render.InventoryMarkdownReportRenderer
import com.github.jk1.license.render.TextReportRenderer
import org.gradle.kotlin.dsl.support.unzipTo
import org.gradle.kotlin.dsl.support.zipTo
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
import proguard.gradle.ProGuardTask
import java.time.Instant
import java.util.Properties
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("com.guardsquare:proguard-gradle:7.4.0")
}
}
plugins {
kotlin("jvm") version "1.9.0"
java
`maven-publish`
// There are newer versions available, but they are not guaranteed to support Java 8.
id("io.github.gradle-nexus.publish-plugin") version "2.0.0"
jacoco
signing
id("com.github.johnrengelman.shadow") version "8.1.1"
id("org.cyclonedx.bom") version "1.7.2"
id("com.github.spotbugs") version "5.0.13"
id("org.jlleitschuh.gradle.ktlint") version "11.3.2"
id("com.diffplug.spotless") version "7.0.2"
// Used for generating the third party attribution document
id("com.github.jk1.dependency-license-report") version "2.5"
// Used for generating OSGi bundle information
// We cannot use the latest version since it targets JDK 17, and we don't want to force building with JDK 17
// Without `apply false`, the plugin is automatically applied to the main "jar" task, which somehow interferes with
// the "spotbugsMain" task, causing it to fail. Instead, we will create a separate task to generate the bundle info.
id("biz.aQute.bnd.builder") version "6.4.0" apply false
id("me.champeau.jmh") version "0.7.3"
}
jacoco {
toolVersion = "0.8.10+"
}
repositories {
mavenCentral()
google()
}
// This list should be kept up to date to include all LTS versions of Corretto.
// These are the versions that we guarantee are supported by `ion-java`, though it can probably run on other versions too.
val SUPPORTED_JRE_VERSIONS = listOf(8, 11, 17, 21)
java {
toolchain {
// Build with a consistent Java version so that builds are reproducible. We use the max version because the min
// is more likely to run into deprecation or compatibility issues with Gradle plugins.
// We still target the minimum supported Java version in compilation with the `--release` flag.
languageVersion.set(JavaLanguageVersion.of(SUPPORTED_JRE_VERSIONS.max()))
vendor.set(JvmVendorSpec.AMAZON)
}
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.0")
testImplementation("org.junit.jupiter:junit-jupiter:5.7.1")
testCompileOnly("junit:junit:4.13")
testRuntimeOnly("org.junit.vintage:junit-vintage-engine")
testImplementation("org.hamcrest:hamcrest:2.2")
testImplementation("pl.pragmatists:JUnitParams:1.1.1")
testImplementation("com.google.code.tempus-fugit:tempus-fugit:1.1")
testImplementation("com.github.luben:zstd-jni:1.5.6-5")
}
group = "com.amazon.ion"
// The version is stored in a separate file so that we can easily create CI workflows that run when the version changes
// and so that any tool can access the version without having to do any special parsing.
version = File(project.rootDir.path + "/project.version").readLines().single()
description = "A Java implementation of the Amazon Ion data notation."
val isCI: Boolean = System.getenv("CI") == "true"
val githubRepositoryUrl = "https://github.com/amazon-ion/ion-java/"
val isReleaseVersion: Boolean = !version.toString().endsWith("SNAPSHOT")
// Workflows triggered by a new release always have a tag ref.
val isReleaseWorkflow: Boolean = (System.getenv("GITHUB_REF") ?: "").startsWith("refs/tags/")
val generatedResourcesDir = layout.buildDirectory.dir("generated/main/resources")
sourceSets {
main {
resources.srcDir(generatedResourcesDir)
}
}
licenseReport {
// Because of the current gradle project structure, we must explicitly exclude ion-java-cli, even
// though ion-java does not depend on ion-java-cli. By default, the license report generator includes
// the current project (ion-java) and all its subprojects.
projects = arrayOf(project)
outputDir = layout.buildDirectory.dir("reports/licenses").get().asFile.path
renderers = arrayOf(InventoryMarkdownReportRenderer(), TextReportRenderer())
// Dependencies use inconsistent titles for Apache-2.0, so we need to specify mappings
filters = arrayOf(
LicenseBundleNormalizer(
mapOf(
"The Apache License, Version 2.0" to "Apache-2.0",
"The Apache Software License, Version 2.0" to "Apache-2.0",
)
)
)
}
// Spotless eagerly checks for the `rachetFrom` git ref even if there are no spotless tasks in the task
// graph, so we're going to use a git tag to create our own lazy evaluation and setting of `rachetFrom`.
// See https://github.com/diffplug/spotless/issues/1902
val SPOTLESS_TAG = "spotless-check-${Instant.now().epochSecond}-DELETE-ME"
/**
* This is the commit where the current branch most recently forked from master. We use this as
* our "rachetFrom" base so that changes in master don't cause unexpected formatting failures in
* feature branches.
*/
val sourceRepoRachetFromCommit: String by lazy {
val git = System.getenv("GIT_CLI") ?: "git"
fun String.isSourceRepo(): Boolean {
val url = "$git remote get-url ${this@isSourceRepo}".trim().runCommand()
return "amazon-ion/ion-java" in url || "amzn/ion-java" in url
}
var remoteName = "$git remote".runCommand().trim().lines().firstOrNull { it.isSourceRepo() }
if (isCI) {
// When running on a CI environment e.g. GitHub Actions, we might need to automatically add the remote
if (remoteName == null) {
remoteName = "ci_source_repository"
"$git remote add $remoteName $githubRepositoryUrl".runCommand(log = logger::quiet)
logger.quiet("Added remote repository ")
}
// ...and make sure that we have indeed fetched that remote
"$git fetch --unshallow --no-tags --no-recurse-submodules $remoteName master".runCommand()
}
remoteName ?: throw Exception(
"""
|No git remote found for amazon-ion/ion-java. Try again after running:
|
| git remote add -f <name> $githubRepositoryUrl
""".trimMargin()
)
// TODO: We might need to use the PR base ref when this is running as part of a CI check for a PR.
logger.quiet("Finding spotless ratchetFrom base...")
"$git merge-base $remoteName/master HEAD".runCommand(log = logger::quiet).trim()
}
fun String.runCommand(workingDir: File = rootProject.projectDir, log: (String) -> Unit = logger::info): String {
log("$ $this")
val parts = this.split("\\s".toRegex())
val proc = ProcessBuilder(*parts.toTypedArray())
.directory(workingDir)
.redirectOutput(ProcessBuilder.Redirect.PIPE)
.redirectError(ProcessBuilder.Redirect.PIPE)
.start()
proc.waitFor(30, TimeUnit.SECONDS)
val stdOut = proc.inputStream.bufferedReader().readText()
val stdErr = proc.errorStream.bufferedReader().readText()
if (stdOut.isNotBlank()) log(stdOut)
if (stdErr.isNotBlank()) logger.warn(stdErr)
if (proc.exitValue() != 0) {
throw Exception("Failed to run command: $this")
}
return stdOut
}
spotless {
// If this is an automated release workflow, don't configure any style checks.
// This is important because we're ratcheting from `master` and when we create
// a release that is not directly from `master`, the spotless checks can cause
// the release workflow to fail if `master` has any commits that are not in the
// release branch.
if (isReleaseWorkflow) return@spotless
"git tag -f $SPOTLESS_TAG".runCommand()
ratchetFrom(SPOTLESS_TAG)
// Make sure this always gets cleaned up. We can't do it inline here, so we'll do it once the task graph is created.
gradle.taskGraph.addTaskExecutionGraphListener { "git tag -d $SPOTLESS_TAG".runCommand() }
val shortFormLicenseHeader = """
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
""".trimIndent()
java {
// Note that the order of these is important. Each of these is an individual formatter
// that is applied sequentially.
licenseHeader(shortFormLicenseHeader)
removeUnusedImports()
}
kotlin {
licenseHeader(shortFormLicenseHeader)
}
}
// Tasks that must be visible outside the tasks block
lateinit var sourcesJar: AbstractArchiveTask
lateinit var javadocJar: AbstractArchiveTask
lateinit var minifyJar: ProGuardTask
tasks {
withType<JavaCompile> {
options.encoding = "UTF-8"
// https://docs.gradle.org/current/userguide/building_java_projects.html#sec:compiling_with_release
options.release = SUPPORTED_JRE_VERSIONS.min()
}
withType<KotlinCompile<KotlinJvmOptions>> {
kotlinOptions {
// Kotlin jvmTarget must match the JavaCompile release version
jvmTarget = "1.8"
}
}
jar {
archiveClassifier.set("original")
}
val generateManifest = create<aQute.bnd.gradle.Bundle>("generateManifest") {
// Create the manifest using the same sources as the regular jar.
from(jar.get().source)
archiveClassifier.set("manifest")
manifest {
attributes(
"Automatic-Module-Name" to "com.amazon.ion",
"Main-Class" to "com.amazon.ion.impl._Private_CommandLine",
"Build-Time" to "${Instant.now()}",
"Build-Version" to "$version",
)
}
// Sets OSGi bundle attributes
// See https://en.wikipedia.org/wiki/OSGi#Bundles for a minimal introduction to the bundle manifest
// See https://enroute.osgi.org/FAQ/520-bnd.html for a high level of what is the "bnd" tool
// If we ever expose any shaded classes, then the bundle info will need to be added after the shadow step.
// For now, though, generating the bundle info here results
bundle {
bnd(
"Bundle-License: https://www.apache.org/licenses/LICENSE-2.0.txt",
// These must be specified manually to keep the values the same as the pre-v1.9.5 values.
// What will happen if they change? I don't know, but possibly some sort of compatibility problem.
"Bundle-Name: com.amazon.ion:ion-java",
"Bundle-SymbolicName: com.amazon.ion.java",
// Exclusions must come first when specifying exports.
// We exclude the `apps`, `impl`, and `shaded_` packages and expose everything else.
"Export-Package: !com.amazon.ion.apps.*,!com.amazon.ion.impl.*,!com.amazon.ion.shaded_.*,com.amazon.ion.*",
// Limit imports to only this package so that we don't add in any kotlin imports.
// This line is not necessary if we create bundle info after shading (but that is more complex).
"Import-Package: com.amazon.ion.*",
// Removing the 'Private-Package' header because it is optional and was not present prior to v1.9.5
"-removeheaders: Private-Package",
)
}
// This is not strictly necessary, but it is nice to make the output of this task into a manifest-only jar.
doLast {
val temp = temporaryDir
unzipTo(temp, outputs.files.singleFile)
delete(fileTree(temp).matching { excludes.add("META-INF/MANIFEST.MF") })
zipTo(outputs.files.singleFile, temp)
}
}
// Creates a super jar of ion-java and its dependencies where all dependencies are shaded (moved)
// to com.amazon.ion_.shaded.are_you_sure_you_want_to_use_this
shadowJar {
val newLocation = "com.amazon.ion.shaded_.do_not_use"
archiveClassifier.set("shaded")
dependsOn(generateManifest, generateLicenseReport, cyclonedxBom)
from(generateLicenseReport.get().outputFolder)
relocate("kotlin", "$newLocation.kotlin")
relocate("org.jetbrains", "$newLocation.org.jetbrains")
relocate("org.intellij", "$newLocation.org.intellij")
dependencies {
// Remove all Kotlin metadata so that it looks like an ordinary Java Jar
exclude("**/*.kotlin_metadata")
exclude("**/*.kotlin_module")
exclude("**/*.kotlin_builtins")
// Eliminate dependencies' pom files
exclude("**/pom.*")
}
manifest.inheritFrom(generateManifest.manifest)
}
/**
* The `minifyJar` task uses Proguard to create a JAR that is smaller than the combined size of ion-java
* and its dependencies. This is the final JAR that is published to maven central.
*/
minifyJar = create<ProGuardTask>("minifyJar") proguardTask@{
group = "build"
val rulesPath = file("config/proguard/rules.pro")
val inputJarPath = shadowJar.get().outputs.files.singleFile
val outputJarPath = "build/libs/ion-java-$version.jar"
inputs.file(rulesPath)
inputs.file(inputJarPath)
outputs.file(outputJarPath)
dependsOn(shadowJar)
dependsOn(configurations.runtimeClasspath)
injars(inputJarPath)
outjars(outputJarPath)
configuration(rulesPath)
val javaHome = System.getProperty("java.home")
if (JavaVersion.current() == JavaVersion.VERSION_1_8) {
libraryjars("$javaHome/lib/jce.jar")
libraryjars("$javaHome/lib/rt.jar")
} else {
libraryjars(
mapOf("jarfilter" to "!**.jar", "filter" to "!module-info.class"),
"$javaHome/jmods/java.base.jmod"
)
}
}
build {
dependsOn(minifyJar)
}
generateLicenseReport {
doLast {
// We don't want the time in the generated markdown report because that makes it unstable for
// our verification of the THIRD_PARTY_LICENSES file.
val markdownReport = outputs.files.single().walk().single { it.path.endsWith(".md") }
val dateRegex = Regex("^_\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} \\w+_$")
// Reads the content of the markdown report, replacing the date line with an empty line, and
// trimming extra whitespace from the end of all other lines.
val newMarkdownContent = markdownReport.readLines()
.joinToString("\n") { if (it.matches(dateRegex)) "" else it.trimEnd() }
markdownReport.writeText(newMarkdownContent)
}
}
// Task to check whether the THIRD_PARTY_LICENSES file is still up-to-date.
val checkThirdPartyLicensesFile by register("checkThirdPartyLicensesFile") {
val thirdPartyLicensesFileName = "THIRD_PARTY_LICENSES.md"
val thirdPartyLicensesPath = "$rootDir/$thirdPartyLicensesFileName"
dependsOn(generateLicenseReport)
inputs.file(thirdPartyLicensesPath)
group = "verification"
description = "Verifies that $thirdPartyLicensesFileName is up-to-date."
doLast {
val generatedMarkdownReport = generateLicenseReport.get().outputs.files.single()
.walk().single { it.path.endsWith(".md") }
val generatedMarkdownReportContent = generatedMarkdownReport.readLines()
.filter { it.isNotBlank() }
.joinToString("\n")
val sourceControlledMarkdownReport = File(thirdPartyLicensesPath)
val sourceControlledMarkdownReportContent = sourceControlledMarkdownReport.readLines()
.filter { it.isNotBlank() }
.joinToString("\n")
if (sourceControlledMarkdownReportContent != generatedMarkdownReportContent) {
throw IllegalStateException(
"$thirdPartyLicensesPath is out of date.\n" +
"Please replace the file content with the content of $generatedMarkdownReport."
)
}
}
}
check {
dependsOn(checkThirdPartyLicensesFile)
}
javadoc {
// Suppressing Javadoc warnings is clunky, but there doesn't seem to be any nicer way to do it.
// https://stackoverflow.com/questions/62894307/option-xdoclintnone-does-not-work-in-gradle-to-ignore-javadoc-warnings
options {
this as StandardJavadocDocletOptions
addBooleanOption("Xdoclint:none", true)
addStringOption("Xmaxwarns", "1") // best we can do is limit warnings to 1
// Stops jquery from being included as a bundled dependency
this.noIndex(true)
}
}
ktlint {
version.set("0.40.0")
outputToConsole.set(true)
}
// spotbugs-gradle-plugin creates a :spotbugsTest task by default, but we don't want it
// see: https://github.com/spotbugs/spotbugs-gradle-plugin/issues/391
project.gradle.startParameter.excludedTaskNames.add(":spotbugsTest")
// same for :spotbugsJmh, we don't need to run Spotbugs on our JMH code
// Alternatively we *could* set the toolchain for this task as we do for :spotBugsMain, but this is easier.
project.gradle.startParameter.excludedTaskNames.add(":spotbugsJmh")
spotbugsMain {
launcher.set(
project.javaToolchains.launcherFor {
languageVersion.set(JavaLanguageVersion.of(SUPPORTED_JRE_VERSIONS.min()))
vendor.set(JvmVendorSpec.AMAZON)
}
)
val spotbugsBaselineFile = "$rootDir/config/spotbugs/baseline.xml"
val baselining = project.hasProperty("baseline") // e.g. `./gradlew :spotbugsMain -Pbaseline`
if (!baselining) {
baselineFile.set(file(spotbugsBaselineFile))
}
// The plugin only prints to console when no reports are configured
// See: https://github.com/spotbugs/spotbugs-gradle-plugin/issues/172
if (!baselining) {
reports.create("html").required.set(true)
} else {
// Note this path succeeds :spotbugsMain because *of course it does*
ignoreFailures = true
reports.create("xml") {
// Why bother? Otherwise we have kilobytes of workspace-specific absolute paths, statistics, etc.
// cluttering up the baseline XML and preserved in perpetuity. It would be far better if we could use
// the SpotBugs relative path support, but the way SpotBugs reporters are presently architected they
// drop the `destination` information long before Project.writeXML uses its presence/absence to
// determine whether to generate relative instead of absolute paths. So, contribute patch to SpotBugs or
// write own SpotBugs reporter in parallel or... do this.
// Improvements are definitely possible, but left as an exercise to the reader.
doLast {
// It would be super neat if we had some way to handle this xml processing directly inline, without
// generating a temp file or at least without shelling out.
// Use ant's xslt capabilities? Xalan? Saxon gradle plugin (eerohele)? javax.xml.transform?
// In the mean time... xsltproc!
exec {
commandLine(
"xsltproc",
"--output", spotbugsBaselineFile,
"$rootDir/config/spotbugs/baseline.xslt",
"${outputLocation.get()}"
)
}
}
}
}
}
sourcesJar = create<Jar>("sourcesJar") sourcesJar@{
archiveClassifier.set("sources")
from(sourceSets["main"].java.srcDirs)
}
javadocJar = create<Jar>("javadocJar") javadocJar@{
archiveClassifier.set("javadoc")
from(javadoc)
}
/**
* This task creates a properties file that will be included in the compiled jar. It contains information about
* the build/version of the library used in [com.amazon.ion.util.JarInfo]. See https://github.com/amazon-ion/ion-java/pull/433
* for why this is done with a properties file rather than the Jar manifest.
*/
val generateJarInfo by creating<Task> {
val propertiesFile = generatedResourcesDir.get().file("${project.name}.properties").asFile
doLast {
propertiesFile.parentFile.mkdirs()
val properties = Properties()
properties.setProperty("build.version", version.toString())
properties.setProperty("build.time", Instant.now().toString())
properties.store(propertiesFile.writer(), null)
}
outputs.file(propertiesFile)
}
processResources { dependsOn(generateJarInfo) }
jacocoTestReport {
dependsOn(test)
reports {
xml.required.set(true)
html.required.set(true)
}
doLast {
logger.quiet("Coverage report written to file://${reports.html.outputLocation.get()}/index.html")
}
}
fun Test.applyCommonTestConfig() {
group = "verification"
maxHeapSize = "1g" // When this line was added Xmx 512m was the default, and we saw OOMs
maxParallelForks = Math.max(1, Runtime.getRuntime().availableProcessors() / 2)
useJUnitPlatform()
}
test {
applyCommonTestConfig()
// report is always generated after tests run
finalizedBy(jacocoTestReport)
}
/**
* Runs the JUnit test on the shadow jar.
* Potentially useful for debugging issues that are not reproducible in the standard `test` task.
*/
register<Test>("shadowTest") {
applyCommonTestConfig()
classpath = project.configurations.testRuntimeClasspath.get() + project.sourceSets.test.get().output + shadowJar.get().outputs.files
dependsOn(minifyJar)
}
val jvmSpecificMinifyTests = SUPPORTED_JRE_VERSIONS.map {
// Run the JUnit tests on the minified jar using the given java version for setting up the JRE
register<Test>("minifyTest$it") {
javaLauncher.set(
project.javaToolchains.launcherFor {
languageVersion.set(JavaLanguageVersion.of(it))
vendor.set(JvmVendorSpec.AMAZON)
}
)
applyCommonTestConfig()
classpath = project.configurations.testRuntimeClasspath.get() + project.sourceSets.test.get().output + minifyJar.outputs.files
dependsOn(minifyJar)
}
}.toTypedArray()
/**
* Umbrella task for the JUnit tests on the minified jar for all supported JRE versions.
*
* This ensures that the built JAR will run properly on all the supported JREs. It is time-consuming
* to run all tests for each JRE, so they are not included in the `build` task. However, they are
* mandatory as a prerequisite for publishing any release.
*
* They should all be run in the CI workflow for every PR, but it is best if they run concurrently
* in separate workflow steps.
*/
val minifyTest = register<Task>("minifyTest") {
group = "verification"
dependsOn(jvmSpecificMinifyTests)
}
publish { dependsOn(minifyTest) }
withType<Sign> {
setOnlyIf { isReleaseVersion && (gradle.taskGraph.hasTask(":publish") || gradle.taskGraph.hasTask(":publishToSonatype")) }
}
cyclonedxBom {
dependsOn(jar)
includeConfigs.set(listOf("runtimeClasspath"))
}
withType<SpotlessTask> {
doFirst { "git tag -f $SPOTLESS_TAG $sourceRepoRachetFromCommit".runCommand() }
doLast { "git tag -d $SPOTLESS_TAG".runCommand() }
}
}
publishing {
publications.create<MavenPublication>("IonJava") {
artifact(sourcesJar)
artifact(javadocJar)
artifact(minifyJar.outJarFiles.single()) {
builtBy(minifyJar)
}
pom {
name.set("Ion Java")
description.set(project.description)
url.set(githubRepositoryUrl)
licenses {
license {
name.set("The Apache License, Version 2.0")
url.set("https://www.apache.org/licenses/LICENSE-2.0.txt")
}
}
developers {
developer {
name.set("Amazon Ion Team")
email.set("ion-team@amazon.com")
organization.set("Amazon Ion")
organizationUrl.set("https://github.com/amazon-ion")
}
}
scm {
connection.set("scm:git:git@github.com:amazon-ion/ion-java.git")
developerConnection.set("scm:git:git@github.com:amazon-ion/ion-java.git")
url.set("git@github.com:amazon-ion/ion-java.git")
}
}
}
}
nexusPublishing {
// Documentation for this plugin, see https://github.com/gradle-nexus/publish-plugin/blob/v2.0.0/README.md
// Updated for Central Portal migration
this.repositories {
sonatype {
nexusUrl.set(uri("https://ossrh-staging-api.central.sonatype.com/service/local/"))
snapshotRepositoryUrl.set(uri("https://central.sonatype.com/repository/maven-snapshots/"))
// For CI environments, the username and password should be stored in
// ORG_GRADLE_PROJECT_sonatypeUsername and ORG_GRADLE_PROJECT_sonatypePassword respectively.
if (!isCI) {
username.set(properties["ossrhUsername"].toString())
password.set(properties["ossrhPassword"].toString())
}
}
}
}
signing {
// Allow publishing to maven local even if we don't have the signing keys
// This works because when not required, the signing task will be skipped
// if signing.keyId, signing.password, signing.secretKeyRingFile, etc are
// not present in gradle.properties.
isRequired = isReleaseVersion
sign(publishing.publications["IonJava"])
}
afterEvaluate {
if (isCI) {
val signingKeyId: String? by project
val signingKey: String? by project
val signingPassword: String? by project
if (signingKeyId.isNullOrEmpty() || signingKey.isNullOrEmpty() || signingPassword.isNullOrEmpty()) {
logger.lifecycle("signing credentials unavailable; build artifacts will not be signed")
} else {
signing.useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)
}
}
}