From 214e1fd402cf6d35e3e3ecc3295ef90f79c68710 Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Fri, 17 Oct 2025 10:08:06 -0400 Subject: [PATCH 1/7] Script to configure staging load balancers ref: https://3.basecamp.com/2914079/buckets/37331921/todos/9180260061 --- script/configure-lb-staging.sh | 69 ++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100755 script/configure-lb-staging.sh diff --git a/script/configure-lb-staging.sh b/script/configure-lb-staging.sh new file mode 100755 index 000000000..17ae50494 --- /dev/null +++ b/script/configure-lb-staging.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash + +set -e + +# fizzy-staging-lb-01.sc-chi-int.37signals.com +# +# Service Host Path Target State TLS +# fizzy fizzy.37signals-staging.com / fizzy-staging-app-01.sc-chi-int.37signals.com,fizzy-staging-app-02.sc-chi-int.37signals.com running yes +# fizzy-admin fizzy.37signals-staging.com /admin fizzy-staging-app-01.sc-chi-int.37signals.com running yes +ssh app@fizzy-staging-lb-01.sc-chi-int.37signals.com \ + docker exec fizzy-load-balancer \ + kamal-proxy deploy fizzy \ + --tls \ + --host=fizzy.37signals-staging.com \ + --target=fizzy-staging-app-01.sc-chi-int.37signals.com \ + --read-target=fizzy-staging-app-02.sc-chi-int.37signals.com \ + --tls-acme-cache-path=/certificates + +ssh app@fizzy-staging-lb-01.sc-chi-int.37signals.com \ + docker exec fizzy-load-balancer \ + kamal-proxy deploy fizzy-admin \ + --host=fizzy.37signals-staging.com \ + --path-prefix /admin \ + --strip-path-prefix=false \ + --target=fizzy-staging-app-01.sc-chi-int.37signals.com + +# fizzy-staging-lb-101.df-iad-int.37signals.com +# +# Service Host Path Target State TLS +# fizzy fizzy.37signals-staging.com / fizzy-staging-app-01.sc-chi-int.37signals.com,fizzy-staging-app-102.df-iad-int.37signals.com running yes +# fizzy-admin fizzy.37signals-staging.com /admin fizzy-staging-app-01.sc-chi-int.37signals.com running yes +ssh app@fizzy-staging-lb-101.df-iad-int.37signals.com \ + docker exec fizzy-load-balancer \ + kamal-proxy deploy fizzy \ + --tls \ + --host=fizzy.37signals-staging.com \ + --target=fizzy-staging-app-01.sc-chi-int.37signals.com \ + --read-target=fizzy-staging-app-102.df-iad-int.37signals.com \ + --tls-acme-cache-path=/certificates + +ssh app@fizzy-staging-lb-101.df-iad-int.37signals.com \ + docker exec fizzy-load-balancer \ + kamal-proxy deploy fizzy-admin \ + --host=fizzy.37signals-staging.com \ + --path-prefix /admin \ + --strip-path-prefix=false \ + --target=fizzy-staging-app-01.sc-chi-int.37signals.com + +# fizzy-staging-lb-401.df-ams-int.37signals.com +# +# Service Host Path Target State TLS +# fizzy fizzy.37signals-staging.com / fizzy-staging-app-01.sc-chi-int.37signals.com,fizzy-staging-app-402.df-ams-int.37signals.com running yes +# fizzy-admin fizzy.37signals-staging.com /admin fizzy-staging-app-01.sc-chi-int.37signals.com running yes +ssh app@fizzy-staging-lb-401.df-ams-int.37signals.com \ + docker exec fizzy-load-balancer \ + kamal-proxy deploy fizzy \ + --tls \ + --host=fizzy.37signals-staging.com \ + --target=fizzy-staging-app-01.sc-chi-int.37signals.com \ + --read-target=fizzy-staging-app-402.df-ams-int.37signals.com \ + --tls-acme-cache-path=/certificates + +ssh app@fizzy-staging-lb-401.df-ams-int.37signals.com \ + docker exec fizzy-load-balancer \ + kamal-proxy deploy fizzy-admin \ + --host=fizzy.37signals-staging.com \ + --path-prefix /admin \ + --strip-path-prefix=false \ + --target=fizzy-staging-app-01.sc-chi-int.37signals.com From 1b5f2b72d72654d6fcf50b2e9666ded0c8de1c69 Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Tue, 21 Oct 2025 13:56:11 -0700 Subject: [PATCH 2/7] bin/setup detects when it needs to set up seeds --- bin/setup | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/bin/setup b/bin/setup index f2a2d9737..153fd34de 100755 --- a/bin/setup +++ b/bin/setup @@ -34,6 +34,15 @@ step() { return $exit_code } +needs_seeding() { + has_tenant=$(bin/rails runner "pp ApplicationRecord.tenants.any? { ApplicationRecord.with_tenant(_1) { Account.sole } }" 2>/dev/null) + if [ "$has_tenant" = "true" ] ; then + return 1 + else + return 0 + fi +} + echo gum style --foreground 153 " ˚ ∘ ∘ ˚ " gum style --foreground 111 --bold " ∘˚˳°∘° 𝒻𝒾𝓏𝓏𝓎 °∘°˳˚∘ " @@ -60,6 +69,8 @@ fi if [[ $* == *--reset* ]]; then step "Resetting the database" rails db:reset +elif needs_seeding; then + step "Setting up the database" rails db:reset else step "Preparing the database" rails db:prepare fi From 94c74255b7fd00caa07f0608ed53a23ab178a386 Mon Sep 17 00:00:00 2001 From: Jason Zimdars Date: Tue, 21 Oct 2025 14:10:37 -0700 Subject: [PATCH 3/7] Menu button always has the product name - Indicate the current account in the menu --- app/assets/stylesheets/popup.css | 12 +++--------- app/helpers/filters_helper.rb | 5 +++-- app/views/filters/menu/_accounts.html.erb | 4 ++-- app/views/filters/menu/_button.html.erb | 2 +- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/app/assets/stylesheets/popup.css b/app/assets/stylesheets/popup.css index 11c394ff8..b3b8172be 100644 --- a/app/assets/stylesheets/popup.css +++ b/app/assets/stylesheets/popup.css @@ -138,18 +138,12 @@ padding: var(--inline-space-half) var(--popup-item-padding-inline); text-align: start; - &:has(input:checked) { - --btn-color: var(--color-ink); + .icon.checked { + display: none; - .icon.checked { + .popup__item--current & { display: block; } - - @media (any-hover: hover) { - &:where(:not(:active):hover) { - --btn-background: var(--color-selected); - } - } } } diff --git a/app/helpers/filters_helper.rb b/app/helpers/filters_helper.rb index c93eb9735..1f89eb390 100644 --- a/app/helpers/filters_helper.rb +++ b/app/helpers/filters_helper.rb @@ -15,12 +15,13 @@ module FiltersHelper user_filtering.selected_collection_titles.collect { tag.strong it }.to_sentence.html_safe end - def filter_place_menu_item(path, label, icon, new_window: false) + def filter_place_menu_item(path, label, icon, new_window: false, current: false) link_to_params = new_window ? { target: "_blank" } : {} - tag.li class: "popup__item", id: "filter-place-#{label.parameterize}", data: { filter_target: "item", navigable_list_target: "item" } do + tag.li class: [ "popup__item", { "popup__item--current": current } ], id: "filter-place-#{label.parameterize}", data: { filter_target: "item", navigable_list_target: "item" } do concat icon_tag(icon, class: "popup__icon") concat(link_to(path, link_to_params.merge(class: "popup__btn btn")) do concat tag.span(label, class: "overflow-ellipsis") + concat icon_tag("check", class: "checked flex-item-justify-end", "aria-hidden": true) end) end end diff --git a/app/views/filters/menu/_accounts.html.erb b/app/views/filters/menu/_accounts.html.erb index 8d182ed3e..a7532cea8 100644 --- a/app/views/filters/menu/_accounts.html.erb +++ b/app/views/filters/menu/_accounts.html.erb @@ -1,5 +1,5 @@ <%= collapsible_nav_section "Accounts" do %> - <% Current.user.identity.memberships.where.not(user_tenant: Current.user.tenant).each do |membership| %> - <%= filter_place_menu_item root_url(script_name: "/#{membership.user_tenant}"), "#{membership.account_name}", "marker", new_window: true %> + <% Current.user.identity.memberships.each do |membership| %> + <%= filter_place_menu_item root_url(script_name: "/#{membership.user_tenant}"), "#{membership.account_name}", "marker", new_window: true, current: membership.user_tenant == Current.user.tenant %> <% end %> <% end %> diff --git a/app/views/filters/menu/_button.html.erb b/app/views/filters/menu/_button.html.erb index 5c8dd0bad..625b68b47 100644 --- a/app/views/filters/menu/_button.html.erb +++ b/app/views/filters/menu/_button.html.erb @@ -3,5 +3,5 @@ action: "click->dialog#open:stop keydown.j@document->hotkey#click keydown.meta+j@document->hotkey#click keydown.ctrl+j@document->hotkey#click", controller: "hotkey" } do %> <%= image_tag "fizzy-logo.png" %> - <%= Current.user.identity.memberships.many? ? Account.sole.name : "Fizzy" %> + Fizzy <% end %> From 1c5d30213260b7c2dafdb217ad2b135a0500363c Mon Sep 17 00:00:00 2001 From: Jason Zimdars Date: Tue, 21 Oct 2025 14:17:24 -0700 Subject: [PATCH 4/7] Indicate account name in settings --- app/views/account/settings/show.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/account/settings/show.html.erb b/app/views/account/settings/show.html.erb index 732c49abc..e0b8cc14a 100644 --- a/app/views/account/settings/show.html.erb +++ b/app/views/account/settings/show.html.erb @@ -1,4 +1,4 @@ -<% @page_title = "Account Settings" %> +<% @page_title = "Account Settings for #{Account.sole.name}" %> <% content_for :header do %> <%= render "filters/menu" %> From 8e64ef741f99353f458322aca90688cab366c3bd Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Mon, 20 Oct 2025 17:12:10 -0700 Subject: [PATCH 5/7] dev: Fix the default tenant to be the correct Honcho id --- config/initializers/tenanting/default_tenant.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/initializers/tenanting/default_tenant.rb b/config/initializers/tenanting/default_tenant.rb index 096c5721e..2066f61d6 100644 --- a/config/initializers/tenanting/default_tenant.rb +++ b/config/initializers/tenanting/default_tenant.rb @@ -1,6 +1,6 @@ Rails.application.configure do # In test environment, default tenant is set in test_helper.rb if Rails.env.development? - config.active_record_tenanted.default_tenant = "175932900" # Honcho + config.active_record_tenanted.default_tenant = "686465299" # Honcho end end From b4f98e35a7288b01d0a09a83faedea9c85a8ee47 Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Wed, 22 Oct 2025 08:36:46 -0700 Subject: [PATCH 6/7] Fix the default tenant in migration-audit also skip the gum installation check (it's installed in bin/setup) and explicitly use `--` to disambiguate file names. --- bin/migration-audit | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/bin/migration-audit b/bin/migration-audit index 429bb0374..20a96ca7c 100755 --- a/bin/migration-audit +++ b/bin/migration-audit @@ -6,21 +6,6 @@ set -eo pipefail app_root="$(cd "$(dirname "$0")/.."; pwd)" export PATH="$app_root/bin:$PATH" -# Install gum if needed -if ! command -v gum &> /dev/null; then - echo - echo "▸ Installing gum" - if command -v pacman &> /dev/null; then - sudo pacman -S --noconfirm gum - elif command -v brew &> /dev/null; then - brew install gum - else - echo "Please install gum: https://github.com/charmbracelet/gum" - exit 1 - fi - echo -fi - step() { local spin=false if [[ $1 == "--spin" ]] ; then @@ -62,12 +47,12 @@ echo step "Deleting schema files" rm -f db/schema.rb db/schema_cache.yml -step "Deleting tenant directory" rm -rf storage/tenants/development/175932900 +step "Deleting tenant directory" rm -rf storage/tenants/development/686465299 step --spin "Migrating..." "Regenerating schema files" bin/rails db:migrate # Check if the schema files have any git changes -if git diff --quiet db/schema.rb db/schema_cache.yml; then +if git diff --quiet -- db/schema.rb db/schema_cache.yml; then gum style --foreground 46 "✓ Schema files are in sync with migrations" exit 0 else @@ -75,6 +60,6 @@ else gum style --foreground 196 --bold "✗ Schema files are out of sync with migrations!" echo gum style --foreground 135 --bold "Differences:" - git --no-pager diff db/schema.rb db/schema_cache.yml + git --no-pager diff -- db/schema.rb db/schema_cache.yml exit 1 fi From 4017da746ceac2c31e3668f1ca53743d879bbbdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20=C3=81lvarez?= Date: Wed, 22 Oct 2025 10:46:41 -0700 Subject: [PATCH 7/7] Add script for configuring production load balancers --- script/configure-lb-production.sh | 71 +++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100755 script/configure-lb-production.sh diff --git a/script/configure-lb-production.sh b/script/configure-lb-production.sh new file mode 100755 index 000000000..2430df644 --- /dev/null +++ b/script/configure-lb-production.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash + +set -e + +# fizzy-lb-101.df-iad-int.37signals.com +# +# Service Host Path Target State TLS +# fizzy fizzy.37signals.com / fizzy-app-101.df-iad-int.37signals.com,fizzy-app-02.sc-chi-int.37signals.com running yes +# fizzy-admin fizzy.37signals.com /admin fizzy-app-101.df-iad-int.37signals.com running yes +ssh app@fizzy-lb-101.df-iad-int.37signals.com \ + docker exec fizzy-load-balancer \ + kamal-proxy deploy fizzy \ + --tls \ + --host=fizzy.37signals.com \ + --target=fizzy-app-101.df-iad-int.37signals.com \ + --read-target=fizzy-app-102.df-iad-int.37signals.com \ + --tls-acme-cache-path=/certificates + +ssh app@fizzy-lb-101.df-iad-int.37signals.com \ + docker exec fizzy-load-balancer \ + kamal-proxy deploy fizzy-admin \ + --host=fizzy.37signals.com \ + --path-prefix /admin \ + --strip-path-prefix=false \ + --target=fizzy-app-101.df-iad-int.37signals.com + + +# fizzy-lb-01.sc-chi-int.37signals.com +# +# Service Host Path Target State TLS +# fizzy fizzy.37signals.com / fizzy-app-101.df-iad-int.37signals.com,fizzy-app-102.df-iad-int.37signals.com running yes +# fizzy-admin fizzy.37signals.com /admin fizzy-app-101.df-iad-int.37signals.com running yes +ssh app@fizzy-lb-01.sc-chi-int.37signals.com \ + docker exec fizzy-load-balancer \ + kamal-proxy deploy fizzy \ + --tls \ + --host=fizzy.37signals.com \ + --target=fizzy-app-101.df-iad-int.37signals.com \ + --read-target=fizzy-app-02.sc-chi-int.37signals.com \ + --tls-acme-cache-path=/certificates + +ssh app@fizzy-lb-01.sc-chi-int.37signals.com \ + docker exec fizzy-load-balancer \ + kamal-proxy deploy fizzy-admin \ + --host=fizzy.37signals.com \ + --path-prefix /admin \ + --strip-path-prefix=false \ + --target=fizzy-app-101.df-iad-int.37signals.com + + +# fizzy-lb-401.df-ams-int.37signals.com +# +# Service Host Path Target State TLS +# fizzy fizzy.37signals.com / fizzy-app-101.df-iad-int.37signals.com,fizzy-app-402.df-ams-int.37signals.com running yes +# fizzy-admin fizzy.37signals.com /admin fizzy-app-101.df-iad-int.37signals.com running yes +ssh app@fizzy-lb-401.df-ams-int.37signals.com \ + docker exec fizzy-load-balancer \ + kamal-proxy deploy fizzy \ + --tls \ + --host=fizzy.37signals.com \ + --target=fizzy-app-101.df-iad-int.37signals.com \ + --read-target=fizzy-app-402.df-ams-int.37signals.com \ + --tls-acme-cache-path=/certificates + +ssh app@fizzy-lb-401.df-ams-int.37signals.com \ + docker exec fizzy-load-balancer \ + kamal-proxy deploy fizzy-admin \ + --host=fizzy.37signals.com \ + --path-prefix /admin \ + --strip-path-prefix=false \ + --target=fizzy-app-101.df-iad-int.37signals.com