Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,10 @@ name: "CodeQL"

on:
push:
branches: [s3mock-v2, main]
branches: [s3mock-v2, s3mock-v3, s3mock-v4, main]
pull_request:
# The branches below must be a subset of the branches above
branches: [s3mock-v2, main]
schedule:
- cron: '43 21 * * 6'
branches: [s3mock-v2, s3mock-v3, s3mock-v4, main]

# Declare default permissions as read only.
permissions: read-all
Expand Down Expand Up @@ -64,12 +62,12 @@ jobs:
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality

# Set up JDK 17, otherwise autobuild will fail below.
# Set up JDK 25, otherwise autobuild will fail below.
- name: Set up JDK
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0
with:
java-version: 21
distribution: 'temurin'
java-version: 25
distribution: 'oracle'
cache: 'maven'

# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/maven-ci-and-prb.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ name: Maven Build

on:
push:
branches: [s3mock-v2, main]
branches: [s3mock-v2, s3mock-v3, s3mock-v4, main]
pull_request:
branches: [s3mock-v2, main]
branches: [s3mock-v2, s3mock-v3, s3mock-v4, main]

# Declare default permissions as read only.
permissions: read-all
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/maven-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ jobs:
- name: Set up JDK
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0
with:
java-version: 21
distribution: 'temurin'
java-version: 25
distribution: 'oracle'
cache: 'maven'

# The release build pushes a Docker image to Docker Hub, so we need to log in
- name: Perform docker login
Expand Down
27 changes: 21 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ Whenever a 3rd party library is updated, S3Mock will update it's MINOR version.
# PLANNED - 6.x - RELEASE TBD
Version 6.x is JDK25 LTS bytecode compatible, with Docker integration.

Probably released with Spring Boot 5.x, updating baselines etc. as Spring Boot 5.x requires.
Will be released after Spring Boot 5.x, updating baselines etc. as Spring Boot 5.x requires.

Any JUnit / direct Java usage support will most likely be dropped and only supported on a best-effort basis.
(i.e., the modules will be deleted from the code base and not released anymore. It *may* be possible to
Expand Down Expand Up @@ -149,7 +149,13 @@ Version 5.x is JDK17 LTS bytecode compatible, with Docker and JUnit / direct Jav
## 5.0.0

* Features and fixes
* Breaking change (file system): Remove "DisplayName" from Owner. (fixes #2738)
* AWS APIs stopped returning "DisplayName" in November 2025.
* This is unfortunately a breaking change for clients starting S3Mock on existing file systems.
* Get object with range now returns the same headers as non-range calls.
* Docker: Copy "s3mock.jar" to "/opt/", run with absolute path reference to avoid issues when working directory is changed. (fixes #2827)
* S3Mock supports ChecksumType.FULL_OBJECT for Multipart uploads (fixes #2843)
* Return 412 on if-none-match=true when making CompleteMultipartRequest (fixes #2790)
* Refactorings
* Use Jackson 3 annotations and mappers.
* AWS has deprecated SDK for Java v1 and will remove support EOY 2025.
Expand All @@ -159,14 +165,23 @@ Version 5.x is JDK17 LTS bytecode compatible, with Docker and JUnit / direct Jav
* Remove legacy properties for S3Mock configuration.
* Move all controller-related code from "com.adobe.testing.s3mock" to "com.adobe.testing.s3mock.controller" package.
* Remove Apache libraries like "commons-compress", "commons-codec" or "commons-lang3" from dependencies. Kotlin and Java standard library provide similar functionality.
* Version updates
* Bump Spring Boot version to 4.0.0
* Version updates (deliverable dependencies)
* Bump Spring Boot version to 4.0.1
* Bump Spring Framework version to 7.0.1
* Bump java version from 17 to 25
* Compile with Java 25, target Java 17
* Bump Java version partially from 17 to 25
* Compile with Java 25, target Java 17. [This follows Spring guidance](https://spring.io/blog/2025/11/13/spring-framework-7-0-general-availability)
* Docker container runs Java 25
* Bump TestContainers to 2.0.2
* Bump Maven to 4.0.0
* Bump kotlin.version from 2.2.21 to 2.3.0
* Compile with Kotlin 2.3, target Kotlin 2.2. [This follows Spring guidance](https://spring.io/blog/2025/12/18/next-level-kotlin-support-in-spring-boot-4#kotlin-2-baseline)
* Version updates (build dependencies)
* Bump Maven to 4.0.0-rc5 (TODO: update to 4.0.0)
* Bump org.apache.maven.plugins:maven-release-plugin from 3.3.0 to 3.3.1
* Bump com.puppycrawl.tools:checkstyle from 12.2.0 to 12.3.0
* Bump actions/upload-artifact from 5.0.0 to 6.0.0
* Bump github/codeql-action from 4.31.6 to 4.31.9
* Bump actions/setup-java from 5.0.0 to 5.1.0
* Bump step-security/harden-runner from 2.13.3 to 2.14.0

# DEPRECATED - 4.x
Version 4.x is JDK17 LTS bytecode compatible, with Docker and JUnit / direct Java integration.
Expand Down
4 changes: 2 additions & 2 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ ENV JAVA_HOME=/opt/java-minimal
ENV PATH="$PATH:$JAVA_HOME/bin"

COPY --from=staging_area "$JAVA_HOME" "$JAVA_HOME"
COPY ./target/s3mock-exec.jar s3mock.jar
COPY ./target/s3mock-exec.jar /opt/s3mock.jar

ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en
Expand All @@ -69,4 +69,4 @@ ENV root=/s3mockroot
EXPOSE 9090 9191

# run the app on startup
ENTRYPOINT ["java", "--illegal-access=warn", "-Djava.security.egd=file:/dev/./urandom", "-XX:+UseZGC", "-XX:+ZGenerational", "-jar", "s3mock.jar" ]
ENTRYPOINT ["java", "--illegal-access=warn", "-Djava.security.egd=file:/dev/./urandom", "-XX:+UseZGC", "-XX:+ZGenerational", "-jar", "/opt/s3mock.jar" ]
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ internal class AclIT : S3TestBase() {
}.also { resp ->
assertThat(resp.sdkHttpResponse().isSuccessful).isTrue()
assertThat(resp.owner().id()).isNotBlank()
assertThat(resp.owner().displayName()).isNotBlank()
assertThat(resp.grants()).hasSize(1)
assertThat(resp.grants().first().permission()).isEqualTo(FULL_CONTROL)
}
Expand All @@ -86,7 +85,6 @@ internal class AclIT : S3TestBase() {

acl.owner().also { owner ->
assertThat(owner.id()).isEqualTo(DEFAULT_OWNER.id)
assertThat(owner.displayName()).isEqualTo(DEFAULT_OWNER.displayName)
}

acl.grants().also {
Expand All @@ -102,7 +100,6 @@ internal class AclIT : S3TestBase() {
.also { grantee ->
assertThat(grantee).isNotNull
assertThat(grantee.id()).isEqualTo(DEFAULT_OWNER.id)
assertThat(grantee.displayName()).isEqualTo(DEFAULT_OWNER.displayName)
assertThat(grantee.type()).isEqualTo(CANONICAL_USER)
}
}
Expand All @@ -126,7 +123,6 @@ internal class AclIT : S3TestBase() {
it.accessControlPolicy {
it.owner {
it.id(userId)
it.displayName(userName)
}
it
.grants(
Expand All @@ -150,7 +146,6 @@ internal class AclIT : S3TestBase() {
acl.owner().also {
assertThat(it).isNotNull
assertThat(it.id()).isEqualTo(userId)
assertThat(it.displayName()).isEqualTo(userName)
}

assertThat(acl.grants()).hasSize(1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@ internal class BucketIT : S3TestBase() {
}
assertThat(it.prefix()).isNull()
assertThat(it.continuationToken()).isNull()
assertThat(it.owner().displayName()).isEqualTo("s3-mock-file-store")
assertThat(it.owner().id()).isEqualTo("79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be")
}
}
Expand Down Expand Up @@ -205,7 +204,6 @@ internal class BucketIT : S3TestBase() {
}
assertThat(it.prefix()).isEqualTo(bucketName)
assertThat(it.continuationToken()).isNull()
assertThat(it.owner().displayName()).isEqualTo("s3-mock-file-store")
assertThat(it.owner().id()).isEqualTo("79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be")
}
}
Expand Down Expand Up @@ -245,7 +243,6 @@ internal class BucketIT : S3TestBase() {
}
assertThat(it.prefix()).isNull()
assertThat(it.continuationToken()).isNotNull
assertThat(it.owner().displayName()).isEqualTo("s3-mock-file-store")
assertThat(it.owner().id()).isEqualTo("79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be")
}.continuationToken()

Expand All @@ -263,7 +260,6 @@ internal class BucketIT : S3TestBase() {
}
assertThat(it.prefix()).isNull()
assertThat(it.continuationToken()).isNull()
assertThat(it.owner().displayName()).isEqualTo("s3-mock-file-store")
assertThat(it.owner().id()).isEqualTo("79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ internal class GetPutDeleteObjectIT : S3TestBase() {
)
}.also {
assertThat(it.eTag()).isEqualTo(eTag.trim('"'))
// default storageClass is STANDARD, which is never returned from APIs except by GetObjectAttributes
// GetObjectAttributes returns the default storageClass "STANDARD", even though other APIs may not.
assertThat(it.storageClass()).isEqualTo(StorageClass.STANDARD)
assertThat(it.objectSize()).isEqualTo(UPLOAD_FILE_LENGTH)
assertThat(it.checksum().checksumSHA1()).isEqualTo(expectedChecksum)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import software.amazon.awssdk.services.s3.model.ChecksumAlgorithm
import software.amazon.awssdk.services.s3.model.CommonPrefix
import software.amazon.awssdk.services.s3.model.EncodingType
import software.amazon.awssdk.services.s3.model.NoSuchBucketException
import software.amazon.awssdk.services.s3.model.ObjectStorageClass
import software.amazon.awssdk.services.s3.model.S3Object
import software.amazon.awssdk.utils.http.SdkHttpUtils

Expand Down Expand Up @@ -103,6 +104,14 @@ internal class ListObjectsIT : S3TestBase() {
Tuple(arrayListOf(ChecksumAlgorithm.SHA256)),
Tuple(arrayListOf(ChecksumAlgorithm.SHA256)),
)
// ListObjects returns the default storageClass "STANDARD", even though other APIs may not.
assertThat(it.contents())
.hasSize(2)
.extracting(S3Object::storageClass)
.containsOnly(
Tuple(ObjectStorageClass.STANDARD),
Tuple(ObjectStorageClass.STANDARD),
)
}
}

Expand Down Expand Up @@ -168,6 +177,8 @@ internal class ListObjectsIT : S3TestBase() {
listing.contents().also {
assertThat(it).hasSize(1)
assertThat(it[0].key()).isEqualTo(key)
// ListObjectsV2 returns the default storageClass "STANDARD", even though other APIs may not.
assertThat(it[0].storageClass()).isEqualTo(ObjectStorageClass.STANDARD)
}
}
}
Expand Down
Loading