-
Notifications
You must be signed in to change notification settings - Fork 0
/
GithubPackagesPublisherPlugin.kt
164 lines (147 loc) · 6.89 KB
/
GithubPackagesPublisherPlugin.kt
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
package io.github.andrewk2112.githubpackagespublisher
import io.github.andrewk2112.githubpackagespublisher.extensions.Properties
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.UnknownDomainObjectException
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin
import org.gradle.plugin.devel.GradlePluginDevelopmentExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import java.io.FileNotFoundException
import java.io.IOException
import java.util.Properties
/**
* Adds GitHub Packages publishing tasks for a [Project].
*
* Reads publishing configs with a higher priority from a file specified by Gradle properties first,
* tries to read publishing configs from Gradle properties as a fallback.
*
* Published artifacts include sources downloadable for clients.
*
* No utility or other modules from the main project are used to avoid circular dependencies.
*/
internal class GithubPackagesPublisherPlugin : Plugin<Project> {
// Public.
@Throws(Exception::class)
override fun apply(target: Project) {
val publishConfigs = try {
getPublishConfigs(target, readCustomPublishProperties(target))
} catch (exception: Exception) {
logPublishConfigsException(target, exception)
return
}
target.plugins.apply(MavenPublishPlugin::class.java)
// Strictly required to detect plugin projects and avoid empty metadata for publishing of non-plugin projects.
target.afterEvaluate {
target.extensions.configure(PublishingExtension::class.java) { publishing ->
// All JVM projects (including plugin projects) require manual configuration to include their sources.
if (isNonKotlinMultiPlatformProject(target)) {
ensureSourcesJarWillBeCreatedAndPublished(target)
// Simple JVM projects strictly require manual configuration, or no artifacts will be published.
if (isNonPluginProject(target)) {
configureArtifactPublication(target, publishing)
}
}
configurePublishingRepository(publishing, publishConfigs)
}
}
}
// Private.
/**
* Tries to read custom publish properties if a path to them was specified in Gradle properties,
* returns `null` otherwise.
*/
@Throws(FileNotFoundException::class, IOException::class)
private fun readCustomPublishProperties(project: Project): Properties? =
project.properties["github.publish.properties"]?.toString()
?.let { Properties(it) }
/**
* Gets all required [PublishConfigs], see [getPublishConfig].
*
* @throws IllegalStateException If any of required configs is missing.
*/
@Throws(IllegalStateException::class)
private fun getPublishConfigs(project: Project, customPublishProperties: Properties?) = PublishConfigs(
repositoryUrl = getPublishConfig(project, customPublishProperties, "github.publish.url"),
username = getPublishConfig(project, customPublishProperties, "github.publish.username"),
password = getPublishConfig(project, customPublishProperties, "github.publish.password")
)
/**
* Gets a config value from [customPublishProperties] by the [key],
* tries to get the same config from [Project.getProperties] if it's not present in the [customPublishProperties].
*
* @throws IllegalStateException If no config with the [key] was found.
*/
@Throws(IllegalStateException::class)
private fun getPublishConfig(project: Project, customPublishProperties: Properties?, key: String): String =
customPublishProperties?.getProperty(key)
?: project.properties[key]?.toString()
?: throw IllegalStateException("No required config present to configure GitHub Packages publishing: $key")
/**
* Logs any kinds of [exception]s describing why the preparation of [PublishConfigs] has failed.
*/
private fun logPublishConfigsException(project: Project, exception: Exception) {
project.logger.run {
warn(
"No configs for GitHub Packages publishing are provided or they can't be read:\n" +
"it's OK if you are not a publisher, otherwise inspect it with \"--info\" option"
)
info("The publishing has failed to be configured because:", exception)
}
}
/**
* Checks if the [project] doesn't declare any Gradle plugin.
*/
private fun isNonPluginProject(project: Project): Boolean =
project.extensions.findByType(GradlePluginDevelopmentExtension::class.java) == null
/**
* Checks if the [project] is not configured as a Kotlin Multiplatform one.
*/
private fun isNonKotlinMultiPlatformProject(project: Project): Boolean =
project.extensions.findByType(KotlinMultiplatformExtension::class.java) == null
/**
* Calls [JavaPluginExtension.withSourcesJar] for JVM projects
* to make sure a sources JAR will be created and published.
*/
@Throws(UnknownDomainObjectException::class)
private fun ensureSourcesJarWillBeCreatedAndPublished(project: Project) {
project.extensions.configure(JavaPluginExtension::class.java) {
it.withSourcesJar()
}
}
/**
* Setups all metadata to publish the target [project] with.
*
* Required only for simple JVM non-Gradle plugin projects.
*/
private fun configureArtifactPublication(project: Project, publishing: PublishingExtension) {
publishing.publications {
// Anything can be substituted instead of "maven" - it's just a publication name.
it.create("maven", MavenPublication::class.java) { publication ->
publication.apply {
groupId = project.group.toString()
artifactId = project.name
version = project.version.toString()
from(project.components.findByName("java")) // strictly required or no artifacts will be published
}
}
}
}
/**
* Applies all configurations to reach the destination repository for publishing.
*/
private fun configurePublishingRepository(publishing: PublishingExtension, publishConfigs: PublishConfigs) {
publishing.repositories.maven { repository ->
repository.apply {
name = "GitHubPackages"
setUrl(publishConfigs.repositoryUrl)
credentials {
it.username = publishConfigs.username
it.password = publishConfigs.password
}
}
}
}
}