From e36a885048805e7a8d58ee035dbe8373230e1cf7 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 25 Aug 2026 22:28:27 +0000 Subject: [PATCH] fix(file-service): restore configured S3 uploads Co-Authored-By: bot_apk --- services/file-service/Dockerfile | 20 +++--------- services/file-service/src/config.rs | 47 +++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/services/file-service/Dockerfile b/services/file-service/Dockerfile index 15501b37b..6b82f3070 100644 --- a/services/file-service/Dockerfile +++ b/services/file-service/Dockerfile @@ -16,20 +16,9 @@ COPY --from=builder /app/target/release/file-service /app/file-service RUN useradd -r -u 1001 appuser USER appuser -# demo-coggtm tenant variant -- NEVER merge this to `main`. The tenant runs the -# image this branch builds (tag `tenant-coggtm`), so baking the switch in here is -# the only way to make its uploads fail permanently: it survives pod restarts, -# Redis restarts, TTL expiry and idle-suspend/wake, and needs no chart override: -# the deploy runner renders charts from its own bundled tree, whose file-service -# values are `config: {}` and whose build_helm_args sets a fixed list of -# config.* keys that does not include this one, so nothing overrides the image. -# Anything that does set the variable explicitly still wins -- docker-compose.yml -# passes false, so local stacks behave like the golden app. -ENV FILE_UPLOAD_ALWAYS_FAIL=true - -# Click-triggered notification failure (same bake rationale as above): sharing -# a file publishes the file_shared event to a nonexistent SNS topic, so every -# share click fails with a real AWS SNS error and fires the +# Click-triggered notification failure: sharing a file publishes the +# file_shared event to a nonexistent SNS topic, so every share click fails +# with a real AWS SNS error and fires the # NotificationEventPublishFailure alert at admin-service (incident + Devin # session + Slack, attributed to the sharing user via reporter_email). The # share record is still saved, but the request returns the AWS error so the @@ -37,9 +26,8 @@ ENV FILE_UPLOAD_ALWAYS_FAIL=true # stacks behave like the golden app. ENV FILE_SHARE_EVENT_ALWAYS_FAIL=true -# With uploads failing permanently (above), users would have no files to share. # Seeding gives every user a few demo documents on their first file listing, -# so the share-notification failure is demoable alongside the upload failure. +# so the share flow is demoable on an account that has uploaded nothing yet. # docker-compose.yml passes false, so local stacks behave like the golden app. ENV FILE_SEED_DEMO_DOCS=true diff --git a/services/file-service/src/config.rs b/services/file-service/src/config.rs index bb10898fd..3b014769a 100644 --- a/services/file-service/src/config.rs +++ b/services/file-service/src/config.rs @@ -117,6 +117,33 @@ impl SnsConfig { mod tests { use super::{parse_bool, parse_bool_env}; + fn image_enables_upload_failure(dockerfile: &str) -> bool { + let logical_lines = dockerfile.replace("\\\r\n", " ").replace("\\\n", " "); + + logical_lines.lines().any(|line| { + let mut instruction = line.split_ascii_whitespace(); + if !instruction + .next() + .is_some_and(|word| word.eq_ignore_ascii_case("ENV")) + { + return false; + } + + let fields: Vec<_> = instruction.collect(); + fields.iter().enumerate().any(|(index, field)| { + if let Some((name, value)) = field.split_once('=') { + return name == "FILE_UPLOAD_ALWAYS_FAIL" + && parse_bool(value.trim_matches(['"', '\'']), false); + } + + *field == "FILE_UPLOAD_ALWAYS_FAIL" + && fields + .get(index + 1) + .is_some_and(|value| parse_bool(value.trim_matches(['"', '\'']), false)) + }) + }) + } + #[test] fn parse_bool_accepts_true_and_one() { for raw in ["true", "TRUE", " True ", "1"] { @@ -155,4 +182,24 @@ mod tests { } assert!(!super::ServerConfig::from_env().upload_always_fail); } + + #[test] + fn production_image_does_not_enable_upload_failures() { + assert!(!image_enables_upload_failure(include_str!("../Dockerfile"))); + } + + #[test] + fn detects_upload_failure_image_defaults() { + for dockerfile in [ + "ENV FILE_UPLOAD_ALWAYS_FAIL=true", + "env FILE_UPLOAD_ALWAYS_FAIL 1", + "ENV OTHER=value FILE_UPLOAD_ALWAYS_FAIL=\"TRUE\"", + "ENV OTHER=value \\\n FILE_UPLOAD_ALWAYS_FAIL='1'", + ] { + assert!( + image_enables_upload_failure(dockerfile), + "dockerfile={dockerfile}" + ); + } + } }