diff --git a/gems/fizzy-saas/.github/dependabot.yml b/gems/fizzy-saas/.github/dependabot.yml deleted file mode 100644 index 83610cfa4..000000000 --- a/gems/fizzy-saas/.github/dependabot.yml +++ /dev/null @@ -1,12 +0,0 @@ -version: 2 -updates: -- package-ecosystem: bundler - directory: "/" - schedule: - interval: weekly - open-pull-requests-limit: 10 -- package-ecosystem: github-actions - directory: "/" - schedule: - interval: weekly - open-pull-requests-limit: 10 diff --git a/gems/fizzy-saas/.github/workflows/ci.yml b/gems/fizzy-saas/.github/workflows/ci.yml deleted file mode 100644 index ef5e97c73..000000000 --- a/gems/fizzy-saas/.github/workflows/ci.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: CI - -on: - pull_request: - push: - branches: [ main ] - -jobs: - lint: - runs-on: ubuntu-latest - env: - RUBY_VERSION: ruby-3.4.5 - RUBOCOP_CACHE_ROOT: tmp/rubocop - steps: - - name: Checkout code - uses: actions/checkout@v5 - - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: ${{ env.RUBY_VERSION }} - bundler-cache: true - - - name: Prepare RuboCop cache - uses: actions/cache@v4 - env: - DEPENDENCIES_HASH: ${{ hashFiles('**/.rubocop.yml', '**/.rubocop_todo.yml', 'Gemfile.lock') }} - with: - path: ${{ env.RUBOCOP_CACHE_ROOT }} - key: rubocop-${{ runner.os }}-${{ env.RUBY_VERSION }}-${{ env.DEPENDENCIES_HASH }}-${{ github.ref_name == github.event.repository.default_branch && github.run_id || 'default' }} - restore-keys: | - rubocop-${{ runner.os }}-${{ env.RUBY_VERSION }}-${{ env.DEPENDENCIES_HASH }}- - - - name: Lint code for consistent style - run: bin/rubocop -f github - - test: - runs-on: ubuntu-latest - - # services: - # redis: - # image: valkey/valkey:8 - # ports: - # - 6379:6379 - # options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5 - steps: - - name: Checkout code - uses: actions/checkout@v5 - - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: ruby-3.4.5 - bundler-cache: true - - - name: Run tests - env: - RAILS_ENV: test - # RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }} - # REDIS_URL: redis://localhost:6379/0 - run: bin/rails db:test:prepare test - - - name: Keep screenshots from failed system tests - uses: actions/upload-artifact@v4 - if: failure() - with: - name: screenshots - path: ${{ github.workspace }}/tmp/screenshots - if-no-files-found: ignore diff --git a/gems/fizzy-saas/.gitignore b/gems/fizzy-saas/.gitignore deleted file mode 100644 index a3ee5aad3..000000000 --- a/gems/fizzy-saas/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -/.bundle/ -/doc/ -/log/*.log -/pkg/ -/tmp/ -/test/dummy/db/*.sqlite3 -/test/dummy/db/*.sqlite3-* -/test/dummy/log/*.log -/test/dummy/storage/ -/test/dummy/tmp/ diff --git a/gems/fizzy-saas/.kamal/hooks/post-deploy b/gems/fizzy-saas/.kamal/hooks/post-deploy deleted file mode 100755 index 871506078..000000000 --- a/gems/fizzy-saas/.kamal/hooks/post-deploy +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -MESSAGE="$KAMAL_PERFORMER deployed $KAMAL_SERVICE_VERSION to $KAMAL_DESTINATION in $KAMAL_RUNTIME seconds" -CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) - -bin/notify_dash_of_deployment "$MESSAGE" $KAMAL_VERSION $KAMAL_PERFORMER $CURRENT_BRANCH $KAMAL_DESTINATION $KAMAL_RUNTIME - -if [[ $CURRENT_BRANCH == "main" && $KAMAL_DESTINATION == "production" ]]; then - gh release create $KAMAL_SERVICE_VERSION --target $KAMAL_VERSION --generate-notes 2> /dev/null || true - - RELEASE_URL=$(gh release view $KAMAL_SERVICE_VERSION --json url,body --jq .url) - RELEASE_BODY=$(gh release view $KAMAL_SERVICE_VERSION --json url,body --jq .body) - - bin/broadcast_to_bc "$MESSAGE "$'\n'"$RELEASE_URL "$'\n'"$RELEASE_BODY" -else - bin/broadcast_to_bc "$MESSAGE" -fi diff --git a/gems/fizzy-saas/.kamal/hooks/pre-build b/gems/fizzy-saas/.kamal/hooks/pre-build deleted file mode 100755 index 99de8a824..000000000 --- a/gems/fizzy-saas/.kamal/hooks/pre-build +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env ruby - -def exit_with_error(message) - $stderr.puts message - exit 1 -end - -def check_branch - if ENV["KAMAL_DESTINATION"] == "production" - current_branch = `git branch --show-current`.strip - - if current_branch != "main" - exit_with_error "Only the `main` branch should be deployed to production, current branch is #{current_branch}. If this is expected, try again with `SKIP_GIT_CHECKS=1` prepended to the command" - end - end -end - -def check_for_uncommitted_changes - if `git status --porcelain`.strip.length != 0 - exit_with_error "You have uncommitted changes, aborting" - end -end - -def check_local_and_remote_heads_match - remote_head = `git ls-remote origin --tags $(git branch --show-current) | cut -f1 | head -1`.strip - local_head = `git rev-parse HEAD`.strip - - if local_head != remote_head - exit_with_error "Remote HEAD #{remote_head}, differs from local HEAD #{local_head}, aborting" - end -end - -unless ENV["SKIP_GIT_CHECKS"] - check_branch - check_for_uncommitted_changes - check_local_and_remote_heads_match -end diff --git a/gems/fizzy-saas/.kamal/hooks/pre-connect b/gems/fizzy-saas/.kamal/hooks/pre-connect deleted file mode 100755 index 5f42f2cf2..000000000 --- a/gems/fizzy-saas/.kamal/hooks/pre-connect +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env bash - -# Validate hostnames are FQDNs ending in -int.37signals.com -if command -v yq >/dev/null 2>&1; then - declare -A SUGGESTIONS - while IFS= read -r host; do - if [[ ! $host =~ -int\.37signals\.com$ ]]; then - if [[ $host =~ -4[0-9]{2}$ ]]; then - SUGGESTIONS["$host"]="$host.df-ams-int.37signals.com" - elif [[ $host =~ -1[0-9]{2}$ ]]; then - SUGGESTIONS["$host"]="$host.df-iad-int.37signals.com" - else - SUGGESTIONS["$host"]="$host.sc-chi-int.37signals.com" - fi - fi - done < <(bin/kamal config -d "${KAMAL_DESTINATION:-production}" 2>/dev/null | yq -r '.":hosts"[]') - - if [ ${#SUGGESTIONS[@]} -gt 0 ]; then - echo "Unqualified hostnames found in config/deploy.${KAMAL_DESTINATION:-production}.yml:" >&2 - echo "" >&2 - echo "Update to use fully-qualified hostnames:" >&2 - for host in "${!SUGGESTIONS[@]}"; do - echo " $host → ${SUGGESTIONS[$host]}" >&2 - done - exit 1 - fi -fi - -# Verify Tailscale connection and SSH authentication before deploying. -tailscale_cmd() { - if command -v tailscale >/dev/null 2>&1; then - tailscale "$@" - elif [ -f "/Applications/Tailscale.app/Contents/MacOS/Tailscale" ]; then - env TAILSCALE_BE_CLI=1 /Applications/Tailscale.app/Contents/MacOS/Tailscale "$@" - else - return 1 - fi -} - -on_tailscale() { - tailscale_cmd status --json 2>/dev/null | jq -e '.Self.Online' >/dev/null 2>&1 -} - -# Check Tailscale connection -if ! on_tailscale; then - echo "" >&2 - echo "You must be connected to Tailscale to deploy." >&2 - echo "" >&2 - echo "→ Connect to Tailscale and try again" >&2 - echo "" >&2 - exit 1 -fi - -# Verify SSH access -echo "Deploying via Tailscale. Verifying SSH access…" >&2 - -TEST_HOST="fizzy-app-101" - -SSH_OUTPUT=$(ssh -o ConnectTimeout=5 "app@$TEST_HOST" true 2>&1) -SSH_EXIT=$? - -echo "$SSH_OUTPUT" >&2 - -if echo "$SSH_OUTPUT" | grep -q "Permission denied"; then - GITHUB_USER=$(gh api user 2>/dev/null | jq -r '.login // "unknown"') - GITHUB_KEYS_URL="https://github.com/${GITHUB_USER}.keys" - - echo "" >&2 - echo "ERROR: SSH authentication failed" >&2 - echo "" >&2 - echo "You must deploy with an SSH key that's on your GitHub account." >&2 - echo "" >&2 - echo "→ Verify your public key is at $GITHUB_KEYS_URL" >&2 - echo " Add it at https://github.com/settings/keys if not" >&2 - echo "" >&2 - echo "Note that SSH keys are pulled from GitHub every 5 minutes, so if you've" >&2 - echo "just added a new key to GitHub, try again in five." >&2 - echo "" >&2 - exit 1 -fi - -exit $SSH_EXIT diff --git a/gems/fizzy-saas/.rubocop.yml b/gems/fizzy-saas/.rubocop.yml deleted file mode 100644 index f9d86d4a5..000000000 --- a/gems/fizzy-saas/.rubocop.yml +++ /dev/null @@ -1,8 +0,0 @@ -# Omakase Ruby styling for Rails -inherit_gem: { rubocop-rails-omakase: rubocop.yml } - -# Overwrite or add rules to create your own house style -# -# # Use `[a, [b, c]]` not `[ a, [ b, c ] ]` -# Layout/SpaceInsideArrayLiteralBrackets: -# Enabled: false diff --git a/gems/fizzy-saas/Gemfile b/gems/fizzy-saas/Gemfile deleted file mode 100644 index 396a3192e..000000000 --- a/gems/fizzy-saas/Gemfile +++ /dev/null @@ -1,6 +0,0 @@ -source "https://rubygems.org" -git_source(:bc) { |repo| "https://github.com/basecamp/#{repo}" } - -# 37id and Queenbee integration -gem "queenbee", bc: "queenbee-plugin", ref: "eb01c697de1ad028afc65cc7d9b5345a7a8e849f" -gem "activeresource", require: "active_resource" # needed by queenbee diff --git a/gems/fizzy-saas/Gemfile.lock b/gems/fizzy-saas/Gemfile.lock deleted file mode 100644 index 5d83987cd..000000000 --- a/gems/fizzy-saas/Gemfile.lock +++ /dev/null @@ -1,69 +0,0 @@ -GIT - remote: https://github.com/basecamp/queenbee-plugin - revision: eb01c697de1ad028afc65cc7d9b5345a7a8e849f - ref: eb01c697de1ad028afc65cc7d9b5345a7a8e849f - specs: - queenbee (3.2.0) - activeresource - builder - rexml - -GEM - remote: https://rubygems.org/ - specs: - activemodel (8.0.2.1) - activesupport (= 8.0.2.1) - activemodel-serializers-xml (1.0.3) - activemodel (>= 5.0.0.a) - activesupport (>= 5.0.0.a) - builder (~> 3.1) - activeresource (6.1.4) - activemodel (>= 6.0) - activemodel-serializers-xml (~> 1.0) - activesupport (>= 6.0) - activesupport (8.0.2.1) - base64 - benchmark (>= 0.3) - bigdecimal - concurrent-ruby (~> 1.0, >= 1.3.1) - connection_pool (>= 2.2.5) - drb - i18n (>= 1.6, < 2) - logger (>= 1.4.2) - minitest (>= 5.1) - securerandom (>= 0.3) - tzinfo (~> 2.0, >= 2.0.5) - uri (>= 0.13.1) - base64 (0.3.0) - benchmark (0.4.1) - bigdecimal (3.2.3) - builder (3.3.0) - concurrent-ruby (1.3.5) - connection_pool (2.5.4) - drb (2.2.3) - i18n (1.14.7) - concurrent-ruby (~> 1.0) - logger (1.7.0) - minitest (5.25.5) - rexml (3.4.4) - securerandom (0.4.1) - tzinfo (2.0.6) - concurrent-ruby (~> 1.0) - uri (1.0.3) - -PLATFORMS - aarch64-linux-gnu - aarch64-linux-musl - arm-linux-gnu - arm-linux-musl - arm64-darwin - x86_64-darwin - x86_64-linux-gnu - x86_64-linux-musl - -DEPENDENCIES - activeresource - queenbee! - -BUNDLED WITH - 2.7.0 diff --git a/gems/fizzy-saas/README.md b/gems/fizzy-saas/README.md deleted file mode 100644 index ecaa3ede6..000000000 --- a/gems/fizzy-saas/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# Fizzy::Saas -Short description and motivation. - -## Usage -How to use my plugin. - -## Installation -Add this line to your application's Gemfile: - -```ruby -gem "fizzy-saas" -``` - -And then execute: -```bash -$ bundle -``` - -Or install it yourself as: -```bash -$ gem install fizzy-saas -``` - -## Contributing -Contribution directions go here. - -## License -The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). diff --git a/gems/fizzy-saas/Rakefile b/gems/fizzy-saas/Rakefile deleted file mode 100644 index e7793b5c1..000000000 --- a/gems/fizzy-saas/Rakefile +++ /dev/null @@ -1,8 +0,0 @@ -require "bundler/setup" - -APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__) -load "rails/tasks/engine.rake" - -load "rails/tasks/statistics.rake" - -require "bundler/gem_tasks" diff --git a/gems/fizzy-saas/app/assets/images/fizzy/saas/.keep b/gems/fizzy-saas/app/assets/images/fizzy/saas/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/gems/fizzy-saas/app/assets/stylesheets/fizzy/saas/application.css b/gems/fizzy-saas/app/assets/stylesheets/fizzy/saas/application.css deleted file mode 100644 index 0ebd7fe82..000000000 --- a/gems/fizzy-saas/app/assets/stylesheets/fizzy/saas/application.css +++ /dev/null @@ -1,15 +0,0 @@ -/* - * This is a manifest file that'll be compiled into application.css, which will include all the files - * listed below. - * - * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, - * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. - * - * You're free to add application-wide styles to this file and they'll appear at the bottom of the - * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS - * files in this directory. Styles in this file should be added after the last require_* statement. - * It is generally better to create a new file per style scope. - * - *= require_tree . - *= require_self - */ diff --git a/gems/fizzy-saas/app/controllers/concerns/.keep b/gems/fizzy-saas/app/controllers/concerns/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/gems/fizzy-saas/app/controllers/signup/completions_controller.rb b/gems/fizzy-saas/app/controllers/signup/completions_controller.rb deleted file mode 100644 index d7f09c086..000000000 --- a/gems/fizzy-saas/app/controllers/signup/completions_controller.rb +++ /dev/null @@ -1,24 +0,0 @@ -class Signup::CompletionsController < ApplicationController - layout "public" - - disallow_account_scope - - def new - @signup = Signup.new(identity: Current.identity) - end - - def create - @signup = Signup.new(signup_params) - - if @signup.complete - redirect_to landing_url(script_name: @signup.account.slug) - else - render :new, status: :unprocessable_entity - end - end - - private - def signup_params - params.expect(signup: %i[ full_name ]).with_defaults(identity: Current.identity) - end -end diff --git a/gems/fizzy-saas/app/models/concerns/.keep b/gems/fizzy-saas/app/models/concerns/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/gems/fizzy-saas/app/models/signup.rb b/gems/fizzy-saas/app/models/signup.rb deleted file mode 100644 index ca76f5b08..000000000 --- a/gems/fizzy-saas/app/models/signup.rb +++ /dev/null @@ -1,127 +0,0 @@ -class Signup - include ActiveModel::Model - include ActiveModel::Attributes - include ActiveModel::Validations - - attr_accessor :full_name, :email_address, :identity - attr_reader :queenbee_account, :account, :user - - with_options on: :completion do - validates_presence_of :full_name, :identity - end - - def initialize(...) - @full_name = nil - @email_address = nil - @account = nil - @user = nil - @queenbee_account = nil - @identity = nil - - super - - @email_address = @identity.email_address if @identity - end - - def create_identity - @identity = Identity.find_or_create_by!(email_address: email_address) - @identity.send_magic_link - end - - def complete - if valid?(:completion) - begin - create_queenbee_account - create_account - - true - rescue => error - destroy_account - destroy_queenbee_account - - errors.add(:base, "Something went wrong, and we couldn't create your account. Please give it another try.") - Rails.error.report(error, severity: :error) - Rails.logger.error error - Rails.logger.error error.backtrace.join("\n") - - false - end - else - false - end - end - - private - def create_queenbee_account - @account_name = AccountNameGenerator.new(identity: identity, name: full_name).generate - @queenbee_account = Queenbee::Remote::Account.create!(queenbee_account_attributes) - @tenant = queenbee_account.id.to_s - end - - def destroy_queenbee_account - @queenbee_account&.cancel - @queenbee_account = nil - end - - def create_account - @account = Account.create_with_admin_user( - account: { - external_account_id: @tenant, - name: @account_name - }, - owner: { - name: full_name, - identity: identity - } - ) - @user = @account.users.find_by!(role: :admin) - @account.setup_customer_template - end - - def destroy_account - @account&.destroy! - - @user = nil - @account = nil - @tenant = nil - end - - def queenbee_account_attributes - {}.tap do |attributes| - attributes[:product_name] = "fizzy" - attributes[:name] = @account_name - attributes[:owner_name] = full_name - attributes[:owner_email] = email_address - - attributes[:trial] = true - attributes[:subscription] = subscription_attributes - attributes[:remote_request] = request_attributes - - # # TODO: Terms of Service - # attributes[:terms_of_service] = true - - # We've confirmed the email - attributes[:auto_allow] = true - - # Tell Queenbee to skip the request to create a local account. We've created it ourselves. - attributes[:skip_remote] = true - end - end - - def subscription_attributes - subscription = FreeV1Subscription - - {}.tap do |attributes| - attributes[:name] = subscription.to_param - attributes[:price] = subscription.price - end - end - - def request_attributes - {}.tap do |attributes| - attributes[:remote_address] = Current.ip_address - attributes[:user_agent] = Current.user_agent - attributes[:referrer] = Current.referrer - end - end -end diff --git a/gems/fizzy-saas/app/models/signup/account_name_generator.rb b/gems/fizzy-saas/app/models/signup/account_name_generator.rb deleted file mode 100644 index a6844d3a3..000000000 --- a/gems/fizzy-saas/app/models/signup/account_name_generator.rb +++ /dev/null @@ -1,53 +0,0 @@ -class Signup::AccountNameGenerator - SUFFIX = "Fizzy".freeze - - attr_reader :identity, :name - - def initialize(identity:, name:) - @identity = identity - @name = name - end - - def generate - next_index = current_index + 1 - - if next_index == 1 - "#{prefix} #{SUFFIX}" - else - "#{prefix} #{next_index.ordinalize} #{SUFFIX}" - end - end - - private - def current_index - existing_indices.max || 0 - end - - def existing_indices - Current.without_account do - identity.accounts.filter_map do |account| - if account.name.match?(first_account_name_regex) - 1 - elsif match = account.name.match(nth_account_name_regex) - match[1].to_i - end - end - end - end - - def first_account_name_regex - @first_account_name_regex ||= /\A#{prefix}\s+#{SUFFIX}\Z/i - end - - def nth_account_name_regex - @nth_account_name_regex ||= /\A#{prefix}\s+(1st|2nd|3rd|\d+th)\s+#{SUFFIX}/i - end - - def prefix - @prefix ||= "#{first_name}'s" - end - - def first_name - name.strip.split(" ", 2).first - end -end diff --git a/gems/fizzy-saas/app/models/subscription.rb b/gems/fizzy-saas/app/models/subscription.rb deleted file mode 100644 index 5efb1a7fa..000000000 --- a/gems/fizzy-saas/app/models/subscription.rb +++ /dev/null @@ -1,13 +0,0 @@ -class Subscription < Queenbee::Subscription - SHORT_NAMES = %w[ FreeV1 ] - - def self.short_name - name.demodulize - end - - class FreeV1 < Subscription - property :proper_name, "Free Subscription" - property :price, 0 - property :frequency, "yearly" - end -end diff --git a/gems/fizzy-saas/app/views/layouts/fizzy/saas/application.html.erb b/gems/fizzy-saas/app/views/layouts/fizzy/saas/application.html.erb deleted file mode 100644 index 144b37838..000000000 --- a/gems/fizzy-saas/app/views/layouts/fizzy/saas/application.html.erb +++ /dev/null @@ -1,17 +0,0 @@ - - - - Fizzy saas - <%= csrf_meta_tags %> - <%= csp_meta_tag %> - - <%= yield :head %> - - <%= stylesheet_link_tag "fizzy/saas/application", media: "all" %> - - - -<%= yield %> - - - diff --git a/gems/fizzy-saas/app/views/signup/completions/new.html.erb b/gems/fizzy-saas/app/views/signup/completions/new.html.erb deleted file mode 100644 index aee8f4586..000000000 --- a/gems/fizzy-saas/app/views/signup/completions/new.html.erb +++ /dev/null @@ -1,30 +0,0 @@ -<% @page_title = "Complete your sign-up" %> - -
"> -

<%= @page_title %>

- - <%= form_with model: @signup, url: saas.signup_completion_path, scope: "signup", class: "flex flex-column gap", data: { controller: "form" } do |form| %> - <%= form.text_field :full_name, class: "input txt-large", autocomplete: "name", placeholder: "Enter your full name…", autofocus: true, required: true %> - -

You’re one step away. Just enter your name to get your own Fizzy account.

- - <% if @signup.errors.any? %> -
- -
- <% end %> - - - <% end %> -
- -<% content_for :footer do %> - <%= render "sessions/footer" %> -<% end %> diff --git a/gems/fizzy-saas/app/views/signup/new.html.erb b/gems/fizzy-saas/app/views/signup/new.html.erb deleted file mode 100644 index 93166dd2f..000000000 --- a/gems/fizzy-saas/app/views/signup/new.html.erb +++ /dev/null @@ -1,28 +0,0 @@ -<% @page_title = "Sign up for Fizzy" %> - -
"> -

Sign up

- - <%= form_with model: @signup, url: saas.signup_path, scope: "signup", class: "flex flex-column gap", data: { turbo: false, controller: "form" } do |form| %> - <%= form.email_field :email_address, class: "input", autocomplete: "username", placeholder: "Email address", required: true %> - - <% if @signup.errors.any? %> -
- -
- <% end %> - - - <% end %> -
- -<% content_for :footer do %> - <%= render "sessions/footer" %> -<% end %> diff --git a/gems/fizzy-saas/bin/rails b/gems/fizzy-saas/bin/rails deleted file mode 100755 index 42a0e5bce..000000000 --- a/gems/fizzy-saas/bin/rails +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env ruby -# This command will automatically be run when you run "rails" with Rails gems -# installed from the root of your application. - -ENGINE_ROOT = File.expand_path("..", __dir__) -ENGINE_PATH = File.expand_path("../lib/fizzy/saas/engine", __dir__) -APP_PATH = File.expand_path("../test/dummy/config/application", __dir__) - -# Set up gems listed in the Gemfile. -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) -require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"]) - -require "rails/all" -require "rails/engine/commands" diff --git a/gems/fizzy-saas/bin/rubocop b/gems/fizzy-saas/bin/rubocop deleted file mode 100755 index 40330c0ff..000000000 --- a/gems/fizzy-saas/bin/rubocop +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env ruby -require "rubygems" -require "bundler/setup" - -# explicit rubocop config increases performance slightly while avoiding config confusion. -ARGV.unshift("--config", File.expand_path("../.rubocop.yml", __dir__)) - -load Gem.bin_path("rubocop", "rubocop") diff --git a/gems/fizzy-saas/config/database.yml b/gems/fizzy-saas/config/database.yml deleted file mode 100644 index 3c68fd081..000000000 --- a/gems/fizzy-saas/config/database.yml +++ /dev/null @@ -1,100 +0,0 @@ -<% - if ENV["MIGRATE"].present? - mysql_app_user_key = "MYSQL_ALTER_USER" - mysql_app_password_key = "MYSQL_ALTER_PASSWORD" - else - mysql_app_user_key = "MYSQL_APP_USER" - mysql_app_password_key = "MYSQL_APP_PASSWORD" - end - - mysql_app_user = ENV[mysql_app_user_key] - mysql_app_password = ENV[mysql_app_password_key] -%> - -default: &default - adapter: trilogy - host: <%= ENV.fetch "FIZZY_DB_HOST", "127.0.0.1" %> - port: <%= ENV.fetch "FIZZY_DB_PORT", 3306 %> - pool: 50 - timeout: 5000 - variables: - transaction_isolation: READ-COMMITTED - -development: - primary: - <<: *default - database: fizzy_development - port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %> - replica: - <<: *default - database: fizzy_development - port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %> - replica: true - cable: - <<: *default - database: development_cable - port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %> - migrations_paths: db/cable_migrate - cache: - <<: *default - database: development_cache - port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %> - migrations_paths: db/cache_migrate - queue: - <<: *default - database: development_queue - port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %> - migrations_paths: db/queue_migrate - -# Warning: The database defined as "test" will be erased and -# re-generated from your development database when you run "rake". -# Do not set this db to the same as development or production. -test: - primary: - <<: *default - database: fizzy_test - port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %> - replica: - <<: *default - database: fizzy_test - port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %> - replica: true - -production: &production - primary: - <<: *default - database: fizzy_production - host: <%= ENV["MYSQL_DATABASE_HOST"] %> - username: <%= mysql_app_user %> - password: <%= mysql_app_password %> - replica: - <<: *default - database: fizzy_production - host: <%= ENV["MYSQL_DATABASE_REPLICA_HOST"] %> - username: <%= ENV["MYSQL_READONLY_USER"] %> - password: <%= ENV["MYSQL_READONLY_PASSWORD"] %> - replica: true - cable: - <<: *default - database: fizzy_solidcable_production - host: <%= ENV["MYSQL_SOLID_CABLE_HOST"] %> - username: <%= mysql_app_user %> - password: <%= mysql_app_password %> - migrations_paths: db/cable_migrate - queue: - <<: *default - database: fizzy_solidqueue_production - host: <%= ENV["MYSQL_SOLID_QUEUE_HOST"] %> - username: <%= mysql_app_user %> - password: <%= mysql_app_password %> - migrations_paths: db/queue_migrate - cache: - <<: *default - database: fizzy_solidcache_production - host: <%= ENV["MYSQL_SOLID_CACHE_HOST"] %> - username: <%= mysql_app_user %> - password: <%= mysql_app_password %> - migrations_paths: db/cache_migrate - -beta: *production -staging: *production diff --git a/gems/fizzy-saas/config/deploy.beta.yml b/gems/fizzy-saas/config/deploy.beta.yml deleted file mode 100644 index 4c4c323f6..000000000 --- a/gems/fizzy-saas/config/deploy.beta.yml +++ /dev/null @@ -1,53 +0,0 @@ -servers: - web: - hosts: - - fizzy-beta-app-01.sc-chi-int.37signals.com: sc_chi - - fizzy-beta-app-101.df-iad-int.37signals.com: df_iad - labels: - otel_scrape_enabled: true - -# we don't run the jobs role in beta -allow_empty_roles: true - -proxy: - ssl: false - -ssh: - user: app - -env: - clear: - RAILS_ENV: beta - MYSQL_DATABASE_HOST: fizzy-mysql-primary - MYSQL_DATABASE_REPLICA_HOST: fizzy-mysql-replica - MYSQL_SOLID_CABLE_HOST: fizzy-mysql-primary - MYSQL_SOLID_QUEUE_HOST: fizzy-mysql-primary - MYSQL_SOLID_CACHE_HOST: fizzy-beta-solidcache-db-101 - secret: - - RAILS_MASTER_KEY - - MYSQL_ALTER_PASSWORD - - MYSQL_ALTER_USER - - MYSQL_APP_PASSWORD - - MYSQL_APP_USER - - MYSQL_READONLY_PASSWORD - - MYSQL_READONLY_USER - tags: - sc_chi: {} - df_iad: - PRIMARY_DATACENTER: true - df_ams: {} - -accessories: - load-balancer: - image: basecamp/kamal-proxy:lb - host: fizzy-beta-lb-01.sc-chi-int.37signals.com - labels: - otel_role: load-balancer - otel_service: fizzy-load-balancer - otel_scrape_enabled: true - options: - publish: - - 80:80 - - 443:443 - volumes: - - load-balancer:/home/kamal-proxy/.config/kamal-proxy diff --git a/gems/fizzy-saas/config/deploy.dhh.yml b/gems/fizzy-saas/config/deploy.dhh.yml deleted file mode 100644 index 05bf874d4..000000000 --- a/gems/fizzy-saas/config/deploy.dhh.yml +++ /dev/null @@ -1,12 +0,0 @@ -servers: - web: - hosts: - - test-1 - jobs: - hosts: - - test-1 -env: - clear: - ARTENANT: test - -proxy: false diff --git a/gems/fizzy-saas/config/deploy.production.yml b/gems/fizzy-saas/config/deploy.production.yml deleted file mode 100644 index 495227c1f..000000000 --- a/gems/fizzy-saas/config/deploy.production.yml +++ /dev/null @@ -1,72 +0,0 @@ -servers: - web: - hosts: - - fizzy-app-01.sc-chi-int.37signals.com: sc_chi - - fizzy-app-02.sc-chi-int.37signals.com: sc_chi - - fizzy-app-101.df-iad-int.37signals.com: df_iad - - fizzy-app-102.df-iad-int.37signals.com: df_iad - - fizzy-app-401.df-ams-int.37signals.com: df_ams - - fizzy-app-402.df-ams-int.37signals.com: df_ams - labels: - otel_scrape_enabled: true - jobs: - hosts: - - fizzy-jobs-101.df-iad-int.37signals.com: df_iad - - fizzy-jobs-102.df-iad-int.37signals.com: df_iad - labels: - otel_scrape_enabled: true - -proxy: - ssl: false - -ssh: - user: app - -env: - clear: - RAILS_ENV: production - MYSQL_DATABASE_HOST: fizzy-mysql-primary - MYSQL_DATABASE_REPLICA_HOST: fizzy-mysql-replica - MYSQL_SOLID_CABLE_HOST: fizzy-mysql-primary - MYSQL_SOLID_QUEUE_HOST: fizzy-mysql-primary - secret: - - RAILS_MASTER_KEY - - MYSQL_ALTER_PASSWORD - - MYSQL_ALTER_USER - - MYSQL_APP_PASSWORD - - MYSQL_APP_USER - - MYSQL_READONLY_PASSWORD - - MYSQL_READONLY_USER - tags: - sc_chi: - MYSQL_SOLID_CACHE_HOST: fizzy-solidcache-db-01.sc-chi-int.37signals.com - df_iad: - MYSQL_SOLID_CACHE_HOST: fizzy-solidcache-db-101.df-iad-int.37signals.com - PRIMARY_DATACENTER: true - df_ams: - MYSQL_SOLID_CACHE_HOST: fizzy-solidcache-db-401.df-ams-int.37signals.com - - -accessories: - load-balancer: - image: basecamp/kamal-proxy:lb - hosts: - - fizzy-lb-101.df-iad-int.37signals.com - - fizzy-lb-102.df-iad-int.37signals.com - - fizzy-lb-01.sc-chi-int.37signals.com - - fizzy-lb-02.sc-chi-int.37signals.com - - fizzy-lb-401.df-ams-int.37signals.com - - fizzy-lb-402.df-ams-int.37signals.com - labels: - otel_role: load-balancer - otel_service: fizzy-load-balancer - otel_scrape_enabled: true - options: - publish: - - 80:80 - - 443:443 - # NFS mount for certificates - # See https://3.basecamp.com/2914079/buckets/37331921/todos/9180260061 - mount: type=volume,src=certificates,dst=/certificates,volume-driver=local,volume-opt=type=nfs,volume-opt=device=:/fizzy-production-certificates,"volume-opt=o=addr=purestorage.sc-chi-int.37signals.com,nfsvers=3,rw,noatime,nconnect=8,soft,timeo=30,retrans=2" - volumes: - - load-balancer:/home/kamal-proxy/.config/kamal-proxy diff --git a/gems/fizzy-saas/config/deploy.staging.yml b/gems/fizzy-saas/config/deploy.staging.yml deleted file mode 100644 index 3163c7a7b..000000000 --- a/gems/fizzy-saas/config/deploy.staging.yml +++ /dev/null @@ -1,69 +0,0 @@ -servers: - web: - hosts: - - fizzy-staging-app-101.df-iad-int.37signals.com: df_iad - - fizzy-staging-app-102.df-iad-int.37signals.com: df_iad - - fizzy-staging-app-01.sc-chi-int.37signals.com: sc_chi - - fizzy-staging-app-02.sc-chi-int.37signals.com: sc_chi - - fizzy-staging-app-401.df-ams-int.37signals.com: df_ams - - fizzy-staging-app-402.df-ams-int.37signals.com: df_ams - labels: - otel_scrape_enabled: true - jobs: - hosts: - - fizzy-staging-jobs-101.df-iad-int.37signals.com: df_iad - - fizzy-staging-jobs-102.df-iad-int.37signals.com: df_iad - labels: - otel_scrape_enabled: true - -proxy: - ssl: false - -ssh: - user: app - -env: - clear: - RAILS_ENV: staging - MYSQL_DATABASE_HOST: fizzy-staging-mysql-primary - MYSQL_DATABASE_REPLICA_HOST: fizzy-staging-mysql-replica - MYSQL_SOLID_CABLE_HOST: fizzy-staging-mysql-primary - MYSQL_SOLID_QUEUE_HOST: fizzy-staging-mysql-primary - secret: - - RAILS_MASTER_KEY - - MYSQL_ALTER_PASSWORD - - MYSQL_ALTER_USER - - MYSQL_APP_PASSWORD - - MYSQL_APP_USER - - MYSQL_READONLY_PASSWORD - - MYSQL_READONLY_USER - tags: - sc_chi: - MYSQL_SOLID_CACHE_HOST: fizzy-staging-solidcache-db-01.sc-chi-int.37signals.com - df_iad: - MYSQL_SOLID_CACHE_HOST: fizzy-staging-solidcache-db-101.df-iad-int.37signals.com - PRIMARY_DATACENTER: true - df_ams: - MYSQL_SOLID_CACHE_HOST: fizzy-staging-solidcache-db-401.df-ams-int.37signals.com - - -accessories: - load-balancer: - image: basecamp/kamal-proxy:lb - hosts: - - fizzy-staging-lb-01.sc-chi-int.37signals.com - - fizzy-staging-lb-101.df-iad-int.37signals.com - - fizzy-staging-lb-401.df-ams-int.37signals.com - labels: - otel_role: load-balancer - otel_service: fizzy-load-balancer - otel_scrape_enabled: true - options: - publish: - - 80:80 - - 443:443 - # NFS mount for certificates - # See https://3.basecamp.com/2914079/buckets/37331921/todos/9180260061 - mount: type=volume,src=certificates,dst=/certificates,volume-driver=local,volume-opt=type=nfs,volume-opt=device=:/fizzy-staging-certificates,"volume-opt=o=addr=purestorage.sc-chi-int.37signals.com,nfsvers=3,rw,noatime,nconnect=8,soft,timeo=30,retrans=2" - volumes: - - load-balancer:/home/kamal-proxy/.config/kamal-proxy diff --git a/gems/fizzy-saas/config/deploy.yml b/gems/fizzy-saas/config/deploy.yml deleted file mode 100644 index ea3ca3c49..000000000 --- a/gems/fizzy-saas/config/deploy.yml +++ /dev/null @@ -1,35 +0,0 @@ -service: fizzy -image: basecamp/fizzy -asset_path: /rails/public/assets -hooks_path: <%= File.join(Gem::Specification.find_by_name("fizzy-saas").gem_dir, ".kamal", "hooks") %> - -servers: - jobs: - cmd: bin/jobs - -volumes: - - fizzy:/rails/storage - -proxy: - ssl: true - -registry: - server: registry.37signals.com - username: robot$harbor-bot - password: - - BASECAMP_REGISTRY_PASSWORD - -builder: - arch: amd64 - secrets: - - GITHUB_TOKEN - remote: ssh://app@docker-builder-102 - local: <%= ENV.fetch("KAMAL_BUILDER_LOCAL", "true") %> - -env: - secret: - - RAILS_MASTER_KEY - -aliases: - console: app exec -i --reuse "bin/rails console" - ssh: app exec -i --reuse /bin/bash diff --git a/gems/fizzy-saas/config/routes.rb b/gems/fizzy-saas/config/routes.rb deleted file mode 100644 index 2b9639edb..000000000 --- a/gems/fizzy-saas/config/routes.rb +++ /dev/null @@ -1,9 +0,0 @@ -Fizzy::Saas::Engine.routes.draw do - get "/signup/new", to: redirect("/session/new") - - namespace :signup do - resource :completion, only: %i[ new create ] - end - - Queenbee.routes(self) -end diff --git a/gems/fizzy-saas/fizzy-saas.gemspec b/gems/fizzy-saas/fizzy-saas.gemspec deleted file mode 100644 index f1b28de00..000000000 --- a/gems/fizzy-saas/fizzy-saas.gemspec +++ /dev/null @@ -1,27 +0,0 @@ -require_relative "lib/fizzy/saas/version" - -Gem::Specification.new do |spec| - spec.name = "fizzy-saas" - spec.version = Fizzy::Saas::VERSION - spec.authors = [ "Mike Dalessio" ] - spec.email = [ "mike@37signals.com" ] - spec.homepage = "TODO" - spec.summary = "TODO: Summary of Fizzy::Saas." - spec.description = "TODO: Description of Fizzy::Saas." - - # Prevent pushing this gem to RubyGems.org. To allow pushes either set the "allowed_push_host" - # to allow pushing to a single host or delete this section to allow pushing to any host. - spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'" - - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here." - spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here." - - spec.files = Dir.chdir(File.expand_path(__dir__)) do - Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"] - end - - spec.add_dependency "rails", ">= 8.1.0.beta1" - spec.add_dependency "queenbee" - spec.add_dependency "rails_structured_logging" -end diff --git a/gems/fizzy-saas/lib/fizzy/saas.rb b/gems/fizzy-saas/lib/fizzy/saas.rb deleted file mode 100644 index dd0d35492..000000000 --- a/gems/fizzy-saas/lib/fizzy/saas.rb +++ /dev/null @@ -1,7 +0,0 @@ -require "fizzy/saas/version" -require "fizzy/saas/engine" - -module Fizzy - module Saas - end -end diff --git a/gems/fizzy-saas/lib/fizzy/saas/engine.rb b/gems/fizzy-saas/lib/fizzy/saas/engine.rb deleted file mode 100644 index 14ce03759..000000000 --- a/gems/fizzy-saas/lib/fizzy/saas/engine.rb +++ /dev/null @@ -1,31 +0,0 @@ -require_relative "metrics" -require_relative "transaction_pinning" - -module Fizzy - module Saas - class Engine < ::Rails::Engine - # moved from config/initializers/queenbee.rb - Queenbee.host_app = Fizzy - - initializer "fizzy_saas.transaction_pinning" do |app| - if ActiveRecord::Base.replica_configured? - app.config.middleware.insert_after( - ActiveRecord::Middleware::DatabaseSelector, - TransactionPinning::Middleware - ) - end - end - - config.to_prepare do - Queenbee::Subscription.short_names = Subscription::SHORT_NAMES - Queenbee::ApiToken.token = Rails.application.credentials.dig(:queenbee_api_token) - - Subscription::SHORT_NAMES.each do |short_name| - const_name = "#{short_name}Subscription" - ::Object.send(:remove_const, const_name) if ::Object.const_defined?(const_name) - ::Object.const_set const_name, Subscription.const_get(short_name, false) - end - end - end - end -end diff --git a/gems/fizzy-saas/lib/fizzy/saas/metrics.rb b/gems/fizzy-saas/lib/fizzy/saas/metrics.rb deleted file mode 100644 index 80a2bc194..000000000 --- a/gems/fizzy-saas/lib/fizzy/saas/metrics.rb +++ /dev/null @@ -1,13 +0,0 @@ -Yabeda.configure do - SHORT_HISTOGRAM_BUCKETS = [ 0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5 ] - - group :fizzy do - counter :replica_stale, - comment: "Number of requests served from a stale replica" - - histogram :replica_wait, - unit: :seconds, - comment: "Time spent waiting for replica to catch up with transaction", - buckets: SHORT_HISTOGRAM_BUCKETS - end -end diff --git a/gems/fizzy-saas/lib/fizzy/saas/transaction_pinning.rb b/gems/fizzy-saas/lib/fizzy/saas/transaction_pinning.rb deleted file mode 100644 index ed3cf2060..000000000 --- a/gems/fizzy-saas/lib/fizzy/saas/transaction_pinning.rb +++ /dev/null @@ -1,65 +0,0 @@ -module TransactionPinning - class Middleware - SESSION_KEY = :last_txn - DEFAULT_MAX_WAIT = 0.25 - - def initialize(app) - @app = app - @timeout = Rails.application.config.x.transaction_pinning&.timeout&.to_f || DEFAULT_MAX_WAIT - end - - def call(env) - request = ActionDispatch::Request.new(env) - replica_metrics = {} - - if ApplicationRecord.current_role == :reading - wait_for_replica_catchup(request, replica_metrics) - end - - status, headers, body = @app.call(env) - headers.merge!(replica_metrics.transform_values(&:to_s)) - - if ApplicationRecord.current_role == :writing - capture_transaction_id(request) - end - - [ status, headers, body ] - end - - private - def wait_for_replica_catchup(request, replica_metrics) - if last_txn = request.session[SESSION_KEY].presence - has_transaction = tracking_replica_wait_time(replica_metrics) do - replica_has_transaction(last_txn) - end - - unless has_transaction - Yabeda.fizzy.replica_stale.increment - replica_metrics["X-Replica-Stale"] = true - end - end - end - - def capture_transaction_id(request) - request.session[SESSION_KEY] = ApplicationRecord.connection.show_variable("global.gtid_executed") - end - - def replica_has_transaction(txn) - sql = ApplicationRecord.sanitize_sql_array([ "SELECT WAIT_FOR_EXECUTED_GTID_SET(?, ?)", txn, @timeout ]) - ApplicationRecord.connection.select_value(sql) == 0 - rescue => e - Sentry.capture_exception(e, extra: { gtid: txn }) - true # Treat as if we're up to date, since we don't know - end - - def tracking_replica_wait_time(replica_metrics) - started_at = Time.current - - Yabeda.fizzy.replica_wait.measure do - yield - end.tap do - replica_metrics["X-Replica-Wait"] = Time.current - started_at - end - end - end -end diff --git a/gems/fizzy-saas/lib/fizzy/saas/version.rb b/gems/fizzy-saas/lib/fizzy/saas/version.rb deleted file mode 100644 index 7a95d2d05..000000000 --- a/gems/fizzy-saas/lib/fizzy/saas/version.rb +++ /dev/null @@ -1,5 +0,0 @@ -module Fizzy - module Saas - VERSION = "0.1.0" - end -end diff --git a/gems/fizzy-saas/lib/tasks/fizzy/saas_tasks.rake b/gems/fizzy-saas/lib/tasks/fizzy/saas_tasks.rake deleted file mode 100644 index 8fe948d94..000000000 --- a/gems/fizzy-saas/lib/tasks/fizzy/saas_tasks.rake +++ /dev/null @@ -1,4 +0,0 @@ -# desc "Explaining what the task does" -# task :fizzy_saas do -# # Task goes here -# end diff --git a/gems/fizzy-saas/test/controllers/.keep b/gems/fizzy-saas/test/controllers/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/gems/fizzy-saas/test/controllers/signups/completions_controller_test.rb b/gems/fizzy-saas/test/controllers/signups/completions_controller_test.rb deleted file mode 100644 index 49628a188..000000000 --- a/gems/fizzy-saas/test/controllers/signups/completions_controller_test.rb +++ /dev/null @@ -1,43 +0,0 @@ -require "test_helper" - -class Signup::CompletionsControllerTest < ActionDispatch::IntegrationTest - setup do - @signup = Signup.new(email_address: "newuser@example.com", full_name: "New User") - - @signup.create_identity || raise("Failed to create identity") - - sign_in_as @signup.identity - end - - test "new" do - untenanted do - get saas.new_signup_completion_path - end - - assert_response :success - end - - test "create" do - untenanted do - post saas.signup_completion_path, params: { - signup: { - full_name: @signup.full_name - } - } - end - - assert_response :redirect, "Valid params should redirect" - end - - test "create with invalid params" do - untenanted do - post saas.signup_completion_path, params: { - signup: { - full_name: "" - } - } - end - - assert_response :unprocessable_entity, "Invalid params should return unprocessable entity" - end -end diff --git a/gems/fizzy-saas/test/fixtures/files/.keep b/gems/fizzy-saas/test/fixtures/files/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/gems/fizzy-saas/test/helpers/.keep b/gems/fizzy-saas/test/helpers/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/gems/fizzy-saas/test/integration/.keep b/gems/fizzy-saas/test/integration/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/gems/fizzy-saas/test/mailers/.keep b/gems/fizzy-saas/test/mailers/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/gems/fizzy-saas/test/models/.keep b/gems/fizzy-saas/test/models/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/gems/fizzy-saas/test/models/signup/account_name_generator_test.rb b/gems/fizzy-saas/test/models/signup/account_name_generator_test.rb deleted file mode 100644 index d22922b29..000000000 --- a/gems/fizzy-saas/test/models/signup/account_name_generator_test.rb +++ /dev/null @@ -1,61 +0,0 @@ -require "test_helper" - -class Signup::AccountNameGeneratorTest < ActiveSupport::TestCase - setup do - @identity = Identity.create!(email_address: "newart.userbaum@example.com") - @name = "Newart userbaum" - @generator = Signup::AccountNameGenerator.new(identity: @identity, name: @name) - end - - test "generate" do - account_name = @generator.generate - assert_equal "Newart's Fizzy", account_name, "The 1st account doesn't have 1st in the name" - - first_account = Account.create!(external_account_id: "1st", name: account_name) - Current.without_account do - @identity.users.create!(account: first_account, name: @name) - @identity.reload - end - - account_name = @generator.generate - assert_equal "Newart's 2nd Fizzy", account_name - - second_account = Account.create!(external_account_id: "2nd", name: account_name) - Current.without_account do - @identity.users.create!(account: second_account, name: @name) - @identity.reload - end - - account_name = @generator.generate - assert_equal "Newart's 3rd Fizzy", account_name - - third_account = Account.create!(external_account_id: "3rd", name: account_name) - Current.without_account do - @identity.users.create!(account: third_account, name: @name) - @identity.reload - end - - account_name = @generator.generate - assert_equal "Newart's 4th Fizzy", account_name - - fourth_account = Account.create!(external_account_id: "4th", name: account_name) - Current.without_account do - @identity.users.create!(account: fourth_account, name: @name) - @identity.reload - end - - account_name = @generator.generate - assert_equal "Newart's 5th Fizzy", account_name - end - - test "generate continues from the previous highest index" do - account = Account.create!(external_account_id: "12th", name: "Newart's 12th Fizzy") - Current.without_account do - @identity.users.create!(account: account, name: @name) - @identity.reload - end - - account_name = @generator.generate - assert_equal "Newart's 13th Fizzy", account_name - end -end diff --git a/gems/fizzy-saas/test/models/signup_test.rb b/gems/fizzy-saas/test/models/signup_test.rb deleted file mode 100644 index 69c0e699f..000000000 --- a/gems/fizzy-saas/test/models/signup_test.rb +++ /dev/null @@ -1,53 +0,0 @@ -require "test_helper" - -class SignupTest < ActiveSupport::TestCase - test "#create_identity" do - signup = Signup.new(email_address: "brian@example.com") - - assert_difference -> { Identity.count }, 1 do - assert_difference -> { MagicLink.count }, 1 do - assert signup.create_identity - end - end - - assert_empty signup.errors - assert signup.identity - assert signup.identity.persisted? - - signup_existing = Signup.new(email_address: "brian@example.com") - - assert_no_difference -> { Identity.count } do - assert_difference -> { MagicLink.count }, 1 do - assert signup_existing.create_identity, "Should send magic link for existing identity" - end - end - - signup_invalid = Signup.new(email_address: "") - assert_raises do - signup_invalid.create_identity - end - end - - test "#complete" do - Account.any_instance.expects(:setup_customer_template).once - Current.without_account do - signup = Signup.new( - full_name: "Kevin", - identity: identities(:kevin) - ) - - assert signup.complete - - assert signup.account - assert signup.user - assert_equal "Kevin", signup.user.name - - signup_invalid = Signup.new( - full_name: "", - identity: identities(:kevin) - ) - assert_not signup_invalid.complete - assert_not_empty signup_invalid.errors[:full_name] - end - end -end diff --git a/gems/fizzy-saas/test/test_helper.rb b/gems/fizzy-saas/test/test_helper.rb deleted file mode 100644 index eeaf24954..000000000 --- a/gems/fizzy-saas/test/test_helper.rb +++ /dev/null @@ -1,9 +0,0 @@ -require "queenbee/testing/mocks" - -Queenbee::Remote::Account.class_eval do - # because we use the account ID as the tenant name, we need it to be unique in each test to avoid - # parallelized tests clobbering each other. - def next_id - super + Random.rand(1000000) - end -end