Skip to content

Commit 1d4fa44

Browse files
committed
feat: package tailwindcss binary executables with the gem
See rakelib/package.rake for details.
1 parent 777e1d2 commit 1d4fa44

File tree

5 files changed

+138
-4
lines changed

5 files changed

+138
-4
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@
1212
.byebug_history
1313
*.gem
1414
.idea/
15-
**/tmp/
15+
**/tmp/
16+
/exe/*/tailwindcss-*

bin/release

+6-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ git commit -m "Bump version for $VERSION"
1414
git push
1515
git tag v$VERSION
1616
git push --tags
17-
gem build tailwindcss-rails.gemspec
18-
gem push "tailwindcss-rails-$VERSION.gem" --host https://rubygems.org
19-
rm "tailwindcss-rails-$VERSION.gem"
17+
18+
rake package
19+
for gem in pkg/tailwindcss-rails-$VERSION*.gem ; do
20+
gem push "$gem" --host https://rubygems.org
21+
rm "$gem"
22+
done

exe/tailwindcss

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#! /usr/bin/env ruby
2+
# because rubygems shims assume a gem's executables are Ruby
3+
4+
require "shellwords"
5+
6+
platform = Gem::Platform.local.to_s
7+
exe_path = Dir.glob(File.join(__dir__, platform, "tailwindcss*"))
8+
9+
if exe_path.empty?
10+
raise "Cannot find the tailwindcss executable for #{platform} in #{__dir__}"
11+
end
12+
13+
exec(Shellwords.join([exe_path, ARGV].flatten))

rakelib/package.rake

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# coding: utf-8
2+
#
3+
# Rake tasks to manage native gem packages with binary executables from tailwindlabs/tailwindcss
4+
#
5+
# TL;DR: run "rake package"
6+
#
7+
# The native platform gems (defined by TAILWINDCSS_NATIVE_PLATFORMS below) will each contain two
8+
# files in addition to what the vanilla ruby gem contains:
9+
#
10+
# exe/
11+
# ├── tailwindcss # generic ruby script to find and run the binary
12+
# └── <Gem::Platform architecture name>/
13+
# └── tailwindcss-<platform extension> # the tailwindcss binary executable
14+
#
15+
# The ruby script `exe/tailwindcss` is installed into the user's path, and it simply locates the
16+
# binary and executes it. Note that this script is required because rubygems requires that
17+
# executables declared in a gemspec must be Ruby scripts.
18+
#
19+
# As a concrete example, an x86_64-linux system will see these files on disk after installing
20+
# tailwindcss-rails-1.x.x-x86_64-linux.gem:
21+
#
22+
# exe/
23+
# ├── tailwindcss
24+
# └── x86_64-linux/
25+
# └── tailwindcss-linux-x64
26+
#
27+
# So the full set of gem files created will be:
28+
#
29+
# - pkg/tailwindcss-rails-1.0.0.gem
30+
# - pkg/tailwindcss-rails-1.0.0-arm64-darwin.gem
31+
# - pkg/tailwindcss-rails-1.0.0-x64-mingw32.gem
32+
# - pkg/tailwindcss-rails-1.0.0-x86_64-darwin.gem
33+
# - pkg/tailwindcss-rails-1.0.0-x86_64-linux.gem
34+
#
35+
# Note that in addition to the native gems, a vanilla "ruby" gem will also be created without
36+
# either the `exe/tailwindcss` script or a binary executable present.
37+
#
38+
#
39+
# New rake tasks created:
40+
#
41+
# - rake gem:ruby # Build the ruby gem
42+
# - rake gem:arm64-darwin # Build the arm64-darwin gem
43+
# - rake gem:x64-mingw32 # Build the x64-mingw32 gem
44+
# - rake gem:x86_64-darwin # Build the x86_64-darwin gem
45+
# - rake gem:x86_64-linux # Build the x86_64-linux gem
46+
# - rake download # Download all tailwindcss binaries
47+
#
48+
# Modified rake tasks:
49+
#
50+
# - rake gem # Build all the gem files
51+
# - rake package # Build all the gem files (same as `gem`)
52+
# - rake repackage # Force a rebuild of all the gem files
53+
#
54+
# Note also that the binary executables will be lazily downloaded when needed, but you can
55+
# explicitly download them with the `rake download` command.
56+
#
57+
require "rubygems/package_task"
58+
require "open-uri"
59+
60+
TAILWINDCSS_VERSION = "v3.0.5" # string used to generate the download URL
61+
62+
# rubygems platform name => upstream release filename
63+
TAILWINDCSS_NATIVE_PLATFORMS = {
64+
"arm64-darwin" => "tailwindcss-macos-x64",
65+
"x64-mingw32" => "tailwindcss-windows-x64.exe",
66+
"x86_64-darwin" => "tailwindcss-macos-arm64",
67+
"x86_64-linux" => "tailwindcss-linux-x64",
68+
}
69+
70+
def tailwindcss_download_url(filename)
71+
"https://github.com/tailwindlabs/tailwindcss/releases/download/#{TAILWINDCSS_VERSION}/#{filename}"
72+
end
73+
74+
TAILWINDCSS_RAILS_GEMSPEC = Bundler.load_gemspec("tailwindcss-rails.gemspec")
75+
76+
gem_path = Gem::PackageTask.new(TAILWINDCSS_RAILS_GEMSPEC).define
77+
desc "Build the ruby gem"
78+
task "gem:ruby" => [gem_path]
79+
80+
exepaths = []
81+
TAILWINDCSS_NATIVE_PLATFORMS.each do |platform, filename|
82+
TAILWINDCSS_RAILS_GEMSPEC.dup.tap do |gemspec|
83+
exedir = File.join(gemspec.bindir, platform) # "exe/x86_64-linux"
84+
exepath = File.join(exedir, filename) # "exe/x86_64-linux/tailwindcss-linux-x64"
85+
exepaths << exepath
86+
87+
# modify a copy of the gemspec to include the native executable
88+
gemspec.platform = platform
89+
gemspec.executables << "tailwindcss"
90+
gemspec.files << exepath
91+
92+
# create a package task
93+
gem_path = Gem::PackageTask.new(gemspec).define
94+
desc "Build the #{platform} gem"
95+
task "gem:#{platform}" => [gem_path]
96+
97+
directory exedir
98+
file exepath => [exedir] do
99+
release_url = tailwindcss_download_url(filename)
100+
warn "Downloading #{exepath} from #{release_url} ..."
101+
102+
# lazy, but fine for now.
103+
URI.open(release_url) do |remote|
104+
File.open(exepath, "wb") do |local|
105+
local.write(remote.read)
106+
end
107+
end
108+
FileUtils.chmod(0755, exepath, verbose: true)
109+
end
110+
end
111+
end
112+
113+
desc "Download all tailwindcss binaries"
114+
task "download" => exepaths
115+
116+
CLOBBER.add(exepaths.map { |p| File.dirname(p) })

tailwindcss-rails.gemspec

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Gem::Specification.new do |spec|
1515
}
1616

1717
spec.files = Dir["{app,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"]
18+
spec.bindir = "exe"
1819

1920
spec.add_dependency "railties", ">= 6.0.0"
2021
end

0 commit comments

Comments
 (0)