diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..1beec72b --- /dev/null +++ b/.envrc @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# Reload if any of these files change +watch_file nix/* +watch_file .envrc.local + +# Build a folder that contains all the tools +nix-build ./nix -A env --out-link ./env + +# source .profile from `$env`. +# This is only used to set things interpolated by nix. +# All *static* things should live inside .envrc. +source_env ./env/.profile + +# used by docker-compose to run processes with the same user ID mapping +HOST_UID=$(id -u) +HOST_GID=$(id -g) +export HOST_UID HOST_GID + +# set protoc path from nix env +export PROTOC_PATH=$(readlink -f ./env/bin/protoc) + +# allow local .envrc overrides +[[ -f .envrc.local ]] && source_env .envrc.local diff --git a/.gitignore b/.gitignore index a2988251..c520b309 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,7 @@ testsetup/ .idea_modules/ *.iml *.ipr -*.iws \ No newline at end of file +*.iws + +# nix +env \ No newline at end of file diff --git a/build.gradle b/build.gradle index 76cb14d7..330471dc 100644 --- a/build.gradle +++ b/build.gradle @@ -1,19 +1,10 @@ +import io.gitlab.arturbosch.detekt.Detekt + import java.time.Instant import java.time.ZoneId import java.time.format.DateTimeFormatter import java.time.temporal.ChronoUnit -buildscript { - repositories { - mavenLocal() - mavenCentral() - } - dependencies { - classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.30' - classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.12' - } -} - plugins { id 'java' id 'groovy' @@ -21,13 +12,13 @@ plugins { id 'application' id 'jacoco' - id 'org.jetbrains.kotlin.jvm' version '1.3.70' - id 'com.google.cloud.tools.jib' version "2.5.0" - id 'org.springframework.boot' version '2.3.5.RELEASE' - id 'io.spring.dependency-management' version '1.0.6.RELEASE' - id 'com.palantir.git-version' version '0.12.2' - id "com.google.protobuf" version "0.8.12" - id "org.jlleitschuh.gradle.ktlint" version "10.2.0" + alias(libs.plugins.kotlin) + alias(libs.plugins.jib) + alias(libs.plugins.spring) + alias(libs.plugins.git) + alias(libs.plugins.protobuf) + alias(libs.plugins.ktlint) + alias(libs.plugins.detekt) } @@ -35,7 +26,7 @@ group = 'io.emeraldpay.dshackle' // Version schema: // x.x.x for production, following SemVer model -// x.x-SNAPSHOT for development +// x.x.x-SNAPSHOT for development version = '0.11.0-SNAPSHOT' java { @@ -46,7 +37,6 @@ java { repositories { mavenLocal() mavenCentral() - jcenter() maven { url "https://repo.spring.io/snapshot" } maven { url "https://repo.spring.io/milestone" } maven { url "https://maven.emrld.io" } @@ -62,81 +52,51 @@ configurations { } dependencies { - implementation "io.emeraldpay:emerald-api:0.10.0" + implementation libs.bundles.kotlin - implementation "io.grpc:grpc-protobuf:${grpcVersion}" - implementation "io.grpc:grpc-stub:${grpcVersion}" - implementation "io.grpc:grpc-netty:${grpcVersion}" - - implementation "io.netty:netty-transport:$nettyVersion" - implementation "io.netty:netty-common:$nettyVersion" - implementation "io.netty:netty-handler:$nettyVersion" - implementation "io.netty:netty-handler-proxy:$nettyVersion" - implementation "io.netty:netty-resolver:$nettyVersion" - implementation "io.netty:netty-resolver-dns:$nettyVersion" - implementation "io.netty:netty-codec:$nettyVersion" - implementation "io.netty:netty-codec-http2:$nettyVersion" - implementation "io.netty:netty-codec-http:$nettyVersion" - implementation "io.netty:netty-buffer:$nettyVersion" - implementation "io.netty:netty-tcnative:2.0.39.Final" - implementation "io.netty:netty-tcnative-boringssl-static:2.0.39.Final" - - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" - implementation "org.jetbrains.kotlin:kotlin-reflect" - - implementation("org.springframework.boot:spring-boot-starter:$springBootVersion") { + implementation libs.bundles.grpc + implementation libs.bundles.netty + implementation(libs.bundles.spring.framework) { exclude module: 'spring-boot-starter-logging' } - implementation "org.springframework.security:spring-security-core:$springSecurtyVersion" - implementation "org.springframework.security:spring-security-web:$springSecurtyVersion" - implementation "org.springframework.security:spring-security-config:$springSecurtyVersion" - implementation "io.projectreactor:reactor-core:$reactorVersion" - implementation "io.projectreactor.netty:reactor-netty:1.0.11" - implementation 'io.projectreactor.addons:reactor-extra:3.4.5' - implementation 'io.projectreactor.kotlin:reactor-kotlin-extensions:1.1.4' - implementation "com.salesforce.servicelibs:reactor-grpc-stub:$reactiveGrpcVersion" - implementation 'io.micrometer:micrometer-registry-prometheus:1.5.6' - implementation 'io.lettuce:lettuce-core:5.2.2.RELEASE' - implementation "io.emeraldpay.etherjar:etherjar-domain:$etherjarVersion" - implementation "io.emeraldpay.etherjar:etherjar-hex:$etherjarVersion" - implementation "io.emeraldpay.etherjar:etherjar-rpc-api:$etherjarVersion" - implementation "io.emeraldpay.etherjar:etherjar-rpc-http:$etherjarVersion" - implementation "io.emeraldpay.etherjar:etherjar-rpc-ws:$etherjarVersion" - implementation "io.emeraldpay.etherjar:etherjar-tx:$etherjarVersion" - implementation "io.emeraldpay.etherjar:etherjar-contract:$etherjarVersion" - implementation "io.emeraldpay.etherjar:etherjar-erc20:$etherjarVersion" - implementation 'org.bitcoinj:bitcoinj-core:0.15.8' + implementation libs.bundles.reactor - implementation 'org.yaml:snakeyaml:1.24' - implementation 'org.apache.httpcomponents:httpmime:4.5.8' - implementation 'org.apache.httpcomponents:httpclient:4.5.8' - implementation "com.fasterxml.jackson.core:jackson-core:$jacksonVersion" - implementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" - implementation "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:$jacksonVersion" - implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jacksonVersion" - implementation "com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion" - implementation 'commons-io:commons-io:2.6' - implementation 'org.apache.commons:commons-lang3:3.9' - implementation 'org.apache.commons:commons-collections4:4.3' - implementation 'javax.annotation:javax.annotation-api:1.3.2' - implementation 'org.bouncycastle:bcprov-jdk15on:1.61' - implementation 'com.github.ben-manes.caffeine:caffeine:2.8.5' + implementation(libs.reactor.grpc.stub) - implementation "org.slf4j:slf4j-api:$slf4jVersion" - implementation "org.apache.logging.log4j:log4j-slf4j-impl:2.11.1" - implementation "org.slf4j:jul-to-slf4j:$slf4jVersion" - implementation "org.slf4j:jcl-over-slf4j:$slf4jVersion" + implementation libs.micrometer.registry.prometheus + implementation libs.lettuce.core - testImplementation 'cglib:cglib-nodep:3.3.0' - testImplementation "org.spockframework:spock-core:$spockVersion" - testImplementation "io.grpc:grpc-testing:${grpcVersion}" - testImplementation "io.projectreactor:reactor-test:$reactorVersion" - testImplementation 'org.objenesis:objenesis:3.1' - testImplementation 'org.mock-server:mockserver-netty:5.11.2' - testImplementation "org.java-websocket:Java-WebSocket:1.5.1" - testImplementation "nl.jqno.equalsverifier:equalsverifier:3.3" - testImplementation "org.codehaus.groovy:groovy:${groovyVersion}" + implementation libs.bundles.etherjar + + implementation(libs.emerald.api) { + exclude group: 'com.salesforce.servicelibs', module: 'reactor-grpc' + } + + implementation libs.bitcoinj + + implementation libs.snake.yaml + implementation libs.bundles.httpcomponents + implementation libs.bundles.jackson + + implementation libs.bundles.apache.commons + implementation libs.bouncycastle + implementation libs.caffeine + implementation libs.javax.annotations + + implementation libs.bundles.slf4j + + testImplementation libs.cglib.nodep + testImplementation libs.spockframework.core + testImplementation libs.grpc.testing + testImplementation libs.reactor.test + testImplementation libs.objgenesis + testImplementation libs.mockserver.netty + testImplementation libs.java.websocket + testImplementation libs.equals.verifier + testImplementation libs.groovy + + detektPlugins libs.detekt.formatting } compileKotlin { @@ -173,7 +133,7 @@ test { } application { - mainClassName = 'io.emeraldpay.dshackle.StarterKt' + getMainClass().set('io.emeraldpay.dshackle.StarterKt') } jib { @@ -192,8 +152,8 @@ jib { '/dshackle:', 'snapshot' ].join('') - tags = [project.version].with (true) { - add "t"+ DateTimeFormatter.ofPattern("yyyyMMddHHmm").withZone(ZoneId.of('UTC')).format(Instant.now()) + tags = [project.version].with(true) { + add "t" + DateTimeFormatter.ofPattern("yyyyMMddHHmm").withZone(ZoneId.of('UTC')).format(Instant.now()) add project.version.toString().replaceAll('(\\d+\\.\\d+).+', '$1') } auth { @@ -202,9 +162,7 @@ jib { } } container { - jvmFlags = [ - '-Xms1024m', - ] + jvmFlags = ['-Xms1024m'] mainClass = 'io.emeraldpay.dshackle.StarterKt' args = [] ports = ['2448', '2449', '8545'] @@ -212,7 +170,7 @@ jib { } jar { - enabled=true + enabled = true } afterEvaluate { @@ -222,7 +180,11 @@ afterEvaluate { } protobuf { - protoc { artifact = "com.google.protobuf:protoc:${protocVersion}" } + protoc { + // if $PROTOC_PATH is set then locally installed protoc is used otherwise it is downloaded remotely + path = System.getenv("PROTOC_PATH") ?: null + artifact = System.getenv("PROTOC_PATH") == null ? "com.google.protobuf:protoc:${libs.versions.protoc.get()}" : null + } plugins { } generateProtoTasks { @@ -235,7 +197,7 @@ sourceSets { } } -task generateVersion() { +task generateVersion() { group = 'Build' description = 'Generate project version' @@ -267,7 +229,7 @@ tasks.withType(Test) { } } afterTest { TestDescriptor descriptor, TestResult result -> - if(result.resultType == org.gradle.api.tasks.testing.TestResult.ResultType.FAILURE){ + if (result.resultType == org.gradle.api.tasks.testing.TestResult.ResultType.FAILURE) { failedTests << "${descriptor.className} > ${descriptor.name}" if (!stdout.isEmpty()) { println("-------- ${descriptor.className} > ${descriptor.name} OUTPUT ".padRight(120, "-")) @@ -278,7 +240,7 @@ tasks.withType(Test) { } } gradle.buildFinished { - if(!failedTests.empty){ + if (!failedTests.empty) { println "Failed tests for ${project.name}:" failedTests.each { failedTest -> println failedTest @@ -290,8 +252,8 @@ gradle.buildFinished { jacocoTestReport { dependsOn test reports { - xml.enabled true - html.enabled true + xml.required.set true + html.required.set true } afterEvaluate { classDirectories.setFrom(files(classDirectories.files.collect { @@ -301,4 +263,27 @@ jacocoTestReport { } jacoco { toolVersion = "0.8.7" -} \ No newline at end of file +} + +detekt { + toolVersion = "1.18.1" + parallel = false + basePath = projectDir + debug = false + ignoreFailures = true + + reports { + xml { + enabled = true + destination = file("build/reports/detekt/detekt.xml") + } + html { + enabled = true + destination = file("build/reports/detekt/detekt.html") + } + } +} + +tasks.withType(Detekt).configureEach { + jvmTarget = "13" +} diff --git a/gradle.properties b/gradle.properties index e67fc02c..974d2f80 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,21 +1,3 @@ kotlin.code.style=official -# Languages -groovyVersion=2.5.14 -kotlinVersion=1.5.30 -protocVersion=3.9.0 -# Main Libs -slf4jVersion=1.7.25 -jacksonVersion=2.11.0 -grpcVersion=1.38.0 -reactiveGrpcVersion=1.2.0 -springBootVersion=2.4.5 -springVersion=5.3.6 -springSecurtyVersion=5.4.6 -reactorVersion=3.4.10 -nettyVersion=4.1.65.Final -# Our Libs -etherjarVersion=0.11.1 -# Testing -spockVersion=1.3-groovy-2.5 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 00000000..98a70932 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,132 @@ +[versions] +detekt = "1.18.1" +etherjar = "0.11.1" +groovy = "2.5.14" +protoc = "3.9.0" +slf4j = "1.7.25" +jackson = "2.11.0" +grpc = "1.38.0" +reactive-grpc = "1.2.0" +spring-boot = "2.5.6" +spring-security = "5.5.3" +reactor = "3.4.10" +netty = "4.1.65.Final" +netty-tcnative = "2.0.39.Final" +kotlin = "1.5.31" +httpcomponents = "4.5.8" + +[libraries] +apache-commons-lang3 = "org.apache.commons:commons-lang3:3.9" +apache-commons-collections4 = "org.apache.commons:commons-collections4:4.3" + +bitcoinj = "org.bitcoinj:bitcoinj-core:0.15.8" + +bouncycastle = "org.bouncycastle:bcprov-jdk15on:1.61" + +caffeine = "com.github.ben-manes.caffeine:caffeine:2.8.5" + +commons-io = "commons-io:commons-io:2.6" + +cglib-nodep = "cglib:cglib-nodep:3.3.0" + +detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detekt" } + +emerald-api = "io.emeraldpay:emerald-api:0.10.0" + +equals-verifier = "nl.jqno.equalsverifier:equalsverifier:3.3" + +etherjar-domain = { module = "io.emeraldpay.etherjar:etherjar-domain", version.ref = "etherjar" } +etherjar-hex = { module = "io.emeraldpay.etherjar:etherjar-hex", version.ref = "etherjar" } +etherjar-rpc-api = { module = "io.emeraldpay.etherjar:etherjar-rpc-api", version.ref = "etherjar" } +etherjar-rpc-http = { module = "io.emeraldpay.etherjar:etherjar-rpc-http", version.ref = "etherjar" } +etherjar-rpc-ws = { module = "io.emeraldpay.etherjar:etherjar-rpc-ws", version.ref = "etherjar" } +etherjar-tx = { module = "io.emeraldpay.etherjar:etherjar-tx", version.ref = "etherjar" } +etherjar-contract = { module = "io.emeraldpay.etherjar:etherjar-contract", version.ref = "etherjar" } +etherjar-erc20 = { module = "io.emeraldpay.etherjar:etherjar-erc20", version.ref = "etherjar" } + +groovy = { module = "org.codehaus.groovy:groovy", version.ref = "groovy" } + +grpc-protobuf = { module = "io.grpc:grpc-protobuf", version.ref = "grpc" } +grpc-stub = { module = "io.grpc:grpc-stub", version.ref = "grpc" } +grpc-netty = { module = "io.grpc:grpc-netty", version.ref = "grpc" } +grpc-testing = { module = "io.grpc:grpc-testing", version.ref = "grpc" } + +httpcomponents-httpmime = { module = "org.apache.httpcomponents:httpmime", version.ref = "httpcomponents" } +httpcomponents-httpclient = { module = "org.apache.httpcomponents:httpclient", version.ref = "httpcomponents" } + +jackson-core = { module = "com.fasterxml.jackson.core:jackson-core", version.ref = "jackson" } +jackson-databind = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "jackson" } +jackson-datatype-jdk8 = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jdk8", version.ref = "jackson" } +jackson-datatype-jsr310 = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jsr310", version.ref = "jackson" } +jackson-module-kotlin = { module = "com.fasterxml.jackson.module:jackson-module-kotlin", version.ref = "jackson" } + +java-websocket = "org.java-websocket:Java-WebSocket:1.5.1" + +javax-annotations = "javax.annotation:javax.annotation-api:1.3.2" + +kotlin-stdlib-jdk8 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" } +kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" } + +lettuce-core = "io.lettuce:lettuce-core:5.2.2.RELEASE" + +micrometer-registry-prometheus = "io.micrometer:micrometer-registry-prometheus:1.5.6" + +mockserver-netty = "org.mock-server:mockserver-netty:5.11.2" + +netty-common = { module = "io.netty:netty-common", version.ref = "netty" } +netty-transport = { module = "io.netty:netty-transport", version.ref = "netty" } +netty-handler-core = { module = "io.netty:netty-handler", version.ref = "netty" } +netty-handler-proxy = { module = "io.netty:netty-handler-proxy", version.ref = "netty" } +netty-resolver-core = { module = "io.netty:netty-resolver", version.ref = "netty" } +netty-resolver-dns = { module = "io.netty:netty-resolver-dns", version.ref = "netty" } +netty-codec-core = { module = "io.netty:netty-codec", version.ref = "netty" } +netty-codec-http = { module = "io.netty:netty-codec-http", version.ref = "netty" } +netty-codec-http2 = { module = "io.netty:netty-codec-http2", version.ref = "netty" } +netty-buffer = { module = "io.netty:netty-buffer", version.ref = "netty" } +netty-tcnative-core = { module = "io.netty:netty-tcnative", version.ref = "netty-tcnative" } +netty-tcnative-boringssl = { module = "io.netty:netty-tcnative-boringssl-static", version.ref = "netty-tcnative" } + +objgenesis = "org.objenesis:objenesis:3.1" + +reactor-core = { module = "io.projectreactor:reactor-core", version.ref = "reactor" } +reactor-netty = { module = "io.projectreactor.netty:reactor-netty", version = "1.0.11" } +reactor-extra = { module = "io.projectreactor.addons:reactor-extra", version = "3.4.5" } +reactor-kotlin = { module = "io.projectreactor.kotlin:reactor-kotlin-extensions", version = "1.1.4" } +reactor-test = { module = "io.projectreactor:reactor-test", version.ref = "reactor" } + +reactor-grpc-stub = "com.salesforce.servicelibs:reactor-grpc-stub:1.2.0" + +slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } +slf4j-jul = { module = "org.slf4j:jul-to-slf4j", version.ref = "slf4j" } +slf4j-jcl = { module = "org.slf4j:jcl-over-slf4j", version.ref = "slf4j" } +log4j-slf4j = "org.apache.logging.log4j:log4j-slf4j-impl:2.11.1" + +snake-yaml = "org.yaml:snakeyaml:1.24" + +spockframework-core = "org.spockframework:spock-core:2.0-groovy-3.0" + +spring-boot-starter = { module = "org.springframework.boot:spring-boot-starter", version.ref = "spring-boot" } +spring-security-core = { module = "org.springframework.security:spring-security-core", version.ref = "spring-security" } +spring-security-web = { module = "org.springframework.security:spring-security-web", version.ref = "spring-security" } +spring-security-config = { module = "org.springframework.security:spring-security-config", version.ref = "spring-security" } + +[bundles] +apache-commons = ["commons-io", "apache-commons-lang3", "apache-commons-collections4"] +etherjar = ["etherjar-domain", "etherjar-hex", "etherjar-rpc-api", "etherjar-rpc-http", "etherjar-rpc-ws", "etherjar-tx", "etherjar-contract", "etherjar-erc20"] +grpc = ["grpc-protobuf", "grpc-stub", "grpc-netty"] +httpcomponents = ["httpcomponents-httpmime", "httpcomponents-httpclient"] +jackson = ["jackson-core", "jackson-databind", "jackson-datatype-jdk8", "jackson-datatype-jsr310", "jackson-module-kotlin"] +kotlin = ["kotlin-stdlib-jdk8", "kotlin-reflect"] +netty = ["netty-common", "netty-transport", "netty-handler-core", "netty-handler-proxy", "netty-resolver-core", "netty-resolver-dns", "netty-codec-core", "netty-codec-http", "netty-codec-http2", "netty-buffer", "netty-tcnative-core", "netty-tcnative-boringssl"] +reactor = ["reactor-core", "reactor-netty", "reactor-extra", "reactor-kotlin"] +slf4j = ["slf4j-api", "slf4j-jul", "slf4j-jcl", "log4j-slf4j"] +spring-framework = ["spring-boot-starter", "spring-security-core", "spring-security-web", "spring-security-config"] + +[plugins] +kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } +jib = { id = "com.google.cloud.tools.jib", version = "2.5.0" } +spring = { id = "org.springframework.boot", version = "2.3.5.RELEASE" } +git = { id = "com.palantir.git-version", version = "0.12.3" } +protobuf = { id = "com.google.protobuf", version = "0.8.17" } +ktlint = { id = "org.jlleitschuh.gradle.ktlint", version = "10.2.0" } +detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index bb8b2fc2..ffed3a25 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew.bat b/gradlew.bat index 5093609d..a9f778a7 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,104 +1,104 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/nix/default.nix b/nix/default.nix new file mode 100644 index 00000000..a1941c4e --- /dev/null +++ b/nix/default.nix @@ -0,0 +1,45 @@ +{ system ? builtins.currentSystem +, nixpkgs ? import ./nixpkgs.nix { inherit system; } +}: +let + mkEnv = nixpkgs.callPackage ./mkEnv.nix { }; +in +rec { + inherit + nixpkgs + ; + + protoc-gen-grpc-java = nixpkgs.callPackage ./pkgs/protoc-gen-grpc-java { }; + + env = mkEnv { + env = { + # Configure nix to use nixpgks + NIX_PATH = "nixpkgs=${toString nixpkgs.path}"; + # Set the env for gradle + JAVA_HOME = "@env-root@/lib/openjdk"; + }; + + paths = [ + # Development tools + nixpkgs.gitAndTools.git-absorb + nixpkgs.jq + nixpkgs.niv + nixpkgs.websocat + nixpkgs.yq + + # Protobuf stuff + nixpkgs.protobuf3_9 + protoc-gen-grpc-java + + # Code formatting + nixpkgs.treefmt + nixpkgs.nixpkgs-fmt + nixpkgs.shfmt + + nixpkgs.jdk + nixpkgs.coreutils + nixpkgs.gnugrep + nixpkgs.which + ]; + }; +} diff --git a/nix/lib/force_cached.nix b/nix/lib/force_cached.nix new file mode 100644 index 00000000..0e416d51 --- /dev/null +++ b/nix/lib/force_cached.nix @@ -0,0 +1,38 @@ +# Source https://github.com/Mic92/nix-build-uncached/blob/master/scripts/force_cached.nix +coreutils: attrs: +with builtins; +let + # Copied from + isDerivation = x: isAttrs x && x ? type && x.type == "derivation"; + + # Return true if `nix-build` would traverse that attribute set to look for + # more derivations to build. + hasRecurseIntoAttrs = x: isAttrs x && (x.recurseForDerivations or false); + + # Wraps derivations that disallow substitutes so that they can be cached. + toCachedDrv = drv: + if !(drv.allowSubstitutes or true) then + derivation + { + name = "${drv.name}-to-cached"; + system = drv.system; + builder = "/bin/sh"; + args = [ "-c" "${coreutils}/bin/ln -s ${drv} $out; exit 0" ]; + } + else + drv; + + op = _: val: + if isDerivation val then + toCachedDrv val + else if hasRecurseIntoAttrs val then + forceCached val + else + val + ; + + # Traverses a tree of derivation and wrap all of those that disallow + # substitutes. + forceCached = attrs: mapAttrs op attrs; +in +forceCached attrs diff --git a/nix/mkEnv.nix b/nix/mkEnv.nix new file mode 100644 index 00000000..12364a51 --- /dev/null +++ b/nix/mkEnv.nix @@ -0,0 +1,29 @@ +{ lib, writeText, buildEnv }: + +{ name ? "dev-env" +, # Environment variables to set + env ? { } +, # Packages to add to the path + paths ? [ ] +}: +let + envToBash = name: value: + "export ${name}=${lib.escapeShellArg (toString value)}" + ; + + exports = lib.concatStringsSep "\n" + (map (name: envToBash name env.${name}) (lib.attrNames env)); + + env-root = writeText "env-root" '' + export PATH=@env-root@/bin:$PATH + + ${exports} + ''; +in +buildEnv { + inherit name; + paths = paths; + postBuild = '' + sed "s|@env-root@|$out|g" ${env-root} > $out/.profile + ''; +} diff --git a/nix/nixpkgs.nix b/nix/nixpkgs.nix new file mode 100644 index 00000000..6c0edfe8 --- /dev/null +++ b/nix/nixpkgs.nix @@ -0,0 +1,9 @@ +{ system ? builtins.currentSystem }: +let + sources = import ./sources.nix; +in +import sources.nixpkgs { + inherit system; + config = { }; + overlays = [ ]; +} diff --git a/nix/pkgs/protoc-gen-grpc-java/default.nix b/nix/pkgs/protoc-gen-grpc-java/default.nix new file mode 100644 index 00000000..e0651159 --- /dev/null +++ b/nix/pkgs/protoc-gen-grpc-java/default.nix @@ -0,0 +1,23 @@ +{ stdenv, runCommand, fetchurl, autoPatchelfHook, lib }: + +stdenv.mkDerivation rec { + pname = "protoc-gen-grpc-java"; + version = "1.38.0"; + + src = fetchurl { + url = "https://repo1.maven.org/maven2/io/grpc/protoc-gen-grpc-java/${version}/protoc-gen-grpc-java-${version}-linux-x86_64.exe"; + sha256 = "sha256:1gy5lkxj6d4vrgalwnjp15biybcnrmp695si9878y7high39ymr3"; + }; + + nativeBuildInputs = [ autoPatchelfHook ]; + + unpackPhase = '' + cp $src ./bin + chmod +x ./bin + ''; + + installPhase = '' + mkdir -p $out/bin + mv ./bin $out/bin/$pname + ''; +} diff --git a/nix/release.nix b/nix/release.nix new file mode 100644 index 00000000..863f0c9c --- /dev/null +++ b/nix/release.nix @@ -0,0 +1,16 @@ +# Use this file with nix-build-uncached on CI +{ system ? builtins.currentSystem }: +let + nixpkgs = import ./nixpkgs.nix { inherit system; }; + + # This is used to wrap all of our outputs, so they all end-up in the cache. + # + # There are two attributes ` allowSubstitutes = false;` and + # `preferLocalBuild = true;` that influence how derivations gets pulled and + # pushed. + forceCached = import ./lib/force_cached.nix nixpkgs.coreutils; + + # All the packages that we care about + ourPackages = import ./. { inherit nixpkgs system; }; +in +forceCached ourPackages diff --git a/nix/sources.json b/nix/sources.json new file mode 100644 index 00000000..c1ec96f7 --- /dev/null +++ b/nix/sources.json @@ -0,0 +1,14 @@ +{ + "nixpkgs": { + "branch": "nixos-unstable", + "description": "Nix Packages collection", + "homepage": "", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e4ef597edfd8a0ba5f12362932fc9b1dd01a0aef", + "sha256": "1w6y7ma2crcsfph60z8j1k3af0v2m110cbjrb62z287mn4skhqjs", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/e4ef597edfd8a0ba5f12362932fc9b1dd01a0aef.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + } +} diff --git a/nix/sources.nix b/nix/sources.nix new file mode 100644 index 00000000..1fc17a6c --- /dev/null +++ b/nix/sources.nix @@ -0,0 +1,160 @@ +# This file has been generated by Niv. +let + # + # The fetchers. fetch_ fetches specs of type . + # + + fetch_file = pkgs: name: spec: + let + name' = sanitizeName name + "-src"; + in + if spec.builtin or true then + builtins_fetchurl { inherit (spec) url sha256; name = name'; } + else + pkgs.fetchurl { inherit (spec) url sha256; name = name'; }; + + fetch_tarball = pkgs: name: spec: + let + name' = sanitizeName name + "-src"; + in + if spec.builtin or true then + builtins_fetchTarball { name = name'; inherit (spec) url sha256; } + else + pkgs.fetchzip { name = name'; inherit (spec) url sha256; }; + + fetch_git = name: spec: + let + ref = + if spec ? ref then spec.ref else + if spec ? branch then "refs/heads/${spec.branch}" else + if spec ? tag then "refs/tags/${spec.tag}" else + abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!"; + in + builtins.fetchGit { url = spec.repo; inherit (spec) rev; inherit ref; }; + + fetch_local = spec: spec.path; + + fetch_builtin-tarball = name: throw + ''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`. + $ niv modify ${name} -a type=tarball -a builtin=true''; + + fetch_builtin-url = name: throw + ''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`. + $ niv modify ${name} -a type=file -a builtin=true''; + + # + # Various helpers + # + + # https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695 + sanitizeName = name: + ( + concatMapStrings (s: if builtins.isList s then "-" else s) + ( + builtins.split "[^[:alnum:]+._?=-]+" + ((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name) + ) + ); + + # The actual fetching function. + fetch = pkgs: name: spec: + + if ! builtins.hasAttr "type" spec then + abort "ERROR: niv spec ${name} does not have a 'type' attribute" + else if spec.type == "file" then fetch_file pkgs name spec + else if spec.type == "tarball" then fetch_tarball pkgs name spec + else if spec.type == "git" then fetch_git name spec + else if spec.type == "local" then fetch_local spec + else if spec.type == "builtin-tarball" then fetch_builtin-tarball name + else if spec.type == "builtin-url" then fetch_builtin-url name + else + abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}"; + + # If the environment variable NIV_OVERRIDE_${name} is set, then use + # the path directly as opposed to the fetched source. + replace = name: drv: + let + saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name; + ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}"; + in + if ersatz == "" then drv else + # this turns the string into an actual Nix path (for both absolute and + # relative paths) + if builtins.substring 0 1 ersatz == "/" then /. + ersatz else /. + builtins.getEnv "PWD" + "/${ersatz}"; + + # Ports of functions for older nix versions + + # a Nix version of mapAttrs if the built-in doesn't exist + mapAttrs = builtins.mapAttrs or ( + f: set: with builtins; + listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set)) + ); + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295 + range = first: last: if first > last then [ ] else builtins.genList (n: first + n) (last - first + 1); + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257 + stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1)); + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269 + stringAsChars = f: s: concatStrings (map f (stringToCharacters s)); + concatMapStrings = f: list: concatStrings (map f list); + concatStrings = builtins.concatStringsSep ""; + + # https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331 + optionalAttrs = cond: as: if cond then as else { }; + + # fetchTarball version that is compatible between all the versions of Nix + builtins_fetchTarball = { url, name ? null, sha256 }@attrs: + let + inherit (builtins) lessThan nixVersion fetchTarball; + in + if lessThan nixVersion "1.12" then + fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; })) + else + fetchTarball attrs; + + # fetchurl version that is compatible between all the versions of Nix + builtins_fetchurl = { url, name ? null, sha256 }@attrs: + let + inherit (builtins) lessThan nixVersion fetchurl; + in + if lessThan nixVersion "1.12" then + fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; })) + else + fetchurl attrs; + + # Create the final "sources" from the config + mkSources = config: + mapAttrs + ( + name: spec: + if builtins.hasAttr "outPath" spec + then + abort + "The values in sources.json should not have an 'outPath' attribute" + else + spec // { outPath = replace name (fetch config.pkgs name spec); } + ) + config.sources; + + # The "config" used by the fetchers + mkConfig = + { sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null + , sources ? if isNull sourcesFile then { } else builtins.fromJSON (builtins.readFile sourcesFile) + , system ? builtins.currentSystem + , pkgs ? abort '' + Some source is being used outside of nixpkgs. For example using import. + + Edit the sources.json and add `"builtin": true` to that source. + '' + }: rec { + # The sources, i.e. the attribute set of spec name to spec + inherit sources; + + # The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers + inherit pkgs; + }; + +in +mkSources (mkConfig { }) // { __functor = _: settings: mkSources (mkConfig settings); } diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..0778dbab --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +enableFeaturePreview("VERSION_CATALOGS") +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")