fix(storage): preserve deployment compatibility

Keep Helm region wiring opt-in, align provider probes on the shared S3 variables, and document the bundled Compose storage contract accurately.

Co-authored-by: Kalvin Chau <kalvin@block.xyz>
Signed-off-by: Kalvin Chau <kalvin@block.xyz>
This commit is contained in:
npub122y0pqkertljmedu303rl0aqrj3w8pvu43t6jxm6875lzg6f2pwqegc3xc
2026-07-28 18:10:03 -07:00
parent 3868d35dc5
commit cf3b54322a
10 changed files with 56 additions and 98 deletions

View File

@@ -1583,34 +1583,15 @@ mod tests {
}
fn live_store() -> GitStore {
let endpoint = std::env::var("BUZZ_GIT_S3_ENDPOINT")
.or_else(|_| std::env::var("BUZZ_S3_ENDPOINT"))
.unwrap_or_else(|_| "http://localhost:9000".into());
let access_key = std::env::var("BUZZ_GIT_S3_ACCESS_KEY")
.or_else(|_| std::env::var("BUZZ_S3_ACCESS_KEY"))
.unwrap_or_else(|_| "buzz_dev".into());
let secret_key = std::env::var("BUZZ_GIT_S3_SECRET_KEY")
.or_else(|_| std::env::var("BUZZ_S3_SECRET_KEY"))
.unwrap_or_else(|_| "buzz_dev_secret".into());
let bucket = std::env::var("BUZZ_GIT_S3_BUCKET")
.or_else(|_| std::env::var("BUZZ_S3_BUCKET"))
.unwrap_or_else(|_| "buzz-media".into());
let region = std::env::var("BUZZ_GIT_S3_REGION")
.or_else(|_| std::env::var("BUZZ_S3_REGION"))
.unwrap_or_else(|_| "us-east-1".into());
let addressing_style = std::env::var("BUZZ_S3_ADDRESSING_STYLE")
.unwrap_or_else(|_| "path".into())
.parse()
.expect("BUZZ_S3_ADDRESSING_STYLE must be path or virtual");
GitStore::new(
&endpoint,
&access_key,
&secret_key,
&bucket,
&region,
addressing_style,
"http://localhost:9000",
"buzz_dev",
"buzz_dev_secret",
"buzz-media",
"us-east-1",
buzz_media::config::S3AddressingStyle::Path,
)
.expect("connect minio")
.expect("connect local MinIO")
}
fn tenant() -> TenantContext {

View File

@@ -588,34 +588,15 @@ mod tests {
}
fn store() -> GitStore {
let endpoint = std::env::var("BUZZ_GIT_S3_ENDPOINT")
.or_else(|_| std::env::var("BUZZ_S3_ENDPOINT"))
.unwrap_or_else(|_| "http://localhost:9000".into());
let access_key = std::env::var("BUZZ_GIT_S3_ACCESS_KEY")
.or_else(|_| std::env::var("BUZZ_S3_ACCESS_KEY"))
.unwrap_or_else(|_| "buzz_dev".into());
let secret_key = std::env::var("BUZZ_GIT_S3_SECRET_KEY")
.or_else(|_| std::env::var("BUZZ_S3_SECRET_KEY"))
.unwrap_or_else(|_| "buzz_dev_secret".into());
let bucket = std::env::var("BUZZ_GIT_S3_BUCKET")
.or_else(|_| std::env::var("BUZZ_S3_BUCKET"))
.unwrap_or_else(|_| "buzz-git".into());
let region = std::env::var("BUZZ_GIT_S3_REGION")
.or_else(|_| std::env::var("BUZZ_S3_REGION"))
.unwrap_or_else(|_| "us-east-1".into());
let addressing_style = std::env::var("BUZZ_S3_ADDRESSING_STYLE")
.unwrap_or_else(|_| "path".into())
.parse()
.expect("BUZZ_S3_ADDRESSING_STYLE must be path or virtual");
GitStore::new(
&endpoint,
&access_key,
&secret_key,
&bucket,
&region,
addressing_style,
"http://localhost:9000",
"buzz_dev",
"buzz_dev_secret",
"buzz-git",
"us-east-1",
buzz_media::config::S3AddressingStyle::Path,
)
.expect("connect S3-compatible storage")
.expect("connect local MinIO")
}
/// Build a tiny on-disk repo, return (pack bytes, head_oid).

View File

@@ -1033,21 +1033,16 @@ mod probe {
}
fn store() -> GitStore {
let endpoint = std::env::var("BUZZ_GIT_S3_ENDPOINT")
.or_else(|_| std::env::var("BUZZ_S3_ENDPOINT"))
.unwrap_or_else(|_| "http://localhost:9000".into());
let access_key = std::env::var("BUZZ_GIT_S3_ACCESS_KEY")
.or_else(|_| std::env::var("BUZZ_S3_ACCESS_KEY"))
.unwrap_or_else(|_| "buzz_dev".into());
let secret_key = std::env::var("BUZZ_GIT_S3_SECRET_KEY")
.or_else(|_| std::env::var("BUZZ_S3_SECRET_KEY"))
.unwrap_or_else(|_| "buzz_dev_secret".into());
let bucket = std::env::var("BUZZ_GIT_S3_BUCKET")
.or_else(|_| std::env::var("BUZZ_S3_BUCKET"))
.unwrap_or_else(|_| "buzz-git".into());
let region = std::env::var("BUZZ_GIT_S3_REGION")
.or_else(|_| std::env::var("BUZZ_S3_REGION"))
.unwrap_or_else(|_| "us-east-1".into());
// This is the dedicated backend conformance path, so all connection and
// signing inputs are overridable for a real provider such as Railway.
// The hydrate/CAS live tests use explicit local MinIO fixtures instead.
let endpoint =
std::env::var("BUZZ_S3_ENDPOINT").unwrap_or_else(|_| "http://localhost:9000".into());
let access_key = std::env::var("BUZZ_S3_ACCESS_KEY").unwrap_or_else(|_| "buzz_dev".into());
let secret_key =
std::env::var("BUZZ_S3_SECRET_KEY").unwrap_or_else(|_| "buzz_dev_secret".into());
let bucket = std::env::var("BUZZ_S3_BUCKET").unwrap_or_else(|_| "buzz-git".into());
let region = std::env::var("BUZZ_S3_REGION").unwrap_or_else(|_| "us-east-1".into());
let addressing_style = std::env::var("BUZZ_S3_ADDRESSING_STYLE")
.unwrap_or_else(|_| "path".into())
.parse()

View File

@@ -138,21 +138,20 @@ impl GitS3Probe {
}
fn from_env() -> Self {
let endpoint = std::env::var("BUZZ_GIT_S3_ENDPOINT")
.or_else(|_| std::env::var("BUZZ_S3_ENDPOINT"))
// These E2E assertions inspect the relay's backing bucket directly, so
// they must receive the same provider connection and URL style as the
// relay. Unit/live MinIO probes in buzz-relay keep explicit local
// fixtures and do not need provider overrides.
let endpoint = std::env::var("BUZZ_S3_ENDPOINT")
.unwrap_or_else(|_| "http://localhost:9000".to_string());
let access_key = std::env::var("BUZZ_GIT_S3_ACCESS_KEY")
.or_else(|_| std::env::var("BUZZ_S3_ACCESS_KEY"))
.unwrap_or_else(|_| "buzz_dev".to_string());
let secret_key = std::env::var("BUZZ_GIT_S3_SECRET_KEY")
.or_else(|_| std::env::var("BUZZ_S3_SECRET_KEY"))
.unwrap_or_else(|_| "buzz_dev_secret".to_string());
let bucket_name = std::env::var("BUZZ_GIT_S3_BUCKET")
.or_else(|_| std::env::var("BUZZ_S3_BUCKET"))
.unwrap_or_else(|_| "buzz-media".to_string());
let region_name = std::env::var("BUZZ_GIT_S3_REGION")
.or_else(|_| std::env::var("BUZZ_S3_REGION"))
.unwrap_or_else(|_| "us-east-1".to_string());
let access_key =
std::env::var("BUZZ_S3_ACCESS_KEY").unwrap_or_else(|_| "buzz_dev".to_string());
let secret_key =
std::env::var("BUZZ_S3_SECRET_KEY").unwrap_or_else(|_| "buzz_dev_secret".to_string());
let bucket_name =
std::env::var("BUZZ_S3_BUCKET").unwrap_or_else(|_| "buzz-media".to_string());
let region_name =
std::env::var("BUZZ_S3_REGION").unwrap_or_else(|_| "us-east-1".to_string());
let addressing_style = std::env::var("BUZZ_S3_ADDRESSING_STYLE")
.unwrap_or_else(|_| "path".to_string())
.parse::<S3AddressingStyle>()

View File

@@ -61,11 +61,13 @@ Buzz uses one URL style for both media and Git/CAS object-store requests:
| `path` (default) | `https://endpoint/bucket/key` | Bundled MinIO and endpoints whose DNS does not resolve bucket subdomains |
| `virtual` | `https://bucket.endpoint/key` | AWS-style providers and new Railway Storage Buckets |
The chart renders `s3.region` and `s3.addressingStyle` as `BUZZ_S3_REGION`
and `BUZZ_S3_ADDRESSING_STYLE`. Only `path` and `virtual` addressing styles are
accepted; invalid values fail chart rendering and relay startup. The bundled
MinIO quickstart deliberately keeps `path` because its Service DNS resolves one
endpoint hostname, not arbitrary `<bucket>.<service>` names.
The chart always renders `s3.addressingStyle` as
`BUZZ_S3_ADDRESSING_STYLE`. It renders `s3.region` as `BUZZ_S3_REGION` only
when explicitly set, preserving the relay's existing `AWS_REGION` fallback for
upgrades. Only `path` and `virtual` addressing styles are accepted; invalid
values fail chart rendering and relay startup. The bundled MinIO quickstart
deliberately keeps `path` because its Service DNS resolves one endpoint
hostname, not arbitrary `<bucket>.<service>` names.
For a Railway Storage Bucket, map its variables to chart values in the service
or generated Helm configuration:

View File

@@ -170,7 +170,9 @@ spec:
- { name: BUZZ_S3_ENDPOINT, value: {{ $s3Endpoint | quote }} }
{{- end }}
- { name: BUZZ_S3_BUCKET, value: {{ .Values.s3.bucket | quote }} }
{{- if .Values.s3.region }}
- { name: BUZZ_S3_REGION, value: {{ .Values.s3.region | quote }} }
{{- end }}
- { name: BUZZ_S3_ADDRESSING_STYLE, value: {{ .Values.s3.addressingStyle | quote }} }
# ── Secrets (from chart-managed or existing) ─────────────

View File

@@ -30,11 +30,10 @@ tests:
path: kind
value: Service
template: templates/service.yaml
- contains:
- notContains:
path: spec.template.spec.containers[0].env
content:
name: BUZZ_S3_REGION
value: "us-east-1"
template: templates/deployment.yaml
- contains:
path: spec.template.spec.containers[0].env

View File

@@ -200,8 +200,7 @@
"bucket": { "type": "string", "minLength": 1 },
"region": {
"type": "string",
"minLength": 1,
"description": "S3 region used for SigV4 signing. Defaults to us-east-1 for bundled MinIO compatibility."
"description": "Optional S3 region used for SigV4 signing. When empty, BUZZ_S3_REGION is omitted so the relay can use AWS_REGION or its own default."
},
"addressingStyle": {
"type": "string",

View File

@@ -338,9 +338,9 @@ externalRedis:
s3:
endpoint: ""
bucket: "buzz-media"
# SigV4 signing region. Keep us-east-1 for bundled MinIO; set this to the
# provider's credential value for managed S3 (for example Railway's REGION).
region: "us-east-1"
# Optional SigV4 signing region. Leave empty to preserve the relay's
# AWS_REGION fallback; set the provider's credential value when needed.
region: ""
# path: https://endpoint/bucket/key (bundled MinIO-compatible default)
# virtual: https://bucket.endpoint/key (standard S3; required by new Railway buckets)
addressingStyle: path

View File

@@ -38,11 +38,11 @@ keypair.
migrations.
- The stack uses Postgres, Redis, MinIO, and a git data volume because
those are real Buzz dependencies today. Minimal mode can simplify this later.
- Bundled MinIO uses `BUZZ_S3_ADDRESSING_STYLE=path`: Docker DNS resolves
`minio`, not `<bucket>.minio`. To replace bundled MinIO with an external
provider, override the endpoint, bucket, region, and addressing style as a
matched set; providers such as new Railway Storage Buckets require `virtual`.
Invalid styles fail relay startup.
- The bundled Compose stack fixes the relay endpoint to `http://minio:9000` and
`BUZZ_S3_ADDRESSING_STYLE=path`: Docker DNS resolves `minio`, not
`<bucket>.minio`. It is not configurable for an external S3 provider through
`.env`; use the Helm chart or a custom Compose configuration for providers
such as new Railway Storage Buckets that require `virtual` addressing.
Run `./run.sh backup-hint` for the backup checklist.