Files
gitlab-foss/bin/spring
2025-04-14 06:12:00 +00:00

98 lines
4.4 KiB
Ruby
Executable File

#!/usr/bin/env ruby
#################################
# BEGIN GITLAB MODIFICATIONS
#
# EXPLANATION OF GITLAB'S CUSTOM LOGIC FOR ENABLING/DISABLING SPRING:
#
# For legacy reasons which do not have any known associated GitLab issues
# (https://gitlab.com/gitlab-org/gitlab/-/merge_requests/180842#note_2355236713),
# but are related to deadlocks (https://github.com/rails/spring/issues/731),
# GitLab wants to require the usage of the Spring pre-loaded to be "opt-in".
#
# This behavior was introduced via a custom `ENABLE_SPRING` environment variable in this MR:
# https://gitlab.com/gitlab-org/gitlab/-/commit/7b523eb1a144fe87e4ce12c3a611b5648ebd93cb
#
# However, the default contract for Spring is to be automatically enabled
# whenever a spring-enabled `bin/*` binstub is invoked (e.g. `bin/rspec`), unless
# the DISABLE_SPRING environment variable is set and contains a non-nil/non-empty/non-"0" value
#
# This can lead to unexpected behavior for contributors who are used to the default behavior of
# Rails and Spring, where it is always used when a binstub is invoked.
#
# It can also cause difficulties in environments such as RubyMine, which (as of 2025) relies on the
# contract of `bin/rspec` to be respected, and it is tedious and error-prone to require that
# the `ENABLE_SPRING` environment variable be set on every test run configuration (even if you set
# it on the default RubyMine RSpec configuration template, it will often get unset/lost).
#
# And finally, in the GitLab codebase as of 2025, with millions of lines of Ruby code,
# using Spring reduces the time for each individual test run by ~15 seconds or more.
# So, it can be a big win for developer productivity to enable it when possible.
#
# Thus, as a compromise, we will still default to NOT using Spring
# even when binstubs are called, but we WILL attempt to automatically use
# it in cases where it is _likely_ that it is desired.
#
# These cases include:
# 1. When the `bin/spring` binstub was directly invoked (File.basename($0) == "spring")
# 2. When the `ENABLE_SPRING` environment variable is explicitly set to a "truthy" value,
# 3. When the `SPRING_TMP_PATH` environment variable is set, which can be used as an indicator
# that RubyMine is being used, since RubyMine always sets this variable
# 4. When the standard `DISABLE_SPRING` environment variable is "0"
# (this is the only non-nil/non-empty value that Spring itself considers to be "enabled")
#
# An exception will be raised if both the GitLab custom `ENABLE_SPRING` and the
# standard `DISABLE_SPRING` environment variables are set.
#
#################################
if ENV["ENABLE_SPRING"] && ENV["DISABLE_SPRING"]
raise "ERROR: Do not set both ENABLE_SPRING and DISABLE_SPRING environment variables, " \
"as they are mutually exclusive. Please set only one or the other."
end
if ENV["ENABLE_SPRING"]
# convert ENABLE_SPRING to DISABLE_SPRING
ENV["DISABLE_SPRING"] = (ENV["ENABLE_SPRING"] =~ /^(true|t|yes|y|1|on)$/i) ? "0" : "1"
elsif !ENV["DISABLE_SPRING"] && ENV["SPRING_TMP_PATH"]
# Enable spring if the SPRING_TMP_PATH is enabled, and DISABLE_SPRING is not set
# Spring is requested by ex. RubyMine
ENV["DISABLE_SPRING"] = "0"
elsif !ENV["DISABLE_SPRING"]
# Retain old behavior, making spring disabled by default
ENV["DISABLE_SPRING"] = "1"
end
#################################
# END GITLAB MODIFICATIONS
#################################
# This file loads Spring without using loading other gems in the Gemfile, in order to be fast.
# It gets overwritten when you run the `spring binstub` command.
if !defined?(Spring) && [nil, "development", "test"].include?(ENV["RAILS_ENV"])
require "bundler"
Bundler.locked_gems.specs.find { |spec| spec.name == "spring" }&.tap do |spring|
Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path
#################################
# BEGIN GITLAB MODIFICATIONS
#
# This rescue was added to gracefully handle if the spring gem is not installed.
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106659
#################################
begin
gem "spring", spring.version
require "spring/binstub"
rescue Gem::MissingSpecError
$stderr.puts "The bin/spring binstub was invoked, but the spring gem is not installed.\n"
$stderr.puts "Run `bundle install` to install the missing spring gem."
end
#################################
# END GITLAB MODIFICATIONS
#################################
end
end