diff --git a/CHANGELOG.md b/CHANGELOG.md index fac957f3..fccb46ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # `tailwindcss-rails` Changelog +## main (unreleased) + +### Improved + +* Setting the `TAILWINDCSS_SKIP_BUILD` environment variable to a non-blank value skips attaching `tailwindcss:build` to `assets:precompile` (and test prepare). This is useful when the CSS is pre-built/committed, when caching CI or Docker layers, or for cross-architecture Docker builds. @cgmoore120 + + ## v4.6.0 / 2026-06-17 ### Fixed diff --git a/README.md b/README.md index e3e3b97d..b080c2bb 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ README](https://github.com/rails/tailwindcss-rails/tree/v3-stable?tab=readme-ov- * [Configuration and commands](#configuration-and-commands) * [Building for production](#building-for-production) * [Building for testing](#building-for-testing) + * [Skipping the automatic build](#skipping-the-automatic-build) * [Building unminified assets](#building-unminified-assets) * [Live rebuild](#live-rebuild) * [Using Tailwind plugins](#using-tailwind-plugins) @@ -288,6 +289,10 @@ The `tailwindcss:build` is automatically attached to `assets:precompile`, so bef The `tailwindcss:build` task is automatically attached to the `test:prepare` Rake task. This task runs before test commands. If you run `bin/rails test` in your CI environment, your Tailwind output will be generated before tests run. +### Skipping the automatic build + +Setting the `TAILWINDCSS_SKIP_BUILD` environment variable to any non-blank value skips the automatic `tailwindcss:build` that is otherwise attached to `assets:precompile` (and to test prepare). This is useful when the CSS is already built and committed, when you want to cache the build across CI or Docker layers, or for cross-architecture Docker builds where the standalone CLI may not produce correct output. The default behavior is unchanged when the variable is unset or blank. + ### Building unminified assets If you want unminified assets, you can: diff --git a/lib/tasks/build.rake b/lib/tasks/build.rake index d07f80a8..8dd65a2e 100644 --- a/lib/tasks/build.rake +++ b/lib/tasks/build.rake @@ -33,12 +33,14 @@ namespace :tailwindcss do end end -Rake::Task["assets:precompile"].enhance(["tailwindcss:build"]) - -if Rake::Task.task_defined?("test:prepare") - Rake::Task["test:prepare"].enhance(["tailwindcss:build"]) -elsif Rake::Task.task_defined?("spec:prepare") - Rake::Task["spec:prepare"].enhance(["tailwindcss:build"]) -elsif Rake::Task.task_defined?("db:test:prepare") - Rake::Task["db:test:prepare"].enhance(["tailwindcss:build"]) +unless ENV["TAILWINDCSS_SKIP_BUILD"].present? + Rake::Task["assets:precompile"].enhance(["tailwindcss:build"]) + + if Rake::Task.task_defined?("test:prepare") + Rake::Task["test:prepare"].enhance(["tailwindcss:build"]) + elsif Rake::Task.task_defined?("spec:prepare") + Rake::Task["spec:prepare"].enhance(["tailwindcss:build"]) + elsif Rake::Task.task_defined?("db:test:prepare") + Rake::Task["db:test:prepare"].enhance(["tailwindcss:build"]) + end end diff --git a/test/lib/tasks/build_test.rb b/test/lib/tasks/build_test.rb new file mode 100644 index 00000000..8bc002ca --- /dev/null +++ b/test/lib/tasks/build_test.rb @@ -0,0 +1,54 @@ +require "test_helper" + +class BuildRakeTest < ActiveSupport::TestCase + BUILD_RAKE = File.expand_path("../../../../lib/tasks/build.rake", __FILE__) + + # Rake tasks are global singletons, so we can't load build.rake into the test + # process and inspect prerequisites without polluting other tests (and we'd + # only ever see one value of the env var per process). Instead we shell out to + # a fresh Ruby process that stubs the tasks build.rake expects to already + # exist, loads build.rake, and prints the resulting prerequisites. + def prerequisites_for(env: {}) + script = <<~RUBY + require "bundler/setup" + require "rake" + require "active_support/all" + + Rake::Task.define_task("environment") + Rake::Task.define_task("assets:precompile") + Rake::Task.define_task("test:prepare") + + load #{BUILD_RAKE.inspect} + + puts Rake::Task["assets:precompile"].prerequisites.inspect + puts Rake::Task["test:prepare"].prerequisites.inspect + RUBY + + output = IO.popen(env, [Gem.ruby, "-e", script], &:read) + assert $?.success?, "subprocess failed:\n#{output}" + + assets_precompile, test_prepare = output.lines.map { |line| eval(line) } # rubocop:disable Security/Eval + { "assets:precompile" => assets_precompile, "test:prepare" => test_prepare } + end + + test "tailwindcss:build is attached to assets:precompile and test:prepare by default" do + prerequisites = prerequisites_for(env: {}) + + assert_includes prerequisites["assets:precompile"], "tailwindcss:build" + assert_includes prerequisites["test:prepare"], "tailwindcss:build" + end + + test "TAILWINDCSS_SKIP_BUILD skips attaching tailwindcss:build" do + prerequisites = prerequisites_for(env: { "TAILWINDCSS_SKIP_BUILD" => "1" }) + + refute_includes prerequisites["assets:precompile"], "tailwindcss:build" + refute_includes prerequisites["test:prepare"], "tailwindcss:build" + end + + test "a blank TAILWINDCSS_SKIP_BUILD does not skip the build" do + prerequisites = prerequisites_for(env: { "TAILWINDCSS_SKIP_BUILD" => "" }) + + assert_includes prerequisites["assets:precompile"], "tailwindcss:build" + assert_includes prerequisites["test:prepare"], "tailwindcss:build" + end +end