diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ea35f9b9b..4e2000db7 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -40,6 +40,9 @@ jobs:
build:
timeout-minutes: 15
name: build
+ permissions:
+ contents: read
+ id-token: write
runs-on: ${{ github.repository == 'stainless-sdks/increase-java' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
@@ -61,6 +64,21 @@ jobs:
- name: Build SDK
run: ./scripts/build
+ - name: Get GitHub OIDC Token
+ if: github.repository == 'stainless-sdks/increase-java'
+ id: github-oidc
+ uses: actions/github-script@v6
+ with:
+ script: core.setOutput('github_token', await core.getIDToken());
+
+ - name: Build and upload Maven artifacts
+ if: github.repository == 'stainless-sdks/increase-java'
+ env:
+ URL: https://pkg.stainless.com/s
+ AUTH: ${{ steps.github-oidc.outputs.github_token }}
+ SHA: ${{ github.sha }}
+ PROJECT: increase-java
+ run: ./scripts/upload-artifacts
test:
timeout-minutes: 15
name: test
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 02bfb399e..842d1edb2 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.395.0"
+ ".": "0.396.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index af0e17b5e..4b965774e 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 232
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/increase%2Fincrease-7a47821c7d33caac95ba05890682dde6da257dbe86033e4f119aa626c11ae387.yml
-openapi_spec_hash: 0ccabc90834936bc2fcdeeee01e77a64
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/increase%2Fincrease-a559a6a1a1f3781fad8db5bcb96c40b69a78b952d659395840accce782098e0c.yml
+openapi_spec_hash: 2ae62041468e5cf6fe653d65b1b7a58a
config_hash: 8a9bb9e2d5dd0ccc3e78ad59f924fd3c
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5f3be5af3..887ad68e4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,19 @@
# Changelog
+## 0.396.0 (2026-01-14)
+
+Full Changelog: [v0.395.0...v0.396.0](https://github.com/Increase/increase-java/compare/v0.395.0...v0.396.0)
+
+### Features
+
+* **api:** api update ([7a3f167](https://github.com/Increase/increase-java/commit/7a3f1676006a0ebdabcb9557b432b0068b9fc19b))
+* **client:** allow configuring dispatcher executor service ([cb9ec15](https://github.com/Increase/increase-java/commit/cb9ec1516cfc976ef1f7ac5256804193c569033a))
+
+
+### Chores
+
+* **internal:** support uploading Maven repo artifacts to stainless package server ([86f6e2f](https://github.com/Increase/increase-java/commit/86f6e2f373c8117a7ff2c84cb76c177b9945fb28))
+
## 0.395.0 (2026-01-08)
Full Changelog: [v0.394.0...v0.395.0](https://github.com/Increase/increase-java/compare/v0.394.0...v0.395.0)
diff --git a/README.md b/README.md
index bb2fa23ab..8b57c83a4 100644
--- a/README.md
+++ b/README.md
@@ -2,8 +2,8 @@
-[](https://central.sonatype.com/artifact/com.increase.api/increase-java/0.395.0)
-[](https://javadoc.io/doc/com.increase.api/increase-java/0.395.0)
+[](https://central.sonatype.com/artifact/com.increase.api/increase-java/0.396.0)
+[](https://javadoc.io/doc/com.increase.api/increase-java/0.396.0)
@@ -13,7 +13,7 @@ The Increase Java SDK is similar to the Increase Kotlin SDK but with minor diffe
-The REST API documentation can be found on [increase.com](https://increase.com/documentation). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.increase.api/increase-java/0.395.0).
+The REST API documentation can be found on [increase.com](https://increase.com/documentation). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.increase.api/increase-java/0.396.0).
@@ -24,7 +24,7 @@ The REST API documentation can be found on [increase.com](https://increase.com/d
### Gradle
```kotlin
-implementation("com.increase.api:increase-java:0.395.0")
+implementation("com.increase.api:increase-java:0.396.0")
```
### Maven
@@ -33,7 +33,7 @@ implementation("com.increase.api:increase-java:0.395.0")
com.increase.api
increase-java
- 0.395.0
+ 0.396.0
```
diff --git a/build.gradle.kts b/build.gradle.kts
index c7fd06b53..83eb758c8 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -8,7 +8,7 @@ repositories {
allprojects {
group = "com.increase.api"
- version = "0.395.0" // x-release-please-version
+ version = "0.396.0" // x-release-please-version
}
subprojects {
diff --git a/buildSrc/src/main/kotlin/increase.publish.gradle.kts b/buildSrc/src/main/kotlin/increase.publish.gradle.kts
index 6269c49ab..bc25185b4 100644
--- a/buildSrc/src/main/kotlin/increase.publish.gradle.kts
+++ b/buildSrc/src/main/kotlin/increase.publish.gradle.kts
@@ -7,6 +7,17 @@ plugins {
id("com.vanniktech.maven.publish")
}
+publishing {
+ repositories {
+ if (project.hasProperty("publishLocal")) {
+ maven {
+ name = "LocalFileSystem"
+ url = uri("${rootProject.layout.buildDirectory.get()}/local-maven-repo")
+ }
+ }
+ }
+}
+
repositories {
gradlePluginPortal()
mavenCentral()
@@ -17,8 +28,10 @@ extra["signingInMemoryKeyId"] = System.getenv("GPG_SIGNING_KEY_ID")
extra["signingInMemoryKeyPassword"] = System.getenv("GPG_SIGNING_PASSWORD")
configure {
- signAllPublications()
- publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL)
+ if (!project.hasProperty("publishLocal")) {
+ signAllPublications()
+ publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL)
+ }
coordinates(project.group.toString(), project.name, project.version.toString())
configure(
diff --git a/increase-java-client-okhttp/src/main/kotlin/com/increase/api/client/okhttp/IncreaseOkHttpClient.kt b/increase-java-client-okhttp/src/main/kotlin/com/increase/api/client/okhttp/IncreaseOkHttpClient.kt
index 8d8f55ae4..849f2ac30 100644
--- a/increase-java-client-okhttp/src/main/kotlin/com/increase/api/client/okhttp/IncreaseOkHttpClient.kt
+++ b/increase-java-client-okhttp/src/main/kotlin/com/increase/api/client/okhttp/IncreaseOkHttpClient.kt
@@ -18,6 +18,7 @@ import java.time.Clock
import java.time.Duration
import java.util.Optional
import java.util.concurrent.Executor
+import java.util.concurrent.ExecutorService
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
@@ -46,11 +47,31 @@ class IncreaseOkHttpClient private constructor() {
class Builder internal constructor() {
private var clientOptions: ClientOptions.Builder = ClientOptions.builder()
+ private var dispatcherExecutorService: ExecutorService? = null
private var proxy: Proxy? = null
private var sslSocketFactory: SSLSocketFactory? = null
private var trustManager: X509TrustManager? = null
private var hostnameVerifier: HostnameVerifier? = null
+ /**
+ * The executor service to use for running HTTP requests.
+ *
+ * Defaults to OkHttp's
+ * [default executor service](https://github.com/square/okhttp/blob/ace792f443b2ffb17974f5c0d1cecdf589309f26/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt#L98-L104).
+ *
+ * This class takes ownership of the executor service and shuts it down when closed.
+ */
+ fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply {
+ this.dispatcherExecutorService = dispatcherExecutorService
+ }
+
+ /**
+ * Alias for calling [Builder.dispatcherExecutorService] with
+ * `dispatcherExecutorService.orElse(null)`.
+ */
+ fun dispatcherExecutorService(dispatcherExecutorService: Optional) =
+ dispatcherExecutorService(dispatcherExecutorService.getOrNull())
+
fun proxy(proxy: Proxy?) = apply { this.proxy = proxy }
/** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */
@@ -323,6 +344,7 @@ class IncreaseOkHttpClient private constructor() {
OkHttpClient.builder()
.timeout(clientOptions.timeout())
.proxy(proxy)
+ .dispatcherExecutorService(dispatcherExecutorService)
.sslSocketFactory(sslSocketFactory)
.trustManager(trustManager)
.hostnameVerifier(hostnameVerifier)
diff --git a/increase-java-client-okhttp/src/main/kotlin/com/increase/api/client/okhttp/IncreaseOkHttpClientAsync.kt b/increase-java-client-okhttp/src/main/kotlin/com/increase/api/client/okhttp/IncreaseOkHttpClientAsync.kt
index d80607c7e..525f508ee 100644
--- a/increase-java-client-okhttp/src/main/kotlin/com/increase/api/client/okhttp/IncreaseOkHttpClientAsync.kt
+++ b/increase-java-client-okhttp/src/main/kotlin/com/increase/api/client/okhttp/IncreaseOkHttpClientAsync.kt
@@ -18,6 +18,7 @@ import java.time.Clock
import java.time.Duration
import java.util.Optional
import java.util.concurrent.Executor
+import java.util.concurrent.ExecutorService
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
@@ -46,11 +47,31 @@ class IncreaseOkHttpClientAsync private constructor() {
class Builder internal constructor() {
private var clientOptions: ClientOptions.Builder = ClientOptions.builder()
+ private var dispatcherExecutorService: ExecutorService? = null
private var proxy: Proxy? = null
private var sslSocketFactory: SSLSocketFactory? = null
private var trustManager: X509TrustManager? = null
private var hostnameVerifier: HostnameVerifier? = null
+ /**
+ * The executor service to use for running HTTP requests.
+ *
+ * Defaults to OkHttp's
+ * [default executor service](https://github.com/square/okhttp/blob/ace792f443b2ffb17974f5c0d1cecdf589309f26/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt#L98-L104).
+ *
+ * This class takes ownership of the executor service and shuts it down when closed.
+ */
+ fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply {
+ this.dispatcherExecutorService = dispatcherExecutorService
+ }
+
+ /**
+ * Alias for calling [Builder.dispatcherExecutorService] with
+ * `dispatcherExecutorService.orElse(null)`.
+ */
+ fun dispatcherExecutorService(dispatcherExecutorService: Optional) =
+ dispatcherExecutorService(dispatcherExecutorService.getOrNull())
+
fun proxy(proxy: Proxy?) = apply { this.proxy = proxy }
/** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */
@@ -323,6 +344,7 @@ class IncreaseOkHttpClientAsync private constructor() {
OkHttpClient.builder()
.timeout(clientOptions.timeout())
.proxy(proxy)
+ .dispatcherExecutorService(dispatcherExecutorService)
.sslSocketFactory(sslSocketFactory)
.trustManager(trustManager)
.hostnameVerifier(hostnameVerifier)
diff --git a/increase-java-client-okhttp/src/main/kotlin/com/increase/api/client/okhttp/OkHttpClient.kt b/increase-java-client-okhttp/src/main/kotlin/com/increase/api/client/okhttp/OkHttpClient.kt
index 29560cac0..dc73395b5 100644
--- a/increase-java-client-okhttp/src/main/kotlin/com/increase/api/client/okhttp/OkHttpClient.kt
+++ b/increase-java-client-okhttp/src/main/kotlin/com/increase/api/client/okhttp/OkHttpClient.kt
@@ -15,11 +15,13 @@ import java.net.Proxy
import java.time.Duration
import java.util.concurrent.CancellationException
import java.util.concurrent.CompletableFuture
+import java.util.concurrent.ExecutorService
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
import okhttp3.Call
import okhttp3.Callback
+import okhttp3.Dispatcher
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaType
@@ -198,6 +200,7 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien
private var timeout: Timeout = Timeout.default()
private var proxy: Proxy? = null
+ private var dispatcherExecutorService: ExecutorService? = null
private var sslSocketFactory: SSLSocketFactory? = null
private var trustManager: X509TrustManager? = null
private var hostnameVerifier: HostnameVerifier? = null
@@ -208,6 +211,10 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien
fun proxy(proxy: Proxy?) = apply { this.proxy = proxy }
+ fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply {
+ this.dispatcherExecutorService = dispatcherExecutorService
+ }
+
fun sslSocketFactory(sslSocketFactory: SSLSocketFactory?) = apply {
this.sslSocketFactory = sslSocketFactory
}
@@ -229,6 +236,8 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien
.callTimeout(timeout.request())
.proxy(proxy)
.apply {
+ dispatcherExecutorService?.let { dispatcher(Dispatcher(it)) }
+
val sslSocketFactory = sslSocketFactory
val trustManager = trustManager
if (sslSocketFactory != null && trustManager != null) {
diff --git a/increase-java-core/src/main/kotlin/com/increase/api/models/files/File.kt b/increase-java-core/src/main/kotlin/com/increase/api/models/files/File.kt
index e5f09ea54..89b9273f7 100644
--- a/increase-java-core/src/main/kotlin/com/increase/api/models/files/File.kt
+++ b/increase-java-core/src/main/kotlin/com/increase/api/models/files/File.kt
@@ -754,6 +754,9 @@ private constructor(
/** The results of an Export you requested via the dashboard or API. */
@JvmField val EXPORT = of("export")
+ /** A fee statement. */
+ @JvmField val FEE_STATEMENT = of("fee_statement")
+
/** An attachment to an Unusual Activity Report. */
@JvmField
val UNUSUAL_ACTIVITY_REPORT_ATTACHMENT = of("unusual_activity_report_attachment")
@@ -859,6 +862,8 @@ private constructor(
ENTITY_SUPPLEMENTAL_DOCUMENT,
/** The results of an Export you requested via the dashboard or API. */
EXPORT,
+ /** A fee statement. */
+ FEE_STATEMENT,
/** An attachment to an Unusual Activity Report. */
UNUSUAL_ACTIVITY_REPORT_ATTACHMENT,
/** A document granting another entity access to the funds into your account. */
@@ -961,6 +966,8 @@ private constructor(
ENTITY_SUPPLEMENTAL_DOCUMENT,
/** The results of an Export you requested via the dashboard or API. */
EXPORT,
+ /** A fee statement. */
+ FEE_STATEMENT,
/** An attachment to an Unusual Activity Report. */
UNUSUAL_ACTIVITY_REPORT_ATTACHMENT,
/** A document granting another entity access to the funds into your account. */
@@ -1015,6 +1022,7 @@ private constructor(
DOCUMENT_REQUEST -> Value.DOCUMENT_REQUEST
ENTITY_SUPPLEMENTAL_DOCUMENT -> Value.ENTITY_SUPPLEMENTAL_DOCUMENT
EXPORT -> Value.EXPORT
+ FEE_STATEMENT -> Value.FEE_STATEMENT
UNUSUAL_ACTIVITY_REPORT_ATTACHMENT -> Value.UNUSUAL_ACTIVITY_REPORT_ATTACHMENT
DEPOSIT_ACCOUNT_CONTROL_AGREEMENT -> Value.DEPOSIT_ACCOUNT_CONTROL_AGREEMENT
PROOF_OF_AUTHORIZATION_REQUEST_SUBMISSION ->
@@ -1062,6 +1070,7 @@ private constructor(
DOCUMENT_REQUEST -> Known.DOCUMENT_REQUEST
ENTITY_SUPPLEMENTAL_DOCUMENT -> Known.ENTITY_SUPPLEMENTAL_DOCUMENT
EXPORT -> Known.EXPORT
+ FEE_STATEMENT -> Known.FEE_STATEMENT
UNUSUAL_ACTIVITY_REPORT_ATTACHMENT -> Known.UNUSUAL_ACTIVITY_REPORT_ATTACHMENT
DEPOSIT_ACCOUNT_CONTROL_AGREEMENT -> Known.DEPOSIT_ACCOUNT_CONTROL_AGREEMENT
PROOF_OF_AUTHORIZATION_REQUEST_SUBMISSION ->
diff --git a/increase-java-core/src/main/kotlin/com/increase/api/models/files/FileListParams.kt b/increase-java-core/src/main/kotlin/com/increase/api/models/files/FileListParams.kt
index c3a66695b..dba7537d2 100644
--- a/increase-java-core/src/main/kotlin/com/increase/api/models/files/FileListParams.kt
+++ b/increase-java-core/src/main/kotlin/com/increase/api/models/files/FileListParams.kt
@@ -687,6 +687,9 @@ private constructor(
/** The results of an Export you requested via the dashboard or API. */
@JvmField val EXPORT = of("export")
+ /** A fee statement. */
+ @JvmField val FEE_STATEMENT = of("fee_statement")
+
/** An attachment to an Unusual Activity Report. */
@JvmField
val UNUSUAL_ACTIVITY_REPORT_ATTACHMENT = of("unusual_activity_report_attachment")
@@ -792,6 +795,8 @@ private constructor(
ENTITY_SUPPLEMENTAL_DOCUMENT,
/** The results of an Export you requested via the dashboard or API. */
EXPORT,
+ /** A fee statement. */
+ FEE_STATEMENT,
/** An attachment to an Unusual Activity Report. */
UNUSUAL_ACTIVITY_REPORT_ATTACHMENT,
/** A document granting another entity access to the funds into your account. */
@@ -894,6 +899,8 @@ private constructor(
ENTITY_SUPPLEMENTAL_DOCUMENT,
/** The results of an Export you requested via the dashboard or API. */
EXPORT,
+ /** A fee statement. */
+ FEE_STATEMENT,
/** An attachment to an Unusual Activity Report. */
UNUSUAL_ACTIVITY_REPORT_ATTACHMENT,
/** A document granting another entity access to the funds into your account. */
@@ -948,6 +955,7 @@ private constructor(
DOCUMENT_REQUEST -> Value.DOCUMENT_REQUEST
ENTITY_SUPPLEMENTAL_DOCUMENT -> Value.ENTITY_SUPPLEMENTAL_DOCUMENT
EXPORT -> Value.EXPORT
+ FEE_STATEMENT -> Value.FEE_STATEMENT
UNUSUAL_ACTIVITY_REPORT_ATTACHMENT -> Value.UNUSUAL_ACTIVITY_REPORT_ATTACHMENT
DEPOSIT_ACCOUNT_CONTROL_AGREEMENT -> Value.DEPOSIT_ACCOUNT_CONTROL_AGREEMENT
PROOF_OF_AUTHORIZATION_REQUEST_SUBMISSION ->
@@ -995,6 +1003,7 @@ private constructor(
DOCUMENT_REQUEST -> Known.DOCUMENT_REQUEST
ENTITY_SUPPLEMENTAL_DOCUMENT -> Known.ENTITY_SUPPLEMENTAL_DOCUMENT
EXPORT -> Known.EXPORT
+ FEE_STATEMENT -> Known.FEE_STATEMENT
UNUSUAL_ACTIVITY_REPORT_ATTACHMENT -> Known.UNUSUAL_ACTIVITY_REPORT_ATTACHMENT
DEPOSIT_ACCOUNT_CONTROL_AGREEMENT -> Known.DEPOSIT_ACCOUNT_CONTROL_AGREEMENT
PROOF_OF_AUTHORIZATION_REQUEST_SUBMISSION ->
diff --git a/scripts/upload-artifacts b/scripts/upload-artifacts
new file mode 100755
index 000000000..729e6f222
--- /dev/null
+++ b/scripts/upload-artifacts
@@ -0,0 +1,96 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+# ANSI Color Codes
+GREEN='\033[32m'
+RED='\033[31m'
+NC='\033[0m' # No Color
+
+log_error() {
+ local msg="$1"
+ local headers="$2"
+ local body="$3"
+ echo -e "${RED}${msg}${NC}"
+ [[ -f "$headers" ]] && echo -e "${RED}Headers:$(cat "$headers")${NC}"
+ echo -e "${RED}Body: ${body}${NC}"
+ exit 1
+}
+
+upload_file() {
+ local file_name="$1"
+ local tmp_headers
+ tmp_headers=$(mktemp)
+
+ if [ -f "$file_name" ]; then
+ echo -e "${GREEN}Processing file: $file_name${NC}"
+ pkg_file_name="mvn${file_name#./build/local-maven-repo}"
+
+ # Get signed URL for uploading artifact file
+ signed_url_response=$(curl -X POST -G "$URL" \
+ -sS --retry 5 \
+ -D "$tmp_headers" \
+ --data-urlencode "filename=$pkg_file_name" \
+ -H "Authorization: Bearer $AUTH" \
+ -H "Content-Type: application/json")
+
+ # Validate JSON and extract URL
+ if ! signed_url=$(echo "$signed_url_response" | jq -e -r '.url' 2>/dev/null) || [[ "$signed_url" == "null" ]]; then
+ log_error "Failed to get valid signed URL" "$tmp_headers" "$signed_url_response"
+ fi
+
+ # Set content-type based on file extension
+ local extension="${file_name##*.}"
+ local content_type
+ case "$extension" in
+ jar) content_type="application/java-archive" ;;
+ md5|sha1|sha256|sha512) content_type="text/plain" ;;
+ module) content_type="application/json" ;;
+ pom|xml) content_type="application/xml" ;;
+ *) content_type="application/octet-stream" ;;
+ esac
+
+ # Upload file
+ upload_response=$(curl -v -X PUT \
+ --retry 5 \
+ -D "$tmp_headers" \
+ -H "Content-Type: $content_type" \
+ --data-binary "@${file_name}" "$signed_url" 2>&1)
+
+ if ! echo "$upload_response" | grep -q "HTTP/[0-9.]* 200"; then
+ log_error "Failed upload artifact file" "$tmp_headers" "$upload_response"
+ fi
+
+ # Insert small throttle to reduce rate limiting risk
+ sleep 0.1
+ fi
+}
+
+walk_tree() {
+ local current_dir="$1"
+
+ for entry in "$current_dir"/*; do
+ # Check that entry is valid
+ [ -e "$entry" ] || [ -h "$entry" ] || continue
+
+ if [ -d "$entry" ]; then
+ walk_tree "$entry"
+ else
+ upload_file "$entry"
+ fi
+ done
+}
+
+cd "$(dirname "$0")/.."
+
+echo "::group::Creating local Maven content"
+./gradlew publishMavenPublicationToLocalFileSystemRepository -PpublishLocal
+echo "::endgroup::"
+
+echo "::group::Uploading to pkg.stainless.com"
+walk_tree "./build/local-maven-repo"
+echo "::endgroup::"
+
+echo "::group::Generating instructions"
+echo "Configure maven or gradle to use the repo located at 'https://pkg.stainless.com/s/${PROJECT}/${SHA}/mvn'"
+echo "::endgroup::"