Skip to content

Commit 99018ff

Browse files
committed
Publishing: Gitlab support
Add support for publishing [Helm charts in the Gitlab Package Registry](https://docs.gitlab.com/ee/user/packages/helm_repository/#helm-charts-in-the-package-registry).
1 parent d9ae913 commit 99018ff

File tree

3 files changed

+136
-1
lines changed

3 files changed

+136
-1
lines changed

docs/publishing-charts.adoc

+42-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ The `helm-publish` plugin allows you to publish your charts to remote repositori
66
====
77
There is currently no "official" API to publish Helm charts; Helm defines only how charts should be
88
served from a repository. The plugin directly supports several types of popular repository servers, including
9-
https://chartmuseum.com/[ChartMuseum], https://jfrog.com/artifactory/[Artifactory] and https://goharbor.io/[Harbor].
9+
https://chartmuseum.com/[ChartMuseum], https://jfrog.com/artifactory/[Artifactory],
10+
https://goharbor.io/[Harbor], https://blog.sonatype.com/nexus-as-a-container-registry[Nexus] and
11+
https://docs.gitlab.com/ce/user/packages/container_registry/[Gitlab].
1012
1113
For other repository types that are not directly supported, you could try using the `custom` repository type,
1214
or consider creating a PR to add support for it.
@@ -127,6 +129,8 @@ The following repository types are supported:
127129
- `artifactory`
128130
- `chartMuseum`
129131
- `harbor`
132+
- `nexus`
133+
- `gitlab`
130134
- `custom`
131135

132136

@@ -285,6 +289,43 @@ helm {
285289
TIP: Nexus API
286290
https://help.sonatype.com/repomanager3/rest-and-integration-api/components-api#ComponentsAPI-UploadComponent[documentation].
287291

292+
=== Gitlab Repositories
293+
294+
The plugin provides direct support for Gitlab repositories. The Gitlab API `url` and the `projectId` must be set in the
295+
repository configuration block.
296+
297+
[source,groovy,role="primary"]
298+
.Groovy
299+
----
300+
helm {
301+
publishing {
302+
repositories {
303+
gitlab {
304+
url = uri('https://gitlab.example.com/api/v4')
305+
projectId = 1234
306+
}
307+
}
308+
}
309+
}
310+
----
311+
312+
[source,kotlin,role="secondary"]
313+
.Kotlin
314+
----
315+
helm {
316+
publishing {
317+
repositories {
318+
gitlab {
319+
url.set(uri("https://gitlab.example.com/api/v4"))
320+
projectName.set(1234)
321+
}
322+
}
323+
}
324+
}
325+
----
326+
TIP: Helm charts in the Gitlab Package Registry
327+
https://docs.gitlab.com/ee/user/packages/helm_repository/#helm-charts-in-the-package-registry[documentation].
328+
288329
=== Custom Repositories
289330

290331
If your target repository is not directly supported but involves some sort of HTTP upload, you can try the `custom`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package org.unbrokendome.gradle.plugins.helm.publishing.dsl
2+
3+
import okhttp3.MultipartBody
4+
import okhttp3.RequestBody
5+
import okhttp3.RequestBody.Companion.asRequestBody
6+
import org.gradle.api.model.ObjectFactory
7+
import org.gradle.api.provider.Property
8+
import org.unbrokendome.gradle.plugins.helm.dsl.credentials.internal.SerializableCredentials
9+
import org.unbrokendome.gradle.plugins.helm.dsl.credentials.internal.toSerializable
10+
import org.unbrokendome.gradle.plugins.helm.publishing.publishers.AbstractHttpHelmChartPublisher
11+
import org.unbrokendome.gradle.plugins.helm.publishing.publishers.HelmChartPublisher
12+
import org.unbrokendome.gradle.plugins.helm.publishing.publishers.PublisherParams
13+
import org.unbrokendome.gradle.plugins.helm.publishing.util.toMultipartBody
14+
import org.unbrokendome.gradle.pluginutils.property
15+
import java.io.File
16+
import java.net.URI
17+
import javax.inject.Inject
18+
19+
20+
interface GitlabHelmPublishingRepository : HelmPublishingRepository {
21+
/**
22+
* The ID of the Gitlab project.
23+
*/
24+
val projectId: Property<Int>
25+
}
26+
27+
28+
private open class DefaultGitlabHelmPublishingRepository @Inject constructor(
29+
name: String,
30+
objects: ObjectFactory
31+
) : AbstractHelmPublishingRepository(objects, name), GitlabHelmPublishingRepository {
32+
33+
override val projectId: Property<Int> =
34+
objects.property()
35+
36+
override val publisherParams: PublisherParams
37+
get() = GitlabPublisherParams(
38+
url = requireNotNull(url.orNull) { "url is required for Gitlab publishing repository" },
39+
credentials = configuredCredentials.orNull?.toSerializable(),
40+
projectId = requireNotNull(projectId.orNull) { "projectId is required for Gitlab publishing repository" }
41+
)
42+
43+
44+
private class GitlabPublisherParams(
45+
private val url: URI,
46+
private val credentials: SerializableCredentials?,
47+
private var projectId: Int
48+
) : PublisherParams {
49+
50+
override fun createPublisher(): HelmChartPublisher =
51+
GitlabPublisher(url, credentials, projectId)
52+
}
53+
54+
55+
private class GitlabPublisher(
56+
url: URI,
57+
credentials: SerializableCredentials?,
58+
private val projectId: Int
59+
) : AbstractHttpHelmChartPublisher(url, credentials) {
60+
61+
override val uploadMethod: String
62+
get() = "POST"
63+
64+
override fun uploadPath(chartName: String, chartVersion: String): String =
65+
"/projects/$projectId/packages/helm/api/stable/charts"
66+
67+
override fun requestBody(chartFile: File): RequestBody =
68+
MultipartBody.Builder().run {
69+
setType(MultipartBody.FORM)
70+
addFormDataPart("chart", chartFile.name, chartFile.asRequestBody(MEDIA_TYPE_GZIP))
71+
build()
72+
}
73+
}
74+
}
75+
76+
77+
internal fun ObjectFactory.newGitlabHelmPublishingRepository(name: String): GitlabHelmPublishingRepository =
78+
newInstance(DefaultGitlabHelmPublishingRepository::class.java, name)

helm-publish-plugin/src/main/kotlin/org/unbrokendome/gradle/plugins/helm/publishing/dsl/HelmPublishingRepositoryContainer.kt

+16
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,19 @@ interface HelmPublishingRepositoryContainer : PolymorphicDomainObjectContainer<H
6868
configuration: Action<NexusHelmPublishingRepository>
6969
): NexusHelmPublishingRepository =
7070
nexus("default", configuration)
71+
72+
@JvmDefault
73+
fun gitlab(
74+
name: String,
75+
configuration: Action<GitlabHelmPublishingRepository>
76+
): GitlabHelmPublishingRepository =
77+
create(name, GitlabHelmPublishingRepository::class.java, configuration)
78+
79+
@JvmDefault
80+
fun gitlab(
81+
configuration: Action<GitlabHelmPublishingRepository>
82+
): GitlabHelmPublishingRepository =
83+
gitlab("default", configuration)
7184
}
7285

7386

@@ -96,6 +109,9 @@ private open class DefaultHelmPublishingRepositoryContainer
96109
registerFactory(NexusHelmPublishingRepository::class.java) { name ->
97110
objects.newNexusHelmPublishingRepository(name)
98111
}
112+
registerFactory(GitlabHelmPublishingRepository::class.java) { name ->
113+
objects.newGitlabHelmPublishingRepository(name)
114+
}
99115

100116
// Default type is "custom"
101117
registerDefaultFactory { name ->

0 commit comments

Comments
 (0)