Skip to content

Instantly share code, notes, and snippets.

@claudiouzelac
Forked from Zetten/build.gradle
Created February 16, 2018 01:27
Show Gist options
  • Save claudiouzelac/6cf4cf053c6d3b201be5f3b6460d0642 to your computer and use it in GitHub Desktop.
Save claudiouzelac/6cf4cf053c6d3b201be5f3b6460d0642 to your computer and use it in GitHub Desktop.
Bazel workspace generation script
plugins {
id "com.github.ben-manes.versions" version "0.15.0"
id "io.spring.dependency-management" version "1.0.3.RELEASE"
}
apply plugin: 'base'
group = 'com.example'
version = '0.0.0'
description = """
Dependency management and generation of java dependency configuration for Bazel project.
"""
repositories {
jcenter()
}
configurations {
generate
}
ext['awaitility.version'] = '3.0.0'
ext['cucumber-jvm.version'] = '1.2.5'
ext['guava.version'] = '23.0'
ext['jfairy.version'] = '0.5.7'
ext['jool.version'] = '0.9.12'
ext['log4j2.version'] = '2.8.1'
ext['okhttp3.version'] = '3.8.1'
ext['postgresql.version'] = '42.1.4'
ext['selenium.version'] = '3.5.2'
ext['spring-boot.version'] = '1.5.6.RELEASE'
ext['spring-boot-admin-server.version'] = '1.5.3'
ext['spring-cloud.version'] = 'Dalston.SR3'
ext['testcontainers.version'] = '1.4.2'
ext['truth.version'] = '0.35'
dependencyManagement {
imports {
mavenBom 'org.springframework.boot:spring-boot-dependencies:' + ext['spring-boot.version']
mavenBom 'org.springframework.cloud:spring-cloud-dependencies:' + ext['spring-cloud.version']
}
dependencies {
dependency group: 'com.codeborne', name: 'phantomjsdriver', version: '1.4.3'
dependency group: 'com.google.guava', name: 'guava', version: ext['guava.version']
dependency group: 'com.google.truth', name: 'truth', version: ext['truth.version']
dependencySet(group: 'com.squareup.okhttp3', version: ext['okhttp3.version']) {
entry 'logging-interceptor'
entry 'mockwebserver'
entry 'okhttp'
}
dependencySet(group: 'de.codecentric', version: ext['spring-boot-admin-server.version']) {
entry('spring-boot-admin-server') {
exclude group: 'ch.qos.logback', name: 'logback-classic'
exclude group: 'ch.qos.logback', name: 'logback-core'
exclude group: 'org.slf4j', name: 'log4j-over-slf4j'
}
entry 'spring-boot-admin-server-ui'
entry 'spring-boot-admin-starter-client'
}
dependencySet(group: 'info.cukes', version: '1.2.5') {
entry 'cucumber-java8'
entry 'cucumber-junit'
entry 'cucumber-picocontainer'
}
dependency group: 'io.codearte.jfairy', name: 'jfairy', version: ext['jfairy.version']
dependency group: 'org.awaitility', name: 'awaitility', version: ext['awaitility.version']
dependency group: 'org.jooq', name: 'jool', version: ext['jool.version']
dependencySet(group: 'org.springframework.boot', version: ext['spring-boot.version']) {
entry('spring-boot-starter') {
exclude group: 'org.springframework.boot', name: 'spring-boot-starter-logging'
}
}
dependency group: 'org.seleniumhq.selenium', name: 'selenium-java', version: ext['selenium.version']
dependencySet(group: 'org.testcontainers', version: ext['testcontainers.version']) {
entry 'selenium'
entry 'testcontainers'
}
}
}
dependencies {
generate 'com.google.guava:guava'
generate 'com.google.truth:truth'
generate 'com.h2database:h2'
generate 'com.querydsl:querydsl-apt'
generate 'com.querydsl:querydsl-jpa'
generate 'com.squareup.okhttp3:logging-interceptor'
generate 'com.squareup.okhttp3:mockwebserver'
generate 'com.squareup.okhttp3:okhttp'
generate 'io.codearte.jfairy:jfairy'
generate 'info.cukes:cucumber-java8'
generate 'info.cukes:cucumber-junit'
generate 'info.cukes:cucumber-picocontainer'
generate 'javax.servlet:javax.servlet-api'
generate 'org.awaitility:awaitility'
generate 'org.jooq:jool'
generate 'org.postgresql:postgresql'
generate 'org.projectlombok:lombok'
generate 'org.seleniumhq.selenium:selenium-java'
generate 'org.springframework.boot:spring-boot-loader'
generate 'org.springframework.boot:spring-boot-starter'
generate 'org.springframework.boot:spring-boot-starter-actuator'
generate 'org.springframework.boot:spring-boot-starter-data-jpa'
generate 'org.springframework.boot:spring-boot-starter-data-rest'
generate 'org.springframework.boot:spring-boot-starter-hateoas'
generate 'org.springframework.boot:spring-boot-starter-log4j2'
generate 'org.springframework.boot:spring-boot-starter-security'
generate 'org.springframework.boot:spring-boot-starter-test'
generate 'org.springframework.boot:spring-boot-starter-web'
generate 'org.springframework.boot:spring-boot-starter-websocket'
generate 'org.springframework.cloud:spring-cloud-starter-eureka'
generate 'org.springframework.cloud:spring-cloud-starter-eureka-server'
generate 'org.springframework.cloud:spring-cloud-starter-zuul'
generate 'org.springframework.data:spring-data-rest-hal-browser'
generate 'org.testcontainers:selenium'
generate 'org.testcontainers:testcontainers'
}
task generateWorkspace() {
SortedMap<ModuleVersionIdentifier, SortedSet<ModuleVersionIdentifier>> moduleDependencies = new TreeMap<>(new Comparator<ModuleVersionIdentifier>() {
@Override
int compare(ModuleVersionIdentifier o1, ModuleVersionIdentifier o2) {
return getBazelIdentifier(o1) <=> getBazelIdentifier(o2)
}
})
configurations.generate.resolvedConfiguration.firstLevelModuleDependencies.each { dep ->
collectDependencies(moduleDependencies, dep)
}
Map<ModuleVersionIdentifier, String> moduleSourceSha256 = new HashMap<>();
SortedSet<ResolvedArtifact> resolvedArtifacts = new TreeSet<>(new Comparator<ResolvedArtifact>() {
@Override
int compare(ResolvedArtifact o1, ResolvedArtifact o2) {
return getBazelIdentifier(o1.moduleVersion.id) <=> getBazelIdentifier(o2.moduleVersion.id)
}
})
resolvedArtifacts.addAll(configurations.generate.resolvedConfiguration.resolvedArtifacts.findAll { resolvedArtifact ->
configurations.generate.incoming.resolutionResult.allDependencies*.selected.toSet().any {
(resolvedArtifact.moduleVersion.id == it.moduleVersion)
}
})
resolvedArtifacts.each {
ArtifactResolutionResult sourcesQueryResult = dependencies.createArtifactResolutionQuery()
.forComponents(it.id.componentIdentifier)
.withArtifacts(JvmLibrary, SourcesArtifact)
.execute()
Set<ResolvedArtifactResult> sourcesArtifacts = sourcesQueryResult.resolvedComponents.collectMany {
it.getArtifacts(SourcesArtifact)
}.toSet()
if (sourcesArtifacts.size() == 1) {
moduleSourceSha256.put(it.moduleVersion.id, sha256(sourcesArtifacts.first().file))
} else if (sourcesArtifacts.size() > 1) {
println("Artifact had multiple sources artifacts! ${it.moduleVersion.id}")
}
}
generateWorkspaceFile(resolvedArtifacts, moduleSourceSha256)
generateBuildFile(moduleDependencies, moduleSourceSha256)
}
private void collectDependencies(SortedMap<ModuleVersionIdentifier, SortedSet<ModuleVersionIdentifier>> moduleDependencies, ResolvedDependency dep) {
if (!moduleDependencies.containsKey(dep.module.id)) {
SortedSet<ModuleVersionIdentifier> childDependencies = new TreeSet<>(new Comparator<ModuleVersionIdentifier>() {
@Override
int compare(ModuleVersionIdentifier o1, ModuleVersionIdentifier o2) {
return getBazelIdentifier(o1) <=> getBazelIdentifier(o2)
}
})
childDependencies.addAll(dep.children.collect { it.module.id })
moduleDependencies.put(dep.module.id, childDependencies)
dep.children.each { collectDependencies(moduleDependencies, it) }
}
}
private void generateWorkspaceFile(SortedSet<ResolvedArtifact> resolvedArtifacts, Map<ModuleVersionIdentifier, String> moduleSourceSha256) {
def generateWorkspace = file("generate_workspace.bzl")
String generateWorkspaceContent = "def generated_maven_jars():\n"
resolvedArtifacts.each { a ->
def module = a.moduleVersion.id
def name = getBazelIdentifier(module)
def artifact = module.toString()
def sha256 = sha256(a.file)
generateWorkspaceContent += bzl_maven_jar(name, "https://jcenter.bintray.com", artifact, sha256)
if (moduleSourceSha256.containsKey(module)) {
generateWorkspaceContent += bzl_maven_jar("${name}_src", "https://jcenter.bintray.com", "${artifact}:sources", moduleSourceSha256.get(module))
}
}
generateWorkspace.text = generateWorkspaceContent
}
private static String sha256(file) {
java.security.MessageDigest md = java.security.MessageDigest.getInstance("SHA-256");
file.eachByte 4096, { bytes, size -> md.update(bytes, 0, size) }
return md.digest().collect { String.format "%02x", it }.join()
}
private void generateBuildFile(Map<ModuleVersionIdentifier, Set<ModuleVersionIdentifier>> modules, Map<ModuleVersionIdentifier, Boolean> moduleSourceSha256) {
def build = file("BUILD")
String buildContent = "licenses([\"notice\"])\n\n"
modules.each { module, dependencies ->
buildContent += bzl_java_library(getBazelIdentifier(module), dependencies.collect { getBazelIdentifier(it) }, moduleSourceSha256.containsKey(module))
}
build.text = buildContent
}
private static String getBazelIdentifier(ModuleVersionIdentifier id) {
id.group.replaceAll("[^\\w]", "_") + "_" + id.name.replaceAll("[^\\w]", "_")
}
private static String bzl_maven_jar(name, repoUrl, artifactId, sha256) {
Object artifactUrl = getArtifactUrl(artifactId, repoUrl)
return """ native.http_file(
name = "${name}",
urls = ["${artifactUrl}.jar"],
sha256 = "${sha256}",
)
"""
}
private static Object getArtifactUrl(artifactId, repoUrl) {
def group, artifact, version, classifier, file_version
String[] parts = artifactId.split(':')
if (parts.length == 4) {
(group, artifact, version, classifier) = parts
file_version = version + '-' + classifier
} else {
(group, artifact, version) = parts
file_version = version
}
return [repoUrl,
group.replace('.', '/'),
artifact,
version,
artifact + '-' + file_version].join('/')
}
private static String bzl_java_library(name, dependencies, Boolean hasSources) {
String deps = ""
dependencies.each {
deps += "\n \":${it}\","
}
if (hasSources) {
return """native.java_import(
name = "${name}",
visibility = ["//visibility:public"],
jars = ["@${name}//file"],
runtime_deps = [${deps}
],
srcjar = "@${name}_src//file",
)
"""
} else {
return """native.java_import(
name = "${name}",
visibility = ["//visibility:public"],
jars = ["@${name}//file"],
runtime_deps = [${deps}
],
)
"""
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment