Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
name.remal.gradle_plugins.toolkit.build_logic.github-submit-dependencies.gradle Maven / Gradle / Ivy
import static java.nio.charset.StandardCharsets.UTF_8
import groovy.json.JsonGenerator
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
import groovy.transform.EqualsAndHashCode
import groovy.transform.TupleConstructor
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
import java.time.Duration
allprojects {
pluginManager.withPlugin('java') {
project.apply plugin: 'reporting-base'
Task githubSubmitDependencies = tasks.create('githubSubmitDependencies') { Task task ->
task.group = 'documentation'
SetProperty lazyDependenciesToSubmitSet = project.objects.setProperty(DependencyToSubmit.class)
task.ext.dependenciesToSubmit = lazyDependenciesToSubmitSet
task.inputs.property('dependenciesToSubmit', lazyDependenciesToSubmitSet)
File reportFile = project.file("${project.reporting.baseDir}/${task.name}.json")
task.ext.reportFile = reportFile
task.outputs.file(reportFile).withPropertyName('reportFile')
doFirst { reportFile.delete() }
Closure nullIfEmpty = { String string ->
return string != null && string.isEmpty() ? null : string
}
Closure nullIfJar = { String string ->
return string != null && string == 'jar' ? null : string
}
Closure isExcludedCategory = { ResolvedDependencyResult resolvedDependency ->
return isPlatformDependency(resolvedDependency) || isDocumentationDependency(resolvedDependency) || isVerificationDependency(resolvedDependency)
}
Closure processConfiguration = { Configuration conf, boolean isBuildscript = false ->
lazyDependenciesToSubmitSet.addAll(
provider {
if (!conf.canSafelyBeResolved()) return []
Collection resolvedArtifacts = conf.resolvedConfiguration.resolvedArtifacts
Set result = [].toSet()
Closure processResolvedDependency = {
ResolvedDependencyResult resolvedDependency,
DependencyToSubmitScope scope,
DependencyToSubmitRelationship relationship ->
ModuleComponentIdentifier id = resolvedDependency.selected.id.with { id ->
if (id instanceof ModuleComponentIdentifier) {
return id
} else {
return null
}
}
if (id == null) return
if (isPlatformDependency(resolvedDependency)) {
result.add(
new DependencyToSubmit(
nullIfEmpty(id.group),
nullIfEmpty(id.module),
nullIfEmpty(id.version),
null,
null,
scope,
relationship
)
)
} else {
Collection dependencyArtifacts = resolvedArtifacts.findAll { it.id.componentIdentifier == id }
dependencyArtifacts.forEach { dependencyArtifact ->
result.add(
new DependencyToSubmit(
nullIfEmpty(id.group),
nullIfEmpty(id.module),
nullIfEmpty(id.version),
nullIfEmpty(dependencyArtifact.classifier),
nullIfEmpty(nullIfJar(dependencyArtifact.extension)),
scope,
relationship
)
)
}
}
}
DependencyToSubmitScope scope = DependencyToSubmitScope.DEVELOPMENT
if (isBuildscript) {
// do nothing
} else if (['runtimeClasspath', 'relocateClasses'].contains(conf.name)) {
scope = DependencyToSubmitScope.RUNTIME
}
conf.incoming.resolutionResult
.root
.dependencies
.collect { (DependencyResult) it }
.findAll { !it.constraint }
.findAll { it instanceof ResolvedDependencyResult }
.collect { (ResolvedDependencyResult) it }
.findAll { !isExcludedCategory(it) }
.forEach { processResolvedDependency(it, scope, DependencyToSubmitRelationship.DIRECT) }
conf.incoming.resolutionResult
.allDependencies
.collect { (DependencyResult) it }
.findAll { !it.constraint }
.findAll { it instanceof ResolvedDependencyResult }
.collect { (ResolvedDependencyResult) it }
.findAll { !isExcludedCategory(it) }
.findAll { !it.selected.selectionReason.expected }
.forEach { processResolvedDependency(it, scope, DependencyToSubmitRelationship.INDIRECT) }
return result
}
)
}
project.buildscript.configurations.all { processConfiguration(it, true) }
project.configurations.all { processConfiguration(it) }
ListProperty lazyDependenciesToSubmit = project.objects.listProperty(DependencyToSubmit.class)
lazyDependenciesToSubmit.set(
provider {
lazyDependenciesToSubmitSet.get()
.findAll { it.version != null && !it.version.isEmpty() }
.toSorted()
.groupBy { it.toString() }
.values()
.toList()
.collect { it.get(0) }
}
)
JsonGenerator jsonGenerator = new JsonGenerator.Options()
.excludeNulls()
.excludeFieldsByName('contentHash', 'originalClassName')
.build()
doLast {
Closure encodeUrlPart = { String string ->
if (string == null) return ''
return URLEncoder.encode(string, UTF_8)
.replace("+", "%20")
.replace("*", "%2A")
.replace("%7E", "~");
}
Map resolved = [:]
lazyDependenciesToSubmit.get().forEach { DependencyToSubmit dep ->
String packageUrl = "pkg:maven/${encodeUrlPart(dep.group)}/${encodeUrlPart(dep.name)}@${encodeUrlPart(dep.version)}"
if (dep.classifier) {
if (!packageUrl.contains('?')) {
packageUrl += '?'
} else {
packageUrl += '&'
}
packageUrl += "packaging=${encodeUrlPart(dep.classifier)}"
}
resolved.put(
dep.toString(),
[
package_url: packageUrl,
relationship: dep.relationship?.name()?.toLowerCase(),
scope: dep.scope?.name()?.toLowerCase(),
]
)
}
Map manifests = [:]
manifests.put(
rootProject.relativePath(project.buildFile),
[
name: rootProject.relativePath(project.buildFile),
file: [
source_location: rootProject.relativePath(project.buildFile),
],
resolved: resolved,
]
)
String runId = [
'github-actions-run',
project.property('github-actions-run-id'),
project.property('github-actions-run-attempt'),
project.property('github-actions-job'),
project.property('github-actions-job-index'),
].collect { it ?: '' }.join('-')
Map requestBody = [
version: System.currentTimeMillis(),
job: [
id: runId,
correlator: project.path,
],
sha: project.property('git-sha'),
ref: project.property('git-ref'),
detector: [
name: 'name.remal.gradle-plugins.toolkit',
version: '0.65.13',
url: 'https://github.com/remal-gradle-plugins/toolkit',
],
manifests: manifests,
scanned: new Date(),
]
String jsonContent = jsonGenerator.toJson(requestBody)
reportFile.parentFile.mkdirs()
reportFile.setText(JsonOutput.prettyPrint(jsonContent), 'UTF-8')
int maxAttempts = 3
int attempt = 0
while (true) {
++attempt
HttpRequest httpRequest = HttpRequest.newBuilder()
.timeout(Duration.ofMinutes(1))
.uri(new URI("${project.property('repository-api-url')}/dependency-graph/snapshots"))
.header('Authorization', "token ${project.property('github-actions-token')}")
.header('Accept', 'application/vnd.github+json')
.header('Content-Type', 'application/json;charset=UTF-8')
.POST(HttpRequest.BodyPublishers.ofString(jsonContent, UTF_8))
.build()
HttpResponse httpResponse = HttpClient.newHttpClient().send(httpRequest, HttpResponse.BodyHandlers.ofString(UTF_8))
int statusCode = httpResponse.statusCode()
if (statusCode >= 400) {
if (statusCode == 429
|| statusCode >= 500
) {
if (attempt < maxAttempts) {
Thread.sleep(5_000)
continue
}
}
throw new GradleException("Dependencies submitting REST API call returned ${httpResponse.statusCode()} error:\n${httpResponse.body()}")
}
String responseBodyJson = httpResponse.body()
Map responseBody = new JsonSlurper().parseText(responseBodyJson)
if (responseBody.message) {
println responseBody.message
} else {
println responseBodyJson
}
break
}
}
}
if (project.isBuildSrcProject) {
if (gradle.startParameter.taskNames.contains(githubSubmitDependencies.name)
|| (gradle.parent && gradle.parent.startParameter.taskNames.contains(githubSubmitDependencies.name))
) {
project.rootProject.tasks.named('build') {
dependsOn(githubSubmitDependencies)
}
}
}
}
}
@TupleConstructor
@EqualsAndHashCode
class DependencyToSubmit implements Serializable, Comparable {
String group
String name
String version
String classifier
String type
DependencyToSubmitScope scope
DependencyToSubmitRelationship relationship
String toString() {
String group = this.group ?: ''
String name = this.name ?: ''
String version = this.version ?: ''
String classifier = this.classifier ?: ''
String type = this.type ?: ''
return "$group:$name:$version:$classifier@$type"
.replaceFirst(/:?@(jar)?$/, '')
}
private static final Comparator scopeComparator = Comparator.nullsLast(Comparator.naturalOrder())
private static final Comparator relationshipComparator = Comparator.nullsLast(Comparator.naturalOrder())
@Override
int compareTo(DependencyToSubmit other) {
int result = toString() <=> other.toString()
if (result == 0) result = scopeComparator.compare(scope, other.scope)
if (result == 0) result = relationshipComparator.compare(relationship, other.relationship)
return result
}
}
enum DependencyToSubmitScope {
RUNTIME,
DEVELOPMENT,
}
enum DependencyToSubmitRelationship {
DIRECT,
INDIRECT,
}