From 6d7fbd2175ea441835ef08b1b7baec7c47803837 Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Sun, 1 Jun 2025 12:42:51 -0400 Subject: [PATCH 1/2] Clean up the purestorage config, and add explanatory comments. We're keeping beta on local disk for now. --- config/environments/beta.rb | 2 +- config/storage.yml | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/config/environments/beta.rb b/config/environments/beta.rb index a037b4159..c7f44040b 100644 --- a/config/environments/beta.rb +++ b/config/environments/beta.rb @@ -3,6 +3,6 @@ require_relative "production" Rails.application.configure do config.action_mailer.default_url_options = { host: "%{tenant}.37signals.works" } - # I couldn't figure out how to configure Pure to allow updates from Kevin's digital ocean instance. + # Let's keep beta on local disk. See https://github.com/basecamp/fizzy/pull/557 for context. config.active_storage.service = :local end diff --git a/config/storage.yml b/config/storage.yml index 1a6bf5c76..38ac38be7 100644 --- a/config/storage.yml +++ b/config/storage.yml @@ -6,10 +6,11 @@ local: service: Disk root: <%= Rails.root.join("storage", "tenants", Rails.env, "%{tenant}", "files") %> -<% purestorage_env_name = Rails.env.beta? ? "staging" : Rails.env %> +# We have "development", "staging", and "production" buckets configured. Note that we don't have a +# "beta" bucket. (As of 2025-06-01.) purestorage: service: S3 - bucket: fizzy-<%= purestorage_env_name %>-activestorage + bucket: fizzy-<%= Rails.env %>-activestorage endpoint: "https://storage.basecamp.com" ssl_verify_peer: false # FIXME: using self-signed cert internally force_path_style: true From a43db94a83e4fef2472e01bc2dbcbd1dec697388 Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Sun, 1 Jun 2025 12:45:24 -0400 Subject: [PATCH 2/2] Update production storage to write to the Pure blob store Modify the blob copying script to update the blob service name. This completes the migration and allows us to (at some point) clean up local disk and remove the "mirror" service from the config. --- config/environments/production.rb | 2 +- config/storage.yml | 1 + script/copy-blobs-to-pure.rb | 9 +++++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/config/environments/production.rb b/config/environments/production.rb index f960c0e81..73f7f6f1b 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -31,7 +31,7 @@ Rails.application.configure do # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX # Store uploaded files on the local file system (see config/storage.yml for options). - config.active_storage.service = :mirror + config.active_storage.service = :purestorage # Mount Action Cable outside main process or domain. # config.action_cable.mount_path = nil diff --git a/config/storage.yml b/config/storage.yml index 38ac38be7..2b062460e 100644 --- a/config/storage.yml +++ b/config/storage.yml @@ -20,6 +20,7 @@ purestorage: access_key_id: <%= Rails.application.credentials.dig(:active_storage, :purestorage_service, :access_key_id) %> secret_access_key: <%= Rails.application.credentials.dig(:active_storage, :purestorage_service, :secret_access_key) %> +# TODO: remove this after we update existing blobs' service names to purestorage. mirror: service: Mirror primary: purestorage diff --git a/script/copy-blobs-to-pure.rb b/script/copy-blobs-to-pure.rb index 01b51e66e..ae906d4ea 100755 --- a/script/copy-blobs-to-pure.rb +++ b/script/copy-blobs-to-pure.rb @@ -16,7 +16,10 @@ def migrate(source_service_name, target_service_name) target_service = ActiveStorage::Blob.services.fetch(target_service_name) ActiveStorage::Blob.find_each do |blob| - if target_service.exist?(blob.key) + if target_service.name.to_sym == blob.service_name.to_sym + report[:skipped] += 1 + putc "-" + elsif target_service.exist?(blob.key) report[:skipped] += 1 putc "S" else @@ -31,7 +34,9 @@ def migrate(source_service_name, target_service_name) putc "E" end end - # blob.update_attribute :service_name, target_service_name + + # Update the service name of the blob. + blob.update_column :service_name, target_service_name end puts