docs-kit 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +36 -2
- data/lib/docs_kit/templates/new_site.rb +11 -40
- data/lib/docs_kit/version.rb +1 -1
- data/lib/generators/docs_kit/install/install_generator.rb +94 -0
- data/lib/generators/docs_kit/install/sync_report.rb +28 -2
- data/lib/generators/docs_kit/install/templates/Dockerfile.tt +96 -0
- data/lib/generators/docs_kit/install/templates/dockerignore +57 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4ede4d90b3f6ca240a59c5f13d14967a29cf8a806fa041a3c7edfe65adf1ed2c
|
|
4
|
+
data.tar.gz: 015f6f05b3d3b09581679810ae41b3486c2428dc219d2d47f32775a40b449759
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2b315f74f9de60f0e02354b3e8e093a85d06c99dc6bc8e9d1f96ad9ac0abc0bf7fe0d5db37f716b68e1fac2daabcafae1bd69b5c22cf587d7068cfc3b27c3050
|
|
7
|
+
data.tar.gz: f7868334e630ce1ab3ec99c9fbcfd91fbb6302c0f999c4b87dfc1c04959cbd8aac7cfecb49623ba2e4f2557665dcd844439f1d69211c97d5baa2ba55ad7efd6e
|
data/README.md
CHANGED
|
@@ -92,6 +92,39 @@ generators:
|
|
|
92
92
|
| `ApplicationController#render_page` defined by hand | `DocsKit::Controller#render_page` is included (the generator injects `include DocsKit::Controller`) | Delete the method — keep the `include`. |
|
|
93
93
|
| `app/helpers/icon_helper.rb` | docs-kit renders icons via rails_icons (`DocsUI::Icon`) | Delete the file. |
|
|
94
94
|
| Hand-pinned docs-kit lines in `config/importmap.rb` | the engine auto-pins the `docs-nav` controller and its assets | Delete the manual `pin`/`pin_all_from` lines for docs-kit. |
|
|
95
|
+
| `Dockerfile` stamped by an older docs-kit (`# docs-kit Dockerfile vX.Y.Z`) | docs-kit ships an optimized, multi-stage Dockerfile; a stale copy misses image-size wins | Diff yours against the current template (`lib/generators/docs_kit/install/templates/Dockerfile.tt` in the gem), adopt the changes or replace it. See [Upgrading your Dockerfile](#upgrading-your-dockerfile). |
|
|
96
|
+
|
|
97
|
+
### Upgrading your Dockerfile
|
|
98
|
+
|
|
99
|
+
The generator ships two Docker files:
|
|
100
|
+
|
|
101
|
+
- **`.dockerignore`** is gem-owned — every `docs_kit:install` (or `--sync`) run
|
|
102
|
+
**refreshes** it, so you always get the current build-context excludes
|
|
103
|
+
(`node_modules`, `.git`, `log`, `tmp`, `spec`, `coverage`, …). It carries no
|
|
104
|
+
site-specific content, so overwriting it is safe.
|
|
105
|
+
- **`Dockerfile`** is site-owned — the generator **never clobbers** it (you tune
|
|
106
|
+
packages, the `CMD`, extra build steps). Instead it stamps a version marker
|
|
107
|
+
(`# docs-kit Dockerfile v<VERSION>`) so `--sync` can tell you when yours is
|
|
108
|
+
stale relative to the gem's current template.
|
|
109
|
+
|
|
110
|
+
When the site bundles `thruster` (a Rails 8 default), the generated Dockerfile
|
|
111
|
+
fronts Puma with Thruster (`CMD ["./bin/thrust", "./bin/rails", "server"]`) for
|
|
112
|
+
HTTP caching, compression, and X-Sendfile — and the generator scaffolds the
|
|
113
|
+
`bin/thrust` binstub if the app lacks one, since the exec-form CMD needs the
|
|
114
|
+
file to exist in the image. Thruster listens on the routed port
|
|
115
|
+
(`HTTP_PORT=3000` — Kamal's `app_port`) and proxies to Puma on `TARGET_PORT=3001`.
|
|
116
|
+
Without thruster in the *production* bundle (absent, or only in a
|
|
117
|
+
development/test group that `BUNDLE_WITHOUT` excludes) the CMD falls back to
|
|
118
|
+
plain `rails server` — never a thrust CMD that would crash at boot.
|
|
119
|
+
|
|
120
|
+
When `--sync` reports your Dockerfile is behind, compare it against the shipped
|
|
121
|
+
template and pull in the improvements (or replace it wholesale if you never
|
|
122
|
+
customized it):
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
# The template path is printed by the generator; it lives in the installed gem:
|
|
126
|
+
diff Dockerfile "$(bundle show docs-kit)/lib/generators/docs_kit/install/templates/Dockerfile.tt"
|
|
127
|
+
```
|
|
95
128
|
|
|
96
129
|
## Configure (per site)
|
|
97
130
|
|
|
@@ -751,8 +784,9 @@ and applies docs-kit's application template, which:
|
|
|
751
784
|
- runs `rails g docs_kit:install` (initializers, controllers, a Doc registry, a
|
|
752
785
|
sample guide page, the Bun/Tailwind build, the docs-nav Stimulus wiring),
|
|
753
786
|
- syncs the lucide icons and builds the CSS,
|
|
754
|
-
- scaffolds Kamal (`config/deploy.yml`, `.kamal/secrets`,
|
|
755
|
-
|
|
787
|
+
- scaffolds Kamal (`config/deploy.yml`, `.kamal/secrets`, an optimized
|
|
788
|
+
multi-stage `Dockerfile` + a `.dockerignore`) and a thin
|
|
789
|
+
`.github/workflows/deploy-docs.yml` that calls the reusable workflow.
|
|
756
790
|
|
|
757
791
|
Then `cd my-docs && bin/dev`. Already have a Rails app? Run the install generator
|
|
758
792
|
instead:
|
|
@@ -4,7 +4,10 @@ require "securerandom"
|
|
|
4
4
|
|
|
5
5
|
# Rails application template for a docs-kit docs site. Run via:
|
|
6
6
|
#
|
|
7
|
-
# rails new my-docs
|
|
7
|
+
# rails new my-docs -a propshaft -j importmap --skip-... -m new_site.rb
|
|
8
|
+
#
|
|
9
|
+
# (NOT --minimal — that strips JS the shell needs AND the thruster gem the
|
|
10
|
+
# generated Dockerfile fronts Puma with; exe/docs-kit passes the right flags.)
|
|
8
11
|
#
|
|
9
12
|
# or, more simply, via the `docs-kit new` CLI (exe/docs-kit) which supplies the
|
|
10
13
|
# right `rails new` flags. It:
|
|
@@ -101,45 +104,13 @@ after_bundle do
|
|
|
101
104
|
KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD
|
|
102
105
|
SH
|
|
103
106
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
ENV PATH="/usr/local/bun/bin:$PATH"
|
|
112
|
-
WORKDIR /rails
|
|
113
|
-
ENV BUNDLE_WITHOUT="development:test" RAILS_ENV="production"
|
|
114
|
-
|
|
115
|
-
RUN apt-get update -qq && \\
|
|
116
|
-
apt-get install --no-install-recommends -y curl libjemalloc2 && \\
|
|
117
|
-
rm -rf /var/lib/apt/lists /var/cache/apt/archives
|
|
118
|
-
RUN gem update --system --no-document && gem install -N bundler
|
|
119
|
-
|
|
120
|
-
FROM base AS build
|
|
121
|
-
RUN apt-get update -qq && \\
|
|
122
|
-
apt-get install --no-install-recommends -y build-essential git libyaml-dev pkg-config unzip
|
|
123
|
-
RUN curl -fsSL https://bun.sh/install | bash -s "bun-v${BUN_VERSION}"
|
|
124
|
-
COPY Gemfile Gemfile.lock ./
|
|
125
|
-
RUN bundle install && rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache
|
|
126
|
-
COPY . .
|
|
127
|
-
RUN bun install --frozen-lockfile
|
|
128
|
-
# assets:precompile runs bun run build:css via the css:build rake enhance.
|
|
129
|
-
RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
|
|
130
|
-
|
|
131
|
-
FROM base
|
|
132
|
-
# Kamal verifies this label on --skip-push deploy; must equal `service:`.
|
|
133
|
-
LABEL service="#{service}"
|
|
134
|
-
COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
|
|
135
|
-
COPY --from=build /rails /rails
|
|
136
|
-
RUN groupadd --system --gid 1000 rails && \\
|
|
137
|
-
useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash && \\
|
|
138
|
-
chown -R 1000:1000 /rails/log /rails/tmp
|
|
139
|
-
USER 1000:1000
|
|
140
|
-
EXPOSE 3000
|
|
141
|
-
CMD ["./bin/rails", "server", "-b", "0.0.0.0"]
|
|
142
|
-
DOCKER
|
|
107
|
+
# The Dockerfile + .dockerignore are written by `docs_kit:install` (run above in
|
|
108
|
+
# after_bundle) so a scaffolded site and an upgrading site share ONE optimized,
|
|
109
|
+
# version-stamped Dockerfile — no divergent copy to maintain here. The generator
|
|
110
|
+
# derives the LABEL service from the app dir basename (= app_name); if the site
|
|
111
|
+
# deploys under a DIFFERENT Kamal service (`--service`), correct the label to
|
|
112
|
+
# match config/deploy.yml so Kamal's --skip-push validate_image passes.
|
|
113
|
+
gsub_file "Dockerfile", /LABEL service=".*"/, %(LABEL service="#{service}") if service != app_name
|
|
143
114
|
|
|
144
115
|
create_file ".github/workflows/deploy-docs.yml", <<~YAML
|
|
145
116
|
name: Deploy docs
|
data/lib/docs_kit/version.rb
CHANGED
|
@@ -4,6 +4,7 @@ require "erb"
|
|
|
4
4
|
require "yaml"
|
|
5
5
|
require "rails/generators/base"
|
|
6
6
|
require_relative "sync_report"
|
|
7
|
+
require_relative "../../../docs_kit/version"
|
|
7
8
|
|
|
8
9
|
module DocsKit
|
|
9
10
|
module Generators
|
|
@@ -178,6 +179,49 @@ module DocsKit
|
|
|
178
179
|
template "docs_kit_og.rake", "lib/tasks/docs_kit_og.rake"
|
|
179
180
|
end
|
|
180
181
|
|
|
182
|
+
# The production Dockerfile — a lean multi-stage build for a standalone
|
|
183
|
+
# docs site. Site-customizable (a site tunes packages/CMD), so skip when it
|
|
184
|
+
# exists and point an upgrader at the current template for a manual diff.
|
|
185
|
+
# The template stamps a `# docs-kit Dockerfile vX.Y.Z` marker so a `--sync`
|
|
186
|
+
# upgrade (SyncReport) can flag a stale copy. (create_initializer follows
|
|
187
|
+
# this same skip-if-exists + template-hint pattern.)
|
|
188
|
+
def create_dockerfile
|
|
189
|
+
dockerfile = "Dockerfile"
|
|
190
|
+
if File.exist?(File.join(destination_root, dockerfile))
|
|
191
|
+
template_path = File.join(self.class.source_root, "Dockerfile.tt")
|
|
192
|
+
return say_status(:skip, "#{dockerfile} exists — compare with #{template_path} if upgrading", :blue)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
template "Dockerfile.tt", dockerfile
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# The .dockerignore — gem-owned build-context trimming (node_modules, .git,
|
|
199
|
+
# logs, specs, coverage). Refreshed on every run (like create_og_task): it
|
|
200
|
+
# carries no site-specific content, so a re-run always ships the current
|
|
201
|
+
# excludes rather than fossilizing an old list.
|
|
202
|
+
def create_dockerignore
|
|
203
|
+
copy_file "dockerignore", ".dockerignore", force: true
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# When the site bundles thruster but lacks the binstub, create it — the
|
|
207
|
+
# Dockerfile's exec-form `CMD ["./bin/thrust", ...]` needs the file to EXIST
|
|
208
|
+
# in the image (`bundle install` installs the gem, not app binstubs, and
|
|
209
|
+
# `COPY . .` can't ship a file the repo doesn't have). Without this, the
|
|
210
|
+
# image builds green and the container crashes at boot. Skip-if-exists: a
|
|
211
|
+
# hand-tuned binstub is never touched.
|
|
212
|
+
def create_thrust_binstub
|
|
213
|
+
return unless gemfile_bundles_thruster? && !thrust_binstub?
|
|
214
|
+
|
|
215
|
+
create_file "bin/thrust", <<~RUBY
|
|
216
|
+
#!/usr/bin/env ruby
|
|
217
|
+
require "rubygems"
|
|
218
|
+
require "bundler/setup"
|
|
219
|
+
|
|
220
|
+
load Gem.bin_path("thruster", "thrust")
|
|
221
|
+
RUBY
|
|
222
|
+
chmod "bin/thrust", 0o755
|
|
223
|
+
end
|
|
224
|
+
|
|
181
225
|
def wire_assets_and_package_json
|
|
182
226
|
# Serve the bun-built CSS from app/assets/builds.
|
|
183
227
|
inject_into_file "config/initializers/assets.rb",
|
|
@@ -452,6 +496,56 @@ module DocsKit
|
|
|
452
496
|
name = defined?(Rails) && Rails.respond_to?(:application) && Rails.application&.class&.module_parent_name
|
|
453
497
|
(name || File.basename(destination_root)).to_s.underscore.humanize
|
|
454
498
|
end
|
|
499
|
+
|
|
500
|
+
# The Kamal `service` name stamped as the Dockerfile's LABEL — the app dir
|
|
501
|
+
# basename (a docs site's repo name), matching the `docs-kit new` default.
|
|
502
|
+
# Used in Dockerfile.tt via <%= docker_service %>.
|
|
503
|
+
def docker_service
|
|
504
|
+
File.basename(destination_root)
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
# The RUBY_VERSION build ARG default: the host's running Ruby (X.Y.Z), so a
|
|
508
|
+
# site's image matches its dev Ruby. Used in Dockerfile.tt.
|
|
509
|
+
def ruby_version_arg
|
|
510
|
+
RUBY_VERSION[/\d+\.\d+\.\d+/] || "3.4.2"
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
# True when the site bundles Thruster (HTTP caching + compression +
|
|
514
|
+
# X-Sendfile in front of Puma) — a Rails 8 `rails new` ships bin/thrust +
|
|
515
|
+
# the gem, but docs_kit:install also runs on older apps where a thrust CMD
|
|
516
|
+
# would crash the container at boot (Gem.bin_path raises). Decides which
|
|
517
|
+
# CMD Dockerfile.tt emits. A committed binstub is authoritative; otherwise
|
|
518
|
+
# the Gemfile decides (and create_thrust_binstub scaffolds the binstub).
|
|
519
|
+
def thruster?
|
|
520
|
+
thrust_binstub? || gemfile_bundles_thruster?
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
def thrust_binstub?
|
|
524
|
+
File.exist?(File.join(destination_root, "bin/thrust"))
|
|
525
|
+
end
|
|
526
|
+
|
|
527
|
+
# True when the Gemfile declares thruster where the PRODUCTION bundle sees
|
|
528
|
+
# it. The Dockerfile sets BUNDLE_WITHOUT="development:test", so a
|
|
529
|
+
# `group :development do ... end` entry (or an inline `group:` kwarg) must
|
|
530
|
+
# NOT count — the gem wouldn't be installed and thrust would raise at boot.
|
|
531
|
+
# Line-level block tracking: any `... do` pushes, `end` pops; a gem line
|
|
532
|
+
# counts only outside every group block (nested non-group blocks are fine).
|
|
533
|
+
def gemfile_bundles_thruster?
|
|
534
|
+
gemfile = File.join(destination_root, "Gemfile")
|
|
535
|
+
return false unless File.exist?(gemfile)
|
|
536
|
+
|
|
537
|
+
block_stack = []
|
|
538
|
+
File.foreach(gemfile) do |line|
|
|
539
|
+
if line.match?(/\bdo\s*(\|[^|]*\|)?\s*$/)
|
|
540
|
+
block_stack.push(line.match?(/^\s*group\b/))
|
|
541
|
+
elsif line.match?(/^\s*end\b/)
|
|
542
|
+
block_stack.pop
|
|
543
|
+
elsif block_stack.none? && line.match?(/^\s*gem\s+["']thruster["']/) && !line.match?(/\bgroup:/)
|
|
544
|
+
return true
|
|
545
|
+
end
|
|
546
|
+
end
|
|
547
|
+
false
|
|
548
|
+
end
|
|
455
549
|
end
|
|
456
550
|
end
|
|
457
551
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../../../docs_kit/version"
|
|
4
|
+
|
|
3
5
|
module DocsKit
|
|
4
6
|
module Generators
|
|
5
7
|
# Detects manual drift in an existing docs site that the install generator
|
|
@@ -9,13 +11,21 @@ module DocsKit
|
|
|
9
11
|
# generator prints these as a checklist during a `--sync` upgrade; the site
|
|
10
12
|
# owner deletes the flagged code by hand.
|
|
11
13
|
#
|
|
12
|
-
#
|
|
14
|
+
# Drift items, from the consumer audits:
|
|
13
15
|
# - ApplicationController hand-defines `render_page` — DocsKit::Controller
|
|
14
16
|
# (included by the generator for months) already provides it.
|
|
15
17
|
# - a dead IconHelper copy — the gem renders icons via rails_icons.
|
|
18
|
+
# - a Dockerfile stamped by an OLDER docs-kit than the gem now ships — the
|
|
19
|
+
# site should diff against the current template and adopt the improvements.
|
|
16
20
|
class SyncReport
|
|
17
21
|
APPLICATION_CONTROLLER = "app/controllers/application_controller.rb"
|
|
18
22
|
ICON_HELPER = "app/helpers/icon_helper.rb"
|
|
23
|
+
DOCKERFILE = "Dockerfile"
|
|
24
|
+
|
|
25
|
+
# Matches the version stamp the Dockerfile template writes, e.g.
|
|
26
|
+
# `# docs-kit Dockerfile v1.0.2`. Absent on a hand-written Dockerfile a site
|
|
27
|
+
# brought itself — which we deliberately leave alone (no marker → no warning).
|
|
28
|
+
DOCKERFILE_MARKER = /docs-kit Dockerfile v(\d+\.\d+\.\d+)/
|
|
19
29
|
|
|
20
30
|
def initialize(destination_root)
|
|
21
31
|
@root = destination_root
|
|
@@ -24,7 +34,7 @@ module DocsKit
|
|
|
24
34
|
# The drift messages, in the order a site should act on them. Empty when
|
|
25
35
|
# the site is clean.
|
|
26
36
|
def items
|
|
27
|
-
[render_page_drift, icon_helper_drift].compact
|
|
37
|
+
[render_page_drift, icon_helper_drift, dockerfile_drift].compact
|
|
28
38
|
end
|
|
29
39
|
|
|
30
40
|
def clean?
|
|
@@ -53,6 +63,22 @@ module DocsKit
|
|
|
53
63
|
"rails_icons (DocsUI::Icon); delete it."
|
|
54
64
|
end
|
|
55
65
|
|
|
66
|
+
# The site's Dockerfile carries a docs-kit version stamp OLDER than the gem
|
|
67
|
+
# now ships. We never rewrite the site's Dockerfile (it's tuned per site) —
|
|
68
|
+
# we point the owner at the current template to diff or replace. A file with
|
|
69
|
+
# no marker (a hand-written Dockerfile) is left alone: no stamp, no warning.
|
|
70
|
+
def dockerfile_drift
|
|
71
|
+
source = read(DOCKERFILE)
|
|
72
|
+
stamped = source&.match(DOCKERFILE_MARKER)
|
|
73
|
+
return unless stamped
|
|
74
|
+
|
|
75
|
+
site_version = stamped[1]
|
|
76
|
+
return if site_version == DocsKit::VERSION
|
|
77
|
+
|
|
78
|
+
"#{DOCKERFILE} is v#{site_version}, docs-kit now ships v#{DocsKit::VERSION} — " \
|
|
79
|
+
"diff against the template (bin/rails g docs_kit:install shows the path) and adopt the changes."
|
|
80
|
+
end
|
|
81
|
+
|
|
56
82
|
def read(rel)
|
|
57
83
|
path = File.join(@root, rel)
|
|
58
84
|
File.exist?(path) ? File.read(path) : nil
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# syntax = docker/dockerfile:1
|
|
2
|
+
# docs-kit Dockerfile v<%= DocsKit::VERSION %> — regenerate/diff: bin/rails g docs_kit:install
|
|
3
|
+
#
|
|
4
|
+
# A standalone docs-kit site: a lean, multi-stage production image. The final
|
|
5
|
+
# stage carries only the runtime (Ruby + the installed bundle + the app), never
|
|
6
|
+
# the build toolchain (build-essential, git, bun) — those live in the throwaway
|
|
7
|
+
# `build` stage. Pair it with the shipped .dockerignore so the build context
|
|
8
|
+
# stays small (no node_modules, .git, logs, specs, coverage).
|
|
9
|
+
#
|
|
10
|
+
# Build context is the app root; `docker build .` (Kamal: context: ".").
|
|
11
|
+
|
|
12
|
+
ARG RUBY_VERSION=<%= ruby_version_arg %>
|
|
13
|
+
FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base
|
|
14
|
+
|
|
15
|
+
# Rails app lives here.
|
|
16
|
+
WORKDIR /rails
|
|
17
|
+
|
|
18
|
+
ARG BUN_VERSION=1.3.2
|
|
19
|
+
ENV BUN_INSTALL="/usr/local/bun" \
|
|
20
|
+
PATH="/usr/local/bun/bin:$PATH" \
|
|
21
|
+
BUNDLE_DEPLOYMENT="1" \
|
|
22
|
+
BUNDLE_PATH="/usr/local/bundle" \
|
|
23
|
+
BUNDLE_WITHOUT="development:test" \
|
|
24
|
+
RAILS_ENV="production"
|
|
25
|
+
|
|
26
|
+
# Base packages the RUNTIME needs (jemalloc for a smaller/faster heap, curl for
|
|
27
|
+
# the container healthcheck). Anything only the build needs goes in `build`.
|
|
28
|
+
RUN apt-get update -qq && \
|
|
29
|
+
apt-get install --no-install-recommends -y curl libjemalloc2 && \
|
|
30
|
+
rm -rf /var/lib/apt/lists /var/cache/apt/archives
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# --- Build stage (throwaway — its layers never reach the final image) ---------
|
|
34
|
+
FROM base AS build
|
|
35
|
+
|
|
36
|
+
# Toolchain to compile native gems + fetch bun. Skip the apt cleanup: this whole
|
|
37
|
+
# stage is discarded.
|
|
38
|
+
RUN apt-get update -qq && \
|
|
39
|
+
apt-get install --no-install-recommends -y build-essential git libyaml-dev pkg-config unzip
|
|
40
|
+
RUN curl -fsSL https://bun.sh/install | bash -s -- "bun-v${BUN_VERSION}"
|
|
41
|
+
|
|
42
|
+
# Install gems first (cached until Gemfile/Gemfile.lock change), then prune the
|
|
43
|
+
# bundler cache + any git-sourced gem checkouts so they don't bloat the layer.
|
|
44
|
+
COPY Gemfile Gemfile.lock ./
|
|
45
|
+
RUN bundle install && \
|
|
46
|
+
rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git
|
|
47
|
+
|
|
48
|
+
# Install JS deps (the Tailwind/daisyUI CLI), then the app.
|
|
49
|
+
COPY package.json bun.lock* ./
|
|
50
|
+
RUN bun install --frozen-lockfile
|
|
51
|
+
COPY . .
|
|
52
|
+
|
|
53
|
+
# assets:precompile runs `bun run build:css` via the css:build rake enhance.
|
|
54
|
+
# Drop the node_modules + bun cache afterwards — the built CSS is all we keep.
|
|
55
|
+
RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile && \
|
|
56
|
+
rm -rf node_modules .bun tmp/cache
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# --- Final stage --------------------------------------------------------------
|
|
60
|
+
FROM base
|
|
61
|
+
|
|
62
|
+
# Kamal's validate_image greps this label on a --skip-push deploy; it must equal
|
|
63
|
+
# `service:` in config/deploy.yml. The reusable deploy workflow also stamps it,
|
|
64
|
+
# but keeping it here means `docker build` alone produces a Kamal-valid image.
|
|
65
|
+
LABEL service="<%= docker_service %>"
|
|
66
|
+
|
|
67
|
+
# Copy ONLY the built artifacts from the build stage: the installed bundle and
|
|
68
|
+
# the app (with precompiled assets). No toolchain, no node_modules.
|
|
69
|
+
COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
|
|
70
|
+
COPY --from=build /rails /rails
|
|
71
|
+
|
|
72
|
+
# Run as a non-root user; own only the runtime dirs it writes.
|
|
73
|
+
RUN groupadd --system --gid 1000 rails && \
|
|
74
|
+
useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash && \
|
|
75
|
+
chown -R 1000:1000 /rails/log /rails/tmp
|
|
76
|
+
USER 1000:1000
|
|
77
|
+
|
|
78
|
+
EXPOSE 3000
|
|
79
|
+
<% if thruster? -%>
|
|
80
|
+
# Thruster fronts Puma (HTTP caching + compression + X-Sendfile). It listens on
|
|
81
|
+
# HTTP_PORT and proxies to Puma on TARGET_PORT (it sets PORT for the child, which
|
|
82
|
+
# config/puma.rb reads). HTTP_PORT MUST be the port traffic is routed to (Kamal's
|
|
83
|
+
# `app_port`, the EXPOSE above) — Thruster's default is 80, which the non-root
|
|
84
|
+
# user can't reliably bind AND which kamal-proxy (app_port: 3000) would never
|
|
85
|
+
# route to, silently bypassing Thruster straight into Puma.
|
|
86
|
+
ENV HTTP_PORT="3000" \
|
|
87
|
+
TARGET_PORT="3001"
|
|
88
|
+
CMD ["./bin/thrust", "./bin/rails", "server"]
|
|
89
|
+
<% else -%>
|
|
90
|
+
# No Thruster in this app's bundle — plain Puma. To front it with Thruster
|
|
91
|
+
# (HTTP caching/compression/X-Sendfile): add `gem "thruster"`, then delete this
|
|
92
|
+
# file and re-run `bin/rails g docs_kit:install` — the generator never
|
|
93
|
+
# overwrites an existing Dockerfile, so a re-run alone won't update it. (It
|
|
94
|
+
# also scaffolds the bin/thrust binstub the thrust CMD needs.)
|
|
95
|
+
CMD ["./bin/rails", "server", "-b", "0.0.0.0"]
|
|
96
|
+
<% end -%>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# docs-kit .dockerignore — keep the build context (and image layers) small.
|
|
2
|
+
# Gem-owned: `bin/rails g docs_kit:install` refreshes this on every run.
|
|
3
|
+
# See https://docs.docker.com/build/building/context/#dockerignore-files
|
|
4
|
+
|
|
5
|
+
# Git metadata — the app build never needs it (a released gem carries its files).
|
|
6
|
+
/.git/
|
|
7
|
+
/.gitignore
|
|
8
|
+
/.gitattributes
|
|
9
|
+
|
|
10
|
+
# Bundler config (BUNDLE_* env in the Dockerfile drives the install instead).
|
|
11
|
+
/.bundle
|
|
12
|
+
|
|
13
|
+
# Environment files and credentials — never bake secrets into an image.
|
|
14
|
+
/.env*
|
|
15
|
+
!/.env*.erb
|
|
16
|
+
/config/master.key
|
|
17
|
+
/config/credentials/*.key
|
|
18
|
+
|
|
19
|
+
# Logs and tempfiles (keep the dirs, drop the contents).
|
|
20
|
+
/log/*
|
|
21
|
+
!/log/.keep
|
|
22
|
+
/tmp/*
|
|
23
|
+
!/tmp/.keep
|
|
24
|
+
/tmp/pids/*
|
|
25
|
+
!/tmp/pids/.keep
|
|
26
|
+
|
|
27
|
+
# JS deps + generated assets: `bun install` + `assets:precompile` rebuild them.
|
|
28
|
+
/node_modules/
|
|
29
|
+
/app/assets/builds/*
|
|
30
|
+
!/app/assets/builds/.keep
|
|
31
|
+
# Generated by bin/build-css — Tailwind resolves the gem @source globs at build.
|
|
32
|
+
/app/assets/stylesheets/tailwind.sources.css
|
|
33
|
+
/public/assets
|
|
34
|
+
|
|
35
|
+
# Tests + coverage — not needed to run the site in production.
|
|
36
|
+
/spec/
|
|
37
|
+
/.rspec
|
|
38
|
+
/coverage/
|
|
39
|
+
/spec/examples.txt
|
|
40
|
+
|
|
41
|
+
# CI / deploy / Docker meta — not part of the runtime image.
|
|
42
|
+
/.github/
|
|
43
|
+
/.kamal/
|
|
44
|
+
/Dockerfile*
|
|
45
|
+
/.dockerignore
|
|
46
|
+
|
|
47
|
+
# Editor + AI-assistant configs.
|
|
48
|
+
/.claude/
|
|
49
|
+
/.cursor/
|
|
50
|
+
/.vscode/
|
|
51
|
+
/.idea/
|
|
52
|
+
/.ruby-lsp/
|
|
53
|
+
/.solargraph.yml
|
|
54
|
+
|
|
55
|
+
# Docs-kit's own tooling snapshots (harmless if absent in a consuming site).
|
|
56
|
+
/codedb.snapshot
|
|
57
|
+
/.worktrees/
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: docs-kit
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mikael Henriksson
|
|
@@ -233,11 +233,13 @@ files:
|
|
|
233
233
|
- lib/generators/docs_kit/install/USAGE
|
|
234
234
|
- lib/generators/docs_kit/install/install_generator.rb
|
|
235
235
|
- lib/generators/docs_kit/install/sync_report.rb
|
|
236
|
+
- lib/generators/docs_kit/install/templates/Dockerfile.tt
|
|
236
237
|
- lib/generators/docs_kit/install/templates/agents_md.erb
|
|
237
238
|
- lib/generators/docs_kit/install/templates/application.tailwind.css.erb
|
|
238
239
|
- lib/generators/docs_kit/install/templates/build-css
|
|
239
240
|
- lib/generators/docs_kit/install/templates/build_css.rake
|
|
240
241
|
- lib/generators/docs_kit/install/templates/doc.rb.erb
|
|
242
|
+
- lib/generators/docs_kit/install/templates/dockerignore
|
|
241
243
|
- lib/generators/docs_kit/install/templates/docs_controller.rb.erb
|
|
242
244
|
- lib/generators/docs_kit/install/templates/docs_kit.rb.erb
|
|
243
245
|
- lib/generators/docs_kit/install/templates/docs_kit_og.rake
|