Introduce a staging environment
ref: https://3.basecamp.com/2914079/buckets/21350690/card_tables/cards/8708868711
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
SECRETS=$(kamal secrets fetch --adapter 1password --account basecamp --from Deploy/Fizzy Deployments/BASECAMP_REGISTRY_PASSWORD Staging/RAILS_MASTER_KEY)
|
||||
|
||||
GITHUB_TOKEN=$(gh config get -h github.com oauth_token)
|
||||
BASECAMP_REGISTRY_PASSWORD=$(kamal secrets extract BASECAMP_REGISTRY_PASSWORD $SECRETS)
|
||||
RAILS_MASTER_KEY=$(kamal secrets extract RAILS_MASTER_KEY $SECRETS)
|
||||
@@ -45,29 +45,40 @@ For testing OpenAI API requests, we use [VCR](https://github.com/vcr/vcr). If yo
|
||||
that you can get from 1Password in "Fizzy - test.key". Then, when running tests that use Open AI API, you must either set the env variable VCR_RECORD=1
|
||||
or to add `vcr_record!` to the test. See `VcrTestHelper`.
|
||||
|
||||
## Deploying
|
||||
## Environments
|
||||
|
||||
Fizzy is deployed with Kamal. You'll need to have the 1Password CLI set up in order to access the secrets that are used when deploying. Provided you have that, it should be as simple as `bin/kamal deploy` to the correct environment.
|
||||
|
||||
### Beta
|
||||
|
||||
For beta:
|
||||
|
||||
bin/kamal deploy -d beta
|
||||
Beta is primarily intended for testing product features.
|
||||
|
||||
Beta tenant is:
|
||||
|
||||
- https://fizzy.37signals.works/
|
||||
|
||||
This environment uses local disk for Active Storage.
|
||||
|
||||
|
||||
### Staging
|
||||
|
||||
Staging is primarily intended for testing infrastructure changes.
|
||||
|
||||
Production tenants are:
|
||||
|
||||
- https://37s.fizzy.37signals-staging.com/
|
||||
- https://dev.fizzy.37signals-staging.com/
|
||||
- https://qa.fizzy.37signals-staging.com/
|
||||
|
||||
This environment uses a FlashBlade bucket for blob storage, and shares nothing with Production. We may periodically copy data here from production.
|
||||
|
||||
|
||||
### Production
|
||||
|
||||
And for production:
|
||||
|
||||
bin/kamal deploy -d production
|
||||
|
||||
Production tenants are:
|
||||
|
||||
- https://37s.fizzy.37signals.com/
|
||||
- https://dev.fizzy.37signals.com/
|
||||
- https://qa.fizzy.37signals.com/
|
||||
|
||||
This environment uses a FlashBlade bucket for blob storage.
|
||||
|
||||
+4
-9
@@ -6,14 +6,9 @@ cable: &cable
|
||||
polling_interval: 0.1.seconds
|
||||
message_retention: 1.day
|
||||
|
||||
development:
|
||||
<<: *cable
|
||||
|
||||
development: *cable
|
||||
test:
|
||||
adapter: test
|
||||
|
||||
production: &production
|
||||
<<: *cable
|
||||
|
||||
beta:
|
||||
<<: *production
|
||||
beta: *cable
|
||||
staging: *cable
|
||||
production: *cable
|
||||
|
||||
+6
-10
@@ -10,16 +10,12 @@ default_connection: &default_connection
|
||||
database:
|
||||
writing: :cache
|
||||
|
||||
development:
|
||||
default: &default
|
||||
<<: *default_connection
|
||||
<<: *default_options
|
||||
|
||||
test:
|
||||
<<: *default_options
|
||||
|
||||
production: &production
|
||||
<<: *default_connection
|
||||
<<: *default_options
|
||||
|
||||
beta:
|
||||
<<: *production
|
||||
development: *default
|
||||
test: *default_options
|
||||
beta: *default
|
||||
staging: *default
|
||||
production: *default
|
||||
|
||||
@@ -1 +1 @@
|
||||
I2oqW56RTDrRxQ5HUGXGUbSiVoeICiF6tjSo1oxmGuZKE6wu99S+RvQ6Mf0enCQdbHG0osoCpUvu7iuOMEA3X6vO7ku1YFbCDKugu6tY913bzRl166SWZdSlEwtcr6wtmUkXLoWfDzOt98lJ03nU8YbeDC2AzuBqcYWS2qjqpFrrDK8WQI7IukM4iFEDjesW2Noekyy6z+b5+DxB2lkCMFgim4ExW/ndFmrvDnt+QeR+rB9XW9BF6CEg5pPsBQ9EwtICsacCWdvFFOZ8EaNoOuF+hKIHoKP60UCfQj5EUir/r5pGE0Z83z91+UpdpVCuGvh62uSZoZOjdGAplg/DWWKpGcj5JOA7V2yyGEMlz7NueBInG8t/eEyeX/98fAy4TNUxxvncNB+xsmgPJIqlek7vXtYe06AMwrRvac4QSSpUuwWuKUV8JF4gYT5Gp92rzqmmwsTmjvEMiPlnnVYH83GCtd2f1Se7EkDVTvgLA3idnjLvFCelAU4Vdo9/pLqG+0xorSxQ4D/UXqykxtTSjz6pC2P8J1g6T91TQhcH4tDFuZICOYLyFV8F5OD3jPaP+ml01oME42FIKmyhvcNhMLqluUvFqqtOxgWp54jCnde6MBHJ9W7gejwfSmjyD+pr/5NXgaGaTq9h6NMdMkr0Bis6Cc/EgHZKBpJx6ARH1ulcp9uZ9tBjNCePBNxATrJLKwiXh0ZTLDfDTkgdznkj8u+FAKclxjIZ63td3hGe--5kL30BIpNtC7wcsf--YaV9PXL74Wl2ePaAdT5Crg==
|
||||
/M5cK3B/Wq1R2f4XsQQ8t7qJGCNMaBU3itDDKNZapeGMjrlE4A9CKOh2RPQsKlrsGjJdgGL4YdfDiT1LiF0pD/KL/t5Fw8Z8GMndzA+hmpvQ+hgufvd8n2ZzK/SIK6RmfC9BabdlvuQ0rr3/EdQJ5yIgk3WtWv73bOWDopqHerEAcaNl8KjCu5n2vokAidqEh0/O30yQQB9PAFMRqEwapLVcDSnaJXr6OQnAAm9tIoWaEaIF8ZJH3Rmn0COs8xZqYFyFv/pP3gVy3Mw+VL3aIkEf/eZ3IQWYNf7fiKPvIdNVsmghmeoQRqCp4E0dpn2XDSEGx5i5oq7ynSDCPky4GahiLtpe3vas+Z+lzD5hAAZmlX0G615b4hWjAViTEQU+CMXhmpj7eVpT9co+1oKmqtbDvHr7uCJIf4d17kC13u/8yjgl2SaCjRWx94wh8su/h6h9Xw0qewITbfM32pFRiH+R5bc=--fxg4Lf+qmYeuvyZp--qVZ+ELV0FRzBb69MUAqOsQ==
|
||||
@@ -0,0 +1 @@
|
||||
Tc514fYVlm1c2c81KUFmuAGZ9rSZT7XfeGUEdTEvJNDD6JE9IghKbAAGgc6AalIt2/VxzSV6AGvNagb0/qlJrMOFeSJLqzufKt1YoLRUZtSUZDtzmI/2WSzju0Tyu4za6rnLEu+WvDc0NM8KZEv/TwwUbSOwoEVDQmava/iuWyvFr5sOH1wNr2kwYbErwDpThKcYqacI4CdvgpgXc//3T0Z5vsVCs6d8723DymM0KkSK9so8WrcCesk2fmhM1K2hQV7QdckaVuOL0JEj1AI7KzdJm7REoeLwRwaBeVDkqDNo2fKxwZ2XmU2ViJOozPsowx+324wQQZjbsf/0ohtDkgjbfMmA2tjkuNJdJFwIIc5VyvILhVs5WQIJHSXmabhUKxzKRCRZNBSaadLGCb7/AGfULKvh2vP1BWqm80EkDmhHm42ucJW1vA377y9UYWVcdvqWtp5m2F7HlXqi9Uw/+kFV2X6Jw1c07FsCu35TrUb5u8G7mu/866GBgf5VlfDVs1BA3aru05CtcsXi2qKMw0II7fZps/4XpYCB+VehXAyLi2ABVeTnqSfF7HwasXvfD3Jgh7zJLD0hudNDpu6xkmoyeksVBn034dmQf0TwAIKmNjEKMDxgAG50T2JhnEvHZEnqzGl6O8if8DKM5rPgt3XEU3zN/U3yA8T0eTyFdGlWbYK7Ergu4TcGo3WPk6bJhTGOHQ9puD89t6JGHbKDYW77w44SHv+C42flmNkzcndXlpvZvnEafDYeW6ofRC4eeTRX4+WKL4CYhlel78+twD6Mh0MV42MYM2rmtl66NHN8fWxyfoyjrNcXveKVAsGMatB0+dOglq6GmOiXRAt/I6D+7QYZLyaUhYNmmiuZXF4=--H6KWPnHc9qUQE5AI--PN98cg9t9ZhxMUEax/Mfgg==
|
||||
+2
-2
@@ -63,5 +63,5 @@ production: &production
|
||||
database: storage/production_queue.sqlite3
|
||||
migrations_paths: db/queue_migrate
|
||||
|
||||
beta:
|
||||
<<: *production
|
||||
beta: *production
|
||||
staging: *production
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
servers:
|
||||
web:
|
||||
hosts:
|
||||
- fizzy-staging-app-01
|
||||
jobs:
|
||||
hosts:
|
||||
- fizzy-staging-app-01
|
||||
web-replica:
|
||||
hosts:
|
||||
- fizzy-staging-app-101
|
||||
proxy: true
|
||||
|
||||
proxy:
|
||||
ssl: false
|
||||
|
||||
ssh:
|
||||
user: app
|
||||
|
||||
env:
|
||||
clear:
|
||||
RAILS_ENV: staging
|
||||
|
||||
x-beamer-accessory: &beamer-accessory
|
||||
image: basecamp/beamer
|
||||
registry:
|
||||
username: bcbot
|
||||
password:
|
||||
- BASECAMP_REGISTRY_PASSWORD
|
||||
options:
|
||||
user: 1000 # Match the UID of the Rails app, for volume permissions
|
||||
volumes:
|
||||
- fizzy:/storage
|
||||
|
||||
|
||||
accessories:
|
||||
beamer-primary:
|
||||
<<: *beamer-accessory
|
||||
service: beamer-primary
|
||||
cmd: beamer primary --remove-after=1h --dir=/storage --disable-tls
|
||||
port: 5000:80
|
||||
roles:
|
||||
- web
|
||||
|
||||
beamer-replica:
|
||||
<<: *beamer-accessory
|
||||
service: beamer-replica
|
||||
cmd: beamer replica --primary=http://fizzy-staging-app-01:5000/ --dir=/storage
|
||||
roles:
|
||||
- web-replica
|
||||
|
||||
load-balancer:
|
||||
image: basecamp/kamal-proxy:lb
|
||||
roles:
|
||||
- web
|
||||
options:
|
||||
publish:
|
||||
- 80:80
|
||||
- 443:443
|
||||
@@ -0,0 +1,5 @@
|
||||
require_relative "production"
|
||||
|
||||
Rails.application.configure do
|
||||
config.action_mailer.default_url_options = { host: "%{tenant}.fizzy.37signals-staging.com" }
|
||||
end
|
||||
@@ -1,4 +1,4 @@
|
||||
if (Rails.env.production? || Rails.env.beta?) && ENV["SKIP_TELEMETRY"].blank?
|
||||
if !Rails.env.local? && ENV["SKIP_TELEMETRY"].blank?
|
||||
Sentry.init do |config|
|
||||
config.dsn = "https://ca338fb1fe6f677d6aeec2336a86f0ee@o33603.ingest.us.sentry.io/4508093839179776"
|
||||
config.breadcrumbs_logger = %i[ active_support_logger http_logger ]
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
Rails.application.config.after_initialize do
|
||||
# in production, we're using a two-level subdomain like "tenant.fizzy.37signals.com", but in
|
||||
# development and beta it's only a single-level subdomain.
|
||||
# in production and staging, we're using a two-level subdomain like "tenant.fizzy.37signals.com".
|
||||
# in development and beta it's only a single-level subdomain.
|
||||
Rails.application.config.active_record_tenanted.tenant_resolver = ->(request) do
|
||||
next nil if request.path == "/up"
|
||||
|
||||
tld_length = request.domain == "37signals.com" ? 2 : 1
|
||||
tld_length = [ "37signals.com", "37signals-staging.com" ].include?(request.domain) ? 2 : 1
|
||||
request.subdomain(tld_length).presence || "return-404" # this is a quick fix for now
|
||||
end
|
||||
end
|
||||
|
||||
+5
-11
@@ -8,14 +8,8 @@ default: &default
|
||||
processes: <%= ENV.fetch("JOB_CONCURRENCY", 1) %>
|
||||
polling_interval: 0.1
|
||||
|
||||
development:
|
||||
<<: *default
|
||||
|
||||
test:
|
||||
<<: *default
|
||||
|
||||
production: &production
|
||||
<<: *default
|
||||
|
||||
beta:
|
||||
<<: *production
|
||||
development: *default
|
||||
test: *default
|
||||
beta: *default
|
||||
staging: *default
|
||||
production: *default
|
||||
|
||||
@@ -15,5 +15,5 @@ production: &production
|
||||
class: DeleteUnusedTagsJob
|
||||
schedule: every day at 04:00
|
||||
|
||||
beta:
|
||||
<<: *production
|
||||
beta: *production
|
||||
staging: *production
|
||||
|
||||
Reference in New Issue
Block a user