chore: move to rustfs for local dev - #1427
TylerHillery wants to merge 7 commits into
Conversation
Coverage Report for CI Build 35874167664Warning Build has drifted: This PR's base is out of sync with its target branch, so coverage data may include unrelated changes. Coverage increased (+0.09%) to 83.42%Details
Uncovered ChangesNo uncovered changes found. Coverage Regressions34 previously-covered lines in 6 files lost coverage.
Coverage Stats💛 - Coveralls |
| @@ -371,7 +367,7 @@ export class S3Backend implements StorageBackendAdapter { | |||
| const copyMetadata = options?.copyMetadata ?? !metadata | |||
| const command = new CopyObjectCommand({ | |||
| Bucket: bucket, | |||
| CopySource: encodeCopySource(bucket, source, version), | |||
| CopySource: encodeURIComponent(`${bucket}/${withOptionalVersion(source, version)}`), | |||
| Key: withOptionalVersion(destination, destinationVersion), | |||
| CopySourceIfMatch: conditions?.ifMatch, | |||
| CopySourceIfNoneMatch: conditions?.ifNoneMatch, | |||
| @@ -556,7 +552,7 @@ export class S3Backend implements StorageBackendAdapter { | |||
| const data = await this.client.send(command) | |||
| return { | |||
| cacheControl: data.CacheControl || 'no-cache', | |||
| mimetype: data.ContentType || 'application/octet-stream', | |||
| mimetype: data.ContentType || 'binary/octet-stream', | |||
| eTag: data.ETag || '', | |||
There was a problem hiding this comment.
The default fallback value for S3 is binary/octet-stream. You can verify this against a real S3 bucket:
echo "hello" > /tmp/s3-src.txt
aws s3api put-object --bucket "$BUCKET" --key "$KEY_SRC" --body /tmp/s3-src.txt
aws s3api head-object --bucket "$BUCKET" --key "$KEY_SRC"
aws s3api copy-object --bucket "$BUCKET" --key "$KEY_DST" \
--copy-source "$BUCKET/$KEY_SRC" \
--metadata-directive REPLACE --cache-control "max-age=2009"
aws s3api head-object --bucket "$BUCKET" --key "$KEY_DST"Both head-object calls return binary/octet-stream
This fallback only fires when the backend returns no ContentType at all. MinIO and real AWS S3 always set one, so we never hit our own fallback there but RustFS has a bug where CopyObject with MetadataDirective=REPLACE doesn't set a content type when none is passed through, which is what surfaced this. I'm working on an upstream fix to RustFS, but the fallback here should be updated, since it's correct behavior.
There was a problem hiding this comment.
here is the upstream fix: rustfs/rustfs#8073
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Unresolved access-policy, startup-order, and MIME-fallback issues remain.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 1
Open (3)
What changed in this PR
Replaces MinIO with RustFS for local development, updating infrastructure, endpoints, tests, documentation, and S3 MIME handling.
Changes:
- Replaces local MinIO services and bootstrap configuration with RustFS.
- Updates tests, environment samples, and acceptance documentation.
- Adjusts S3 content-type fallback behavior.
| File | Summary |
|---|---|
src/test/s3-locker.test.ts |
Updates provider references in comments. |
src/test/iceberg.test.ts |
Renames the local S3 client. |
src/storage/backend/s3/adapter.ts |
Changes MIME fallbacks; retain application/octet-stream. |
src/storage/backend/s3/adapter.test.ts |
Updates endpoints and MIME expectations. |
docker-compose.yml |
Uses RustFS for single-tenant development. |
docker-compose-multi-tenant.yml |
Uses RustFS; wait for the healthy service before setup. |
acceptance/README.md |
Updates RustFS acceptance instructions. |
acceptance/API_COVERAGE.md |
Updates backend coverage terminology. |
.env.sample |
Sets the RustFS private asset endpoint. |
.docker/docker-compose-infra.yml |
Defines RustFS and bucket setup; keep anonymous warehouse access read-only. |
.docker/docker-compose-infra-multigres-override.yml |
Updates infrastructure documentation. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| for b in supa-storage-bucket warehouse--table-s3 supa-storage-profiles; do | ||
| curl -fsS --aws-sigv4 'aws:amz:us-east-1:s3' -u supa-storage:secret1234 -X PUT http://rustfs:9000/\$$b; | ||
| done; | ||
| curl -fsS --aws-sigv4 'aws:amz:us-east-1:s3' -u supa-storage:secret1234 -X PUT 'http://rustfs:9000/warehouse--table-s3?policy' -d '{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":[\"s3:GetObject\",\"s3:PutObject\",\"s3:DeleteObject\",\"s3:ListBucket\"],\"Resource\":[\"arn:aws:s3:::warehouse--table-s3\",\"arn:aws:s3:::warehouse--table-s3/*\"]}]}'; |
| size: data.size, | ||
| cacheControl: cacheControl || 'no-cache', | ||
| mimetype: contentType || 'application/octet-stream', | ||
| mimetype: contentType || 'binary/octet-stream', |
There was a problem hiding this comment.
seems like upload case is missing
There was a problem hiding this comment.
and it also means we need a small test becase there is no test update which is missing


What kind of change does this PR introduce?
Chore to replace minio with rustfs for local development.
What is the current behavior?
Currently we use minio
What is the new behavior?
Now we use rustfs