From 275e06b5046d9bdb2bb00fc4528b1bf2d6b9dea4 Mon Sep 17 00:00:00 2001 From: Ilguiz Latypov Date: Thu, 19 Mar 2020 18:28:11 -0400 Subject: [PATCH 1/4] Test connectivity. Exclude auto-generated tests as they do nothing. Separate an integration test from the unit tests. This allows using "mvn verify" and a parameter file src/it/resources/integration-test.properties Allow running a single test directly with java, java -cp target/ssc-restapi-client-2.0.jar:target/lib/*:target/test-classes \ -Djavax.net.debug=all ListProjectsIT Highlight authentication failures. --- .gitignore | 4 + pom.xml | 70 ++++++++-- src/it/java/ListProjectsIT.java | 123 ++++++++++++++++++ .../integration-test-sample.properties | 4 + src/it/resources/log4j2-test.xml | 17 +++ 5 files changed, 207 insertions(+), 11 deletions(-) create mode 100644 src/it/java/ListProjectsIT.java create mode 100644 src/it/resources/integration-test-sample.properties create mode 100644 src/it/resources/log4j2-test.xml diff --git a/.gitignore b/.gitignore index a451817..52f5665 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,7 @@ hs_err_pid* target .gradle build + +# integration test parameters +src/it/resources/integration-test.properties + diff --git a/pom.xml b/pom.xml index 671900c..f461a23 100644 --- a/pom.xml +++ b/pom.xml @@ -53,22 +53,38 @@ + org.apache.maven.plugins maven-surefire-plugin - 2.12 + 2.22.2 - - - loggerPath - conf/log4j.properties - - -Xms512m -Xmx1500m - methods - pertest + 1 + false + + com.fortify.ssc.restclient.api.*Test + + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.22.2 + + + + integration-test + verify + + + + + -Xms512m -Xmx1500m + + + maven-dependency-plugin @@ -84,6 +100,12 @@ + + org.apache.maven.plugins + maven-resources-plugin + 3.1.0 + + org.apache.maven.plugins @@ -127,8 +149,8 @@ - - src/test/java + src/test/java + src/it/java @@ -161,6 +183,16 @@ + + + + src/it/resources + + **/*.properties + **/*.xml + + + @@ -225,6 +257,21 @@ ${junit-version} test + + commons-codec + commons-codec + 1.14 + + + org.apache.logging.log4j + log4j-api + ${log4j-version} + + + org.apache.logging.log4j + log4j-core + ${log4j-version} + 1.7 @@ -237,6 +284,7 @@ 1.3.5 1.0.0 4.12 + 2.12.1 UTF-8 diff --git a/src/it/java/ListProjectsIT.java b/src/it/java/ListProjectsIT.java new file mode 100644 index 0000000..a67ef21 --- /dev/null +++ b/src/it/java/ListProjectsIT.java @@ -0,0 +1,123 @@ +import com.fortify.ssc.restclient.*; +import com.fortify.ssc.restclient.auth.*; +import com.fortify.ssc.restclient.model.*; +import com.fortify.ssc.restclient.api.ProjectControllerApi; +import com.fortify.ssc.restclient.api.ProjectVersionOfProjectControllerApi; +import org.apache.commons.codec.binary.Base64; + +import org.junit.Test; +import org.junit.Before; +import static org.junit.Assert.*; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.StringWriter; +import java.io.PrintWriter; +import java.util.Properties; + +public class ListProjectsIT { + private static Logger LOGGER = LogManager.getLogger(ListProjectsIT.class.getName()); + + private Properties props; + + private ApiClient defaultClient; + private ProjectControllerApi apiInstance; + + public void initFromProperties(Properties props) throws java.io.UnsupportedEncodingException { + this.props = props; + defaultClient = Configuration.getDefaultApiClient(); + String apiToken = props.getProperty("it.fortifyApiToken"); + if (apiToken == null || apiToken.trim().length() == 0) { + throw new RuntimeException("Missing it.fortifyApiToken"); + } + String apiBase = props.getProperty("it.fortifyApiBase"); + if (apiBase == null || apiBase.trim().length() == 0) { + throw new RuntimeException("Missing it.fortifyApiBase"); + } + defaultClient.setBasePath(apiBase); + // Configure API key authorization: FortifyToken + ApiKeyAuth fortifyToken = (ApiKeyAuth) defaultClient.getAuthentication("FortifyToken"); + fortifyToken.setApiKey(Base64.encodeBase64String(apiToken.getBytes("UTF-8"))); + fortifyToken.setApiKeyPrefix("FortifyToken"); + } + + @Before + public void init() throws java.io.IOException, java.io.UnsupportedEncodingException { + Properties props = new Properties(); + try (java.io.InputStream stream = this.getClass().getResourceAsStream("/integration-test.properties")) { + if (stream == null) { + props = System.getProperties(); + } else { + props.load(stream); + } + } + initFromProperties(props); + } + + @Test + public void testList() throws ApiException { + String projectName = props.getProperty("it.fortifyProjectName"); + if (projectName == null || projectName.trim().length() == 0) { + throw new RuntimeException("Missing it.fortifyProjectName"); + } + String fields = null; // "id,name,description,createdBy,creationDate,issueTemplateId,id"; + + Integer start = null; + Integer limit = null; + String q = "name:" + projectName; + Boolean fulltextsearch = null; + String orderby = null; + + LOGGER.info("Connecting to " + defaultClient.getBasePath() + " and reading a project " + projectName + "..."); + ProjectControllerApi projectController = new ProjectControllerApi(); + ApiResultListProject projectsResult = null; + try { + projectsResult = projectController.listProject(fields, start, limit, q, fulltextsearch, orderby); + LOGGER.info(projectsResult); + + assertEquals(1L, projectsResult.getCount().longValue()); + assertEquals(projectName, ((Project)projectsResult.getData().get(0)).getName()); + } catch (ApiException e) { + LOGGER.error("HTTP response code " + e.getCode()); + if (e.getCode() == 401) { + LOGGER.error("Expected a fresh CIToken in it.fortifyApiToken"); + } else { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + LOGGER.warn(sw.toString()); + } + throw e; + } + + Long projectId = ((Project)projectsResult.getData().get(0)).getId(); + q = null; + Boolean includeInactive = null; + Boolean myAssignedIssues = null; + LOGGER.info("Reading project " + projectId.longValue()); + ProjectVersionOfProjectControllerApi versionsOfProjectController = new ProjectVersionOfProjectControllerApi(); + try { + ApiResultListProjectVersion versionsResult = versionsOfProjectController.listProjectVersionOfProject(projectId, + fields, start, limit, q, fulltextsearch, orderby, includeInactive, myAssignedIssues); + LOGGER.info(versionsResult); + } catch (ApiException e) { + String codeMessage = "HTTP response code " + e.getCode(); + if (e.getCode() == 401) { + LOGGER.error(codeMessage + ": Expected a fresh CIToken in it.fortifyApiToken"); + } else { + LOGGER.error(codeMessage); + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + LOGGER.warn(sw.toString()); + } + throw e; + } + } + + public static void main(String[] args) throws java.io.IOException, java.io.UnsupportedEncodingException, ApiException { + ListProjectsIT ts = new ListProjectsIT(); + ts.init(); + ts.testList(); + } +} + diff --git a/src/it/resources/integration-test-sample.properties b/src/it/resources/integration-test-sample.properties new file mode 100644 index 0000000..6a7a915 --- /dev/null +++ b/src/it/resources/integration-test-sample.properties @@ -0,0 +1,4 @@ +it.fortifyApiBase=https://fortify.example.com/ssc/api/v1 +it.fortifyApiToken=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX +# it.fortifyProjectVersionId=8004 +it.fortifyProjectName=WebGoat diff --git a/src/it/resources/log4j2-test.xml b/src/it/resources/log4j2-test.xml new file mode 100644 index 0000000..f6765f3 --- /dev/null +++ b/src/it/resources/log4j2-test.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + From c81363261c7ea1063c8aaf1d87af169ea2afb876 Mon Sep 17 00:00:00 2001 From: Ilguiz Latypov Date: Thu, 18 Jun 2020 17:56:09 -0400 Subject: [PATCH 2/4] Calculate coverage. --- pom.xml | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 118 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index f461a23..505340a 100644 --- a/pom.xml +++ b/pom.xml @@ -59,7 +59,7 @@ maven-surefire-plugin 2.22.2 - -Xms512m -Xmx1500m + ${surefire.jacoco.args} -Xms512m -Xmx1500m 1 false @@ -81,7 +81,7 @@ - -Xms512m -Xmx1500m + ${failsafe.jacoco.args} -Xms512m -Xmx1500m @@ -160,6 +160,9 @@ org.apache.maven.plugins maven-javadoc-plugin 2.10.4 + + 8 + attach-javadocs @@ -182,6 +185,112 @@ + + org.jacoco + jacoco-maven-plugin + ${jacoco-version} + + + + before-unit-test-execution + + prepare-agent + + + ${project.build.directory}/jacoco-output/jacoco-unit-tests.exec + surefire.jacoco.args + + + + after-unit-test-execution + test + + report + + + ${project.build.directory}/jacoco-output/jacoco-unit-tests.exec + ${project.reporting.outputDirectory}/jacoco-unit-test-coverage-report + + + + before-integration-test-execution + pre-integration-test + + prepare-agent + + + ${project.build.directory}/jacoco-output/jacoco-integration-tests.exec + failsafe.jacoco.args + + + + after-integration-test-execution + post-integration-test + + report + + + ${project.build.directory}/jacoco-output/jacoco-integration-tests.exec + ${project.reporting.outputDirectory}/jacoco-integration-test-coverage-report + + + + merge-unit-and-integration + post-integration-test + + merge + + + + + ${project.build.directory}/jacoco-output/ + + *.exec + + + + ${project.build.directory}/jacoco-output/merged.exec + + + + create-merged-report + post-integration-test + + report + + + ${project.build.directory}/jacoco-output/merged.exec + ${project.reporting.outputDirectory}/jacoco-merged-test-coverage-report + + + + jacoco-check + verify + + check + + + + + CLASS + + *Test + *IT + + + + LINE + COVEREDRATIO + 90% + + + + + ${project.build.directory}/jacoco-output/merged.exec + + + + @@ -272,6 +381,11 @@ log4j-core ${log4j-version} + + javax.annotation + javax.annotation-api + 1.3.2 + 1.7 @@ -281,10 +395,11 @@ 1.5.15 2.7.5 2.8.1 - 1.3.5 + 1.3.5 1.0.0 4.12 2.12.1 + 0.8.5 UTF-8 From 98071acb951f53fa1f512281b789f5474c2f90db Mon Sep 17 00:00:00 2001 From: Ilguiz Latypov Date: Sat, 20 Jun 2020 07:48:44 -0400 Subject: [PATCH 3/4] Unit test one class. --- pom.xml | 16 ++- settings.xml.example | 65 +++++++++ .../api/ProjectControllerApiTest.java | 123 +++++++++++++++--- 3 files changed, 183 insertions(+), 21 deletions(-) create mode 100644 settings.xml.example diff --git a/pom.xml b/pom.xml index 505340a..bd2062b 100644 --- a/pom.xml +++ b/pom.xml @@ -62,9 +62,9 @@ ${surefire.jacoco.args} -Xms512m -Xmx1500m 1 false - - com.fortify.ssc.restclient.api.*Test - + + com.fortify.ssc.restclient.api.ProjectControllerApiTest + @@ -136,8 +136,7 @@ - - src/main/java + src/main/java @@ -281,7 +280,7 @@ LINE COVEREDRATIO - 90% + 0% @@ -339,6 +338,11 @@ okhttp ${okhttp-version} + + com.squareup.okhttp + mockwebserver + ${okhttp-version} + com.squareup.okhttp logging-interceptor diff --git a/settings.xml.example b/settings.xml.example new file mode 100644 index 0000000..39ebf5a --- /dev/null +++ b/settings.xml.example @@ -0,0 +1,65 @@ + + + + + anyother + central + https://SERVER.test/artifactory/jcenter + + + + + + + + false + + libs-release + https://SERVER.test/artifactory/libs-release + + + + libs-snapshot + https://SERVER.test/artifactory/libs-snapshot + + + + + + false + + plugins-release-local + https://SERVER.test/artifactory/plugins-release-local + + + artifactory + + + + artifactory + + + + anyother + USER + AKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX8w + + + libs-release + USER + AKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX8w + + + libs-snapshot + USER + AKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX8w + + + plugins-release-local + USER + AKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX8w + + + + diff --git a/src/test/java/com/fortify/ssc/restclient/api/ProjectControllerApiTest.java b/src/test/java/com/fortify/ssc/restclient/api/ProjectControllerApiTest.java index 680797f..2a8ee3c 100644 --- a/src/test/java/com/fortify/ssc/restclient/api/ProjectControllerApiTest.java +++ b/src/test/java/com/fortify/ssc/restclient/api/ProjectControllerApiTest.java @@ -20,10 +20,19 @@ import com.fortify.ssc.restclient.model.ApiResultApplicationNameTestResponse; import com.fortify.ssc.restclient.model.ApiResultListProject; import com.fortify.ssc.restclient.model.ApiResultProject; +import com.fortify.ssc.restclient.model.ApiActionResponse; import com.fortify.ssc.restclient.model.ApplicationNameTestRequest; +import com.fortify.ssc.restclient.model.ApplicationNameTestResponse; import com.fortify.ssc.restclient.model.Project; + import org.junit.Test; import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Before; +import static org.junit.Assert.*; + +import com.squareup.okhttp.mockwebserver.MockWebServer; +import com.squareup.okhttp.mockwebserver.MockResponse; import java.util.ArrayList; import java.util.HashMap; @@ -33,12 +42,14 @@ /** * API tests for ProjectControllerApi */ -@Ignore public class ProjectControllerApiTest { private final ProjectControllerApi api = new ProjectControllerApi(); - + @Rule + public MockWebServer mockBackend = new MockWebServer(); + + /** * doCollectionAction * @@ -49,10 +60,24 @@ public class ProjectControllerApiTest { */ @Test public void doCollectionActionProjectTest() throws ApiException { - ApiCollectionActionlong apiResourceAction = null; - ApiResultApiActionResponse response = api.doCollectionActionProject(apiResourceAction); + api.getApiClient().setBasePath(mockBackend.url("/ssc/api/v1").toString()); + mockBackend.enqueue( + new MockResponse().setBody("{" + + "\"data\":{" + + "\"status\":\"success\"," + + "\"message\":\"Application search completed\"," + + "\"values\":{\"found\":false}" + + "}," + + "\"responseCode\":200" + + "}") + ); + ApiCollectionActionlong apiCollAction = new ApiCollectionActionlong() + .addIdsItem(1441L) + .type(ApiCollectionActionlong.TypeEnum.REFRESH); + ApiResultApiActionResponse response = api.doCollectionActionProject(apiCollAction); - // TODO: test validations + assertEquals("Application search completed", response.getData().getMessage()); + assertEquals(ApiActionResponse.StatusEnum.SUCCESS, response.getData().getStatus()); } /** @@ -71,9 +96,36 @@ public void listProjectTest() throws ApiException { String q = null; Boolean fulltextsearch = null; String orderby = null; + + api.getApiClient().setBasePath(mockBackend.url("/ssc/api/v1").toString()); + mockBackend.enqueue( + new MockResponse().setBody("{\"data\": [" + + "{" + + "\"id\": 1441," + + "\"name\": \"APP_ONE\"," + + "\"description\": \"Description for APP_ONE\"," + + "\"creationDate\": \"2019-06-14T15:39:27.000+0000\"," + + "\"createdBy\": \"fortify_ci\"," + + "\"issueTemplateId\": null," + + "\"_href\": \"https://SERVER/ssc/api/v1/projects/1441\"" + + "}," + + "{" + + "\"id\": 1442," + + "\"name\": \"APP_TWO\"," + + "\"description\": \"Description for APP_TWO\"," + + "\"creationDate\": \"2019-06-14T15:46:50.000+0000\"," + + "\"createdBy\": \"fortify_ci\"," + + "\"issueTemplateId\": null," + + "\"_href\": \"https://SERVER/ssc/api/v1/projects/1442\"" + + "}" + + "]," + + "\"count\": 2," + + "\"responseCode\": 200" + + "}")); + ApiResultListProject response = api.listProject(fields, start, limit, q, fulltextsearch, orderby); - // TODO: test validations + assertEquals(2L, response.getCount().longValue()); } /** @@ -86,11 +138,27 @@ public void listProjectTest() throws ApiException { */ @Test public void readProjectTest() throws ApiException { - Long id = null; - String fields = null; + api.getApiClient().setBasePath(mockBackend.url("/ssc/api/v1").toString()); + mockBackend.enqueue( + new MockResponse().setBody("{" + + "\"data\":{" + + "\"id\": 1441," + + "\"name\": \"APP_ONE\"," + + "\"description\": \"Description for APP_ONE\"," + + "\"creationDate\": \"2019-06-14T15:39:27.000+0000\"," + + "\"createdBy\": \"fortify_ci\"," + + "\"issueTemplateId\": null," + + "\"_href\": \"https://SERVER/ssc/api/v1/projects/1441\"" + + "}," + + "\"responseCode\": 200" + + "}") + ); + Long id = 1441L; + String fields = "name,description"; ApiResultProject response = api.readProject(id, fields); - // TODO: test validations + assertEquals("APP_ONE", response.getData().getName()); + assertEquals("Description for APP_ONE", response.getData().getDescription()); } /** @@ -103,10 +171,14 @@ public void readProjectTest() throws ApiException { */ @Test public void testProjectTest() throws ApiException { - ApplicationNameTestRequest resource = null; - ApiResultApplicationNameTestResponse response = api.testProject(resource); + api.getApiClient().setBasePath(mockBackend.url("/ssc/api/v1").toString()); + mockBackend.enqueue( + new MockResponse().setBody("{\"data\": {\"found\": true}, \"responseCode\": 200}") + ); + ApplicationNameTestRequest testReq = new ApplicationNameTestRequest().applicationName("APP_ONE"); + ApiResultApplicationNameTestResponse response = api.testProject(testReq); - // TODO: test validations + assertTrue(response.getData().isFound()); } /** @@ -119,11 +191,32 @@ public void testProjectTest() throws ApiException { */ @Test public void updateProjectTest() throws ApiException { - Long id = null; - Project data = null; + api.getApiClient().setBasePath(mockBackend.url("/ssc/api/v1").toString()); + mockBackend.enqueue( + new MockResponse().setBody("{" + + "\"data\":{" + + "\"id\":1441," + + "\"name\":\"APP_ONE_ORIG\"," + + "\"description\":\"Stashed description for the former APP_ONE\"," + + "\"creationDate\":null," + + "\"createdBy\":null," + + "\"issueTemplateId\":null," + + "\"_href\":\"https://SERVER/ssc/api/v1/projects/1441\"" + + "}," + + "\"responseCode\":200," + + "\"links\":{" + + "\"versions\":{" + + "\"href\":\"https://SERVER/ssc/api/v1/projects/1441/versions\"" + + "}" + + "}" + + "}") + ); + Long id = 1441L; + Project data = new Project().name("APP_ONE_ORIG").description("Stashed description for the former APP_ONE"); ApiResultProject response = api.updateProject(id, data); - // TODO: test validations + assertEquals("APP_ONE_ORIG", response.getData().getName()); + assertEquals("Stashed description for the former APP_ONE", response.getData().getDescription()); } } From 1a632fc021a07e0a609efbb6c90caa4238cbda27 Mon Sep 17 00:00:00 2001 From: Ilguiz Latypov Date: Mon, 22 Jun 2020 02:59:22 -0400 Subject: [PATCH 4/4] Use integration tests and coverage reports under gradle. --- .gitignore | 3 ++ build.gradle | 81 ++++++++++++++++++++++++++++++++++++++- gradle.properties.example | 2 + 3 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 gradle.properties.example diff --git a/.gitignore b/.gitignore index 52f5665..dd66320 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,6 @@ build # integration test parameters src/it/resources/integration-test.properties +# Local artifactory parameters +settings.xml +gradle.properties diff --git a/build.gradle b/build.gradle index 255b993..2b78fa3 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,6 @@ apply plugin: 'idea' apply plugin: 'eclipse' +apply plugin: 'jacoco' //apply from: file('fortify-custom.gradle') group = 'com.fortify' @@ -17,7 +18,9 @@ buildscript { } repositories { - jcenter() + maven { + url artifactory_dependencies_url + } } @@ -95,12 +98,88 @@ if(hasProperty('target') && target == 'android') { } } +sourceSets { + integrationTest { + java { + compileClasspath += main.output + test.output + runtimeClasspath += main.output + test.output + srcDir file('src/it/java') + } + resources.srcDir file('src/it/resources') + } +} + +configurations { + integrationTestCompile.extendsFrom testCompile + integrationTestRuntime.extendsFrom testRuntime +} + +task integrationTest(type: Test) { + testClassesDirs = sourceSets.integrationTest.output.classesDirs + classpath = sourceSets.integrationTest.runtimeClasspath + outputs.upToDateWhen { false } +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// https://stackoverflow.com/questions/19025138/gradle-how-to-generate-coverage-report-for-integration-test-using-jacoco +// answered 2019-08-02 by Brice + +// Without it, the only data is the binary data, +// but I need the XML and HTML report after any test task +tasks.withType(Test) { + finalizedBy jacocoTestReport +} + +// Configure the report to look for executionData generated during the test and integrationTest task +jacocoTestReport { + executionData(file("${project.buildDir}/jacoco/test.exec"), + file("${project.buildDir}/jacoco/integrationTest.exec")) + reports { + // for sonarqube + xml.enabled true + xml.destination(file("${project.buildDir}/reports/jacoco/all-tests/jacocoAllTestReport.xml")) + // for devs + html.enabled true + html.destination file("${project.buildDir}/reports/jacoco/all-tests/html") + } +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +integrationTest.mustRunAfter test +jacocoTestReport.dependsOn integrationTest + +jacocoTestCoverageVerification { + violationRules { + rule { + // enabled = false + element = 'CLASS' + excludes = ['*Test', '*IT'] + + limit { + counter = 'LINE' + value = 'COVEREDRATIO' + minimum = 0.0 + } + } + } +} + +jacocoTestCoverageVerification.dependsOn jacocoTestReport +check.dependsOn jacocoTestCoverageVerification + dependencies { compile 'io.swagger:swagger-annotations:1.5.15' compile 'com.squareup.okhttp:okhttp:2.7.5' compile 'com.squareup.okhttp:logging-interceptor:2.7.5' + compile 'com.squareup.okhttp:mockwebserver:2.7.5' compile 'com.google.code.gson:gson:2.8.1' compile 'io.gsonfire:gson-fire:1.8.0' compile 'org.threeten:threetenbp:1.3.5' + compile 'javax.annotation:javax.annotation-api:1.3.2' testCompile 'junit:junit:4.12' + integrationTestCompile 'commons-codec:commons-codec:1.14' + integrationTestCompile 'org.apache.logging.log4j:log4j-api:2.12.1' + integrationTestRuntime 'org.apache.logging.log4j:log4j-core:2.12.1' } + diff --git a/gradle.properties.example b/gradle.properties.example new file mode 100644 index 0000000..8dbae4a --- /dev/null +++ b/gradle.properties.example @@ -0,0 +1,2 @@ +artifactory_dependencies_url=https://SERVER/artifactory/REPO +org.gradle.daemon=false