Skip to content

Conversation

@jorgemanrubia
Copy link
Member

@jorgemanrubia jorgemanrubia commented Nov 23, 2025

Separate SaaS and open source versions of Fizzy.

The default version will be the open source one, that runs on SQLite. This is built on top of the work by @djmb in #1669. @flavorjones had done some previous work where the semantics was inverted (opt-in into open source). I think it makes more sense to have the vanilla open source version as the default, now that we are going to make the whole thing public.

This PR introduces a mehanism to enable the SAAS version of the app:

  1. Setting an env var SAAS=1 (this will enable the private gems and configure the MySQL adapter).
  2. Having a file tmp/saas.txt. There are rake tasks to touch/remove it bin/rails saas:enable and bin/rails saas:disable.

(2) is meant for our own dev work, so that don't have to worry about passing the env var during regular daily work. The goal here is having good development ergonomics for everyone:

  • Open source users clone the repo and have it ready to go with Sqlite.
  • We at 37signals clone the repo, touch tmp/saas.txt and we are ready to go with our private extensions and MySQL, using exactly the same scripts vanilla users would use.

For configuring the private gems, this introduces a separated Gemfile.saas file, that includes the original Gemfile and adds the private gems. In SaaS mode, it will configure the bundle file automaticalyl to use the saas one.

(1) is meant to be set in our SaaS hosts via our SaaS Dockerfile, although obviously you are free to use that too locally.

This also moves several bits to the fizzy-saas gem, which now lives in its own private repo:

  • Database configuration. This extracts two vanilla adapters in the open source version database.mysql.yml and database.sqlite.yml and, in SaaS mode, uses the database.yml from the gem. This way, we can keep our very specific MySQL setup outside of the open source version.
  • Kamal deploy configuration and hooks.
  • Fragments of bin/setup that are specific to 37signals.

Pending:

  • Move our Dockerfile to the gem too. Set SAAS env var in Docker.
  • Move secrets to the gem. We need to extend kamal to let you configure the path for secrets in the deploy descriptor.
  • Leave vanilla Kamal setup in the gem.
  • SaaS tests passing (2 failing)
  • QA in staging / beta

@jorgemanrubia jorgemanrubia changed the title Open source split Open source / SaaS split Nov 23, 2025
@jorgemanrubia jorgemanrubia force-pushed the open-source-split branch 3 times, most recently from 323b2bf to 49cf4d6 Compare November 23, 2025 17:24
@@ -0,0 +1,8 @@
# This Gemfile extends the base Gemfile with SaaS-specific dependencies
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note that I had originally kept these dependencies in the Gemfile so that bundle install and bundle exec would work as expected if we have the SAAS env var set. My initial reaction is slightly negative, but I'm willing to give it five minutes.

Copy link
Member Author

@jorgemanrubia jorgemanrubia Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with a single Gemfile and a conditional inclusion is that, whenever you toggle the mode, you end up with a changed Gemfile.lock.

I agree about the bundle install issue. To me, this was the lesser inconvenience in terms of dev ergonomics. You can use bin/dev and it will take care of setting the right Gemfile. And we could also add our own bin/bundle wrapper that takes care of that.

If you have a better approach in mind please share. I landed here by trying different approaches (conditional inclusion, gem groups, separated gemfiles), but not holding any strong opinion other than trying to make things as seamless as possible.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I do like the idea of having a patched bin/bundle stub. But also I'm fine giving this five minutes and seeing if it's actually a problem.

@jorgemanrubia jorgemanrubia force-pushed the open-source-split branch 5 times, most recently from 398037f to 35bf35b Compare November 25, 2025 11:07
Base automatically changed from sqlite to main November 26, 2025 10:32
@jorgemanrubia jorgemanrubia force-pushed the open-source-split branch 7 times, most recently from 561c34d to 2bf333f Compare November 27, 2025 07:47
## CRUD operations from controllers

In general, we favor a vanilla Rails approach to CRUD operations. We create and update models from Rails controllers passing the parameters directly to the model constructor or update method. We do not use services or form objects to handle these operations.
## Controller and model interactions
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@flavorjones I reviewed a bit the style guidelines regarding controller and model interactions. I think it was emphasizing too much the enter/review pattern we used in HEY, and not emphasizing enough the general approach: clear model APIs directly invoked from the controller.

@jorgemanrubia jorgemanrubia force-pushed the open-source-split branch 4 times, most recently from a6acb89 to 05b7ce6 Compare November 28, 2025 11:18
Use Sentry MCP tools to investigate production errors:
- `search_issues` - Find grouped issues by natural language query
- `get_issue_details` - Get full stacktrace and context for a specific issue
- `analyze_issue_with_seer` - AI-powered root cause analysis with code fix suggestions
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@flavorjones I see you already placed a more compact prompt for observability/sentry in shipyard. I am removing these bits since these are not appropiate for the open source version. All the observability config resides now in the gem. If we need the specialization, I think we could move to the gem fizzy-saas and instruct in the prompt about it. But it is probably better if we can go with a single compact version of this at the shipyard level. What do you think?

@jorgemanrubia jorgemanrubia merged commit d804d4a into main Nov 28, 2025
6 checks passed
@jorgemanrubia jorgemanrubia deleted the open-source-split branch November 28, 2025 15:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants