1
- import com.fasterxml.jackson.databind.MapperFeature
2
- import com.fasterxml.jackson.databind.SerializationFeature
3
- import com.fasterxml.jackson.databind.json.JsonMapper
4
- import com.fasterxml.jackson.databind.node.ArrayNode
5
- import com.fasterxml.jackson.databind.node.JsonNodeFactory
6
- import com.fasterxml.jackson.databind.node.ObjectNode
7
1
import com.vanniktech.maven.publish.JavadocJar.Dokka
8
2
import com.vanniktech.maven.publish.KotlinJvm
9
3
import com.vanniktech.maven.publish.MavenPublishBaseExtension
@@ -16,7 +10,7 @@ plugins {
16
10
}
17
11
18
12
dependencies {
19
- // Ignore transtive dependencies and instead manage explicitly.
13
+ // Ignore transitive dependencies and instead manage explicitly.
20
14
implementation(libs.awsDynamodbLocal) {
21
15
isTransitive = false
22
16
}
@@ -28,6 +22,7 @@ dependencies {
28
22
implementation(libs.kotlinStdLib)
29
23
30
24
// Shadow dependencies will not be shaded.
25
+ // https://gradleup.com/shadow/configuration/#configuring-the-runtime-classpath
31
26
shadow(libs.bundles.sqlite4java)
32
27
shadow(libs.aws2Dynamodb)
33
28
shadow(libs.aws2DynamodbEnhanced)
@@ -39,12 +34,18 @@ dependencies {
39
34
shadow(libs.slf4jApi)
40
35
}
41
36
42
- tasks.named< Jar >( " jar" ) {
37
+ tasks.jar {
43
38
archiveClassifier.set(" unshaded" )
44
39
}
45
40
46
41
tasks.shadowJar {
47
- // Dependencies to be shaded must be explicitly included as dependencies.
42
+ // https://gradleup.com/shadow/configuration/reproducible-builds/
43
+ isPreserveFileTimestamps = false
44
+ isReproducibleFileOrder = true
45
+
46
+ // Explicit allow-list of dependencies to be included. Without this block, _everything_ on runtimeClasspath would be
47
+ // included. An alternative would be an explicit deny-list, but this is seen as safer. Engineers should take care to
48
+ // update it when they update the dependencies of this project.
48
49
dependencies {
49
50
include(dependency(" com.amazonaws:DynamoDBLocal" ))
50
51
include(dependency(" com.fasterxml.jackson.core:.*" ))
@@ -78,82 +79,25 @@ tasks.shadowJar {
78
79
archiveClassifier = " "
79
80
}
80
81
81
- // Override all published JARs to point at the shadow jar
82
- listOf (configurations[" apiElements" ], configurations[" runtimeElements" ]).forEach {
83
- it.outgoing {
84
- artifacts.clear()
85
- artifact(tasks.named(" shadowJar" ))
86
- }
82
+ tasks.assemble {
83
+ dependsOn(tasks.shadowJar)
87
84
}
88
85
89
- // Post-process the gradle module metadata JSON to use the shadow JAR's dependencies as the runtime
90
- // dependencies in gradle builds.
91
- tasks.withType<GenerateModuleMetadata >().configureEach {
92
- doLast {
93
- try {
94
- outputFile.get().asFile.takeIf { it.exists() }?.let { moduleFile ->
95
- val mapper = JsonMapper .builder()
96
- .enable(SerializationFeature .INDENT_OUTPUT )
97
- .nodeFactory(JsonNodeFactory .withExactBigDecimals(true ))
98
- .configure(MapperFeature .SORT_PROPERTIES_ALPHABETICALLY , false )
99
- .configure(SerializationFeature .ORDER_MAP_ENTRIES_BY_KEYS , false )
100
- .build()
101
- val moduleJson = mapper.readTree(moduleFile) as ObjectNode
102
- val variants = moduleJson.get(" variants" ) as ArrayNode
103
-
104
- val shadowVariant = variants
105
- .elements().asSequence()
106
- .map { it as ObjectNode }
107
- .find { it.get(" name" ).asText() == " shadowRuntimeElements" }
108
- ? : throw NoSuchElementException (" could not find the `shadowRuntimeElements` variant!" )
109
-
110
- val runtimeVariant = variants
111
- .elements().asSequence()
112
- .map { it as ObjectNode }
113
- .find { it.get(" name" ).asText() == " runtimeElements" }
114
- ? : throw NoSuchElementException (" could not find the `runtimeElements` variant!" )
115
-
116
- runtimeVariant.replace(" dependencies" , shadowVariant.get(" dependencies" ))
117
-
118
- moduleFile.writeText(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(moduleJson))
119
- }
120
- } catch (e: Exception ) {
121
- throw GradleException (" could not post-process the module metadata!" , e)
86
+ val javaComponent = components[" java" ] as AdhocComponentWithVariants
87
+ listOf (" apiElements" , " runtimeElements" )
88
+ .map { configurations[it] }
89
+ .forEach { unpublishable ->
90
+ // Hide the un-shadowed variants in local consumption, by mangling their attributes
91
+ unpublishable.attributes {
92
+ attribute(Bundling .BUNDLING_ATTRIBUTE , objects.named(" DO_NOT_USE" ))
122
93
}
94
+
95
+ // Hide the un-shadowed variants in publishing
96
+ javaComponent.withVariantsFromConfiguration(unpublishable) { skip() }
123
97
}
124
- }
125
98
126
99
configure<MavenPublishBaseExtension > {
127
100
configure(
128
101
KotlinJvm (javadocJar = Dokka (" dokkaGfm" ))
129
102
)
130
-
131
- pom {
132
- withXml {
133
- val root = asNode()
134
-
135
- // First collect all dependencies nodes.
136
- val dependenciesNodes = root.children()
137
- .filterIsInstance< groovy.util.Node > ()
138
- .filter { it.name().toString().contains(" dependencies" ) }
139
- .toList()
140
-
141
- // Then remove them safely.
142
- dependenciesNodes.forEach { node ->
143
- root.remove(node)
144
- }
145
-
146
- // Add a new dependencies node with shadow configuration.
147
- val dependenciesNode = root.appendNode(" dependencies" )
148
-
149
- // Add all shadow dependencies to the POM.
150
- project.configurations.named(" shadow" ).get().allDependencies.forEach { dep ->
151
- val dependencyNode = dependenciesNode.appendNode(" dependency" )
152
- dependencyNode.appendNode(" groupId" , dep.group)
153
- dependencyNode.appendNode(" artifactId" , dep.name)
154
- dependencyNode.appendNode(" version" , dep.version)
155
- dependencyNode.appendNode(" scope" , " compile" )
156
- }
157
- }
158
- }
159
103
}
0 commit comments