Skip to content

feat(generator): gitignore the generated tailwind.sources.css fleet-wide - #72

Open
mhenrixon wants to merge 7 commits into
mainfrom
issue-71-gitignore-tailwind-sources
Open

feat(generator): gitignore the generated tailwind.sources.css fleet-wide#72
mhenrixon wants to merge 7 commits into
mainfrom
issue-71-gitignore-tailwind-sources

Conversation

@mhenrixon

@mhenrixon mhenrixon commented Aug 16, 2026

Copy link
Copy Markdown
Collaborator

Closes #71 — raised by cubic on glyphs#11 and locallingo#6.

Summary

bin/build-css regenerates app/assets/stylesheets/tailwind.sources.css on every build via bundle show, so a committed copy churns with machine-specific absolute gem paths (/Users/<user>/.gem/ruby/<version>/...) — and no build path consumes it (.dockerignore excludes it; every build runs bin/build-css first). This ships Option 1 (gitignore it fleet-wide) through the generator, not per-site hand edits:

  • New generator step ignore_generated_css_sources — appends the ignore entry (with a comment) to the site's .gitignore, or creates one when absent. Additive and idempotent: a re-run skips, and a hand-added entry (with or without the leading slash) counts as present. Not --sync-guarded — --sync is exactly how existing sites pick up the convention.
  • New SyncReport drift item — a tailwind.sources.css still tracked by git (gitignore doesn't untrack) is flagged with the exact git rm --cached app/assets/stylesheets/tailwind.sources.css command. Warn-only: the generator never mutates git state. The check uses git -C <root> ls-files --error-unmatch (index-only, works for a docs site in a subdir of a larger repo) and reads any failure — no git, not a repo, untracked — as "no drift".
  • README — the one-time-cleanup drift table gains the new row.

docs-kit new needs nothing extra: it runs docs_kit:install, and rails new's .gitignore gets the appended entry. The dogfood site (docs/) already ignores the file and doesn't track it.

Test plan

  • Generator spec: entry appended to an existing .gitignore / created when absent; idempotent re-run and unslashed hand-added variant add no duplicate; --sync adds it too.
  • Drift spec: warns with the git rm --cached command when the file is tracked (real git init + git add in the tmp skeleton), asserts the index is left untouched; silent when the site isn't a repo.
  • bundle exec rake green (99 generator examples; 94.5% line coverage; RuboCop clean).

Deviations & judgment calls

  • No Migration entry, generator step only — the issue said "generator + --sync migration", but --sync re-runs every unguarded generator method, so an idempotent ignore_generated_css_sources step already covers both fresh installs and syncs; a registry Migration doing the same thing would be redundant (and the registry's contract says it ships empty until a release needs a version-gated transform — an always-safe additive step doesn't).
  • git rm --cached is warn-only (SyncReport), not automated — the issue floated the generator running it, but no existing step mutates git state and SyncReport's contract is "never touches a byte"; staging a deletion behind the user's back crosses that line. The drift checklist prints the exact command instead, and keeps printing it until the site acts.
  • Chose Option 1 (gitignore) over Option 2 (portable globs) — the issue leans that way: the committed copy is consumed by no build path (.dockerignore excludes it; every build runs bin/build-css first), so making it portable would still commit a file nothing reads.

Summary by cubic

Gitignores the generated app/assets/stylesheets/tailwind.sources.css fleet‑wide to stop machine/Ruby‑specific churn. Previously many sites committed it; now the generator adds the ignore and the sync report warns if a tracked copy remains, using git ls-files --cached --ignored --exclude-per-directory=.gitignore so only repo .gitignore rules influence the warning and honoring an explicit ! opt‑out.

  • Adds generator step ignore_generated_css_sources: appends a commented entry to .gitignore or creates one; idempotent; runs under --sync; recognizes bare‑filename and **/‑prefixed lines; CRLF‑tolerant; respects last‑match‑wins so only an effective trailing ! negation counts as an opt‑out.
  • Adds SyncReport drift item: when the file is tracked and effectively ignored by repo rules (scoped to committed .gitignore files via git ls-files --cached --ignored --exclude-per-directory=.gitignore), prints git rm --cached app/assets/stylesheets/tailwind.sources.css (warn‑only). Suppressed when an effective ! negation exists.
  • Updates gemspec homepage and metadata URLs to the zoolutions org.

Rollout

  • If your repo tracks app/assets/stylesheets/tailwind.sources.css, run: git rm --cached app/assets/stylesheets/tailwind.sources.css and commit.
  • Existing sites pick up the ignore by re‑running: bin/rails g docs_kit:install --sync.

Written for commit 7b6b7c6. Summary will update on new commits.

Review in cubic

## Summary
bin/build-css regenerates app/assets/stylesheets/tailwind.sources.css on
every build with machine-specific absolute gem paths — committed, it churns
on every rebuild by a different machine/Ruby, and no build consumes the
committed copy (.dockerignore excludes it; every build path regenerates it
first). The install generator now adds the .gitignore entry (additive,
idempotent, tolerant of a hand-added entry with or without the leading
slash, and NOT --sync-guarded — --sync is how the fleet picks it up). A
copy already tracked by git is flagged by SyncReport with the exact
`git rm --cached` command — warn-only, the generator never mutates git
state.

## Test Coverage
- appends the entry to an existing .gitignore / creates one when absent
- idempotent re-run and hand-added-variant tolerance (no duplicates)
- --sync adds the entry (the upgrade path)
- drift warning when the file is git-tracked; silent when not a repo;
  warn-only (the index is untouched)

## Verification
- [x] bundle exec rubocop passes
- [x] bundle exec rspec passes (99 generator examples, suite green)

Closes #71

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 4 files

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread lib/generators/docs_kit/install/install_generator.rb Outdated
Comment thread lib/generators/docs_kit/install/install_generator.rb Outdated
…ces.css

Review follow-ups (PR #72):
- An explicit `!tailwind.sources.css` in .gitignore is the site's deliberate
  opt-out — appending our entry after it would become the last matching rule
  and silently defeat the hand-edit. The generator now backs off with a
  yellow skip, and SyncReport skips the `git rm --cached` nag for the same
  opt-out (a deliberate commit shouldn't be nagged every sync).
- Presence detection now also counts a bare-filename line
  (`tailwind.sources.css`, optionally `**/`-prefixed) as covering — it
  matches at any depth per gitignore semantics. Broader globs stay
  undetected on purpose: the miss costs one harmless redundant line, and
  `git check-ignore` would conflate a user's global excludes with the
  repo's committed convention.

The covering/negation regexes live beside TAILWIND_SOURCES in SyncReport,
shared by both call sites.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 3 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread lib/generators/docs_kit/install/install_generator.rb Outdated
Comment thread lib/generators/docs_kit/install/install_generator.rb Outdated
Review follow-ups (PR #72, round 2):
- `[ \t\r]*` in TAILWIND_SOURCES_COVER: `$` matches before `\n` but never
  past a `\r`, so on a CRLF-checked-out .gitignore both the covering-entry
  and the negation detection silently failed (duplicate appends; a missed
  opt-out).
- SyncReport.tailwind_sources_rule reads the recognized lines the way git
  does — last match wins. A `!` line overridden by a LATER ignore line is
  dead: the file is effectively ignored, so the generator reports it as
  covered (no append, no bogus "opt-out" message) and the tracked-file
  drift warning still fires. Only an EFFECTIVE trailing negation counts as
  the site's opt-out.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 3 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread lib/generators/docs_kit/install/sync_report.rb
Review follow-up (PR #72, round 3): a dead `!` negation followed by an
UNRECOGNIZED broad ignore (`app/assets/stylesheets/*`) read as an opt-out
and suppressed the tracked-file drift warning. Rather than reimplement
gitignore glob semantics, the drift check now asks git itself:
`git check-ignore -q --no-index` resolves the FULL pattern semantics
(broad globs, ordering, nested .gitignores). --no-index is essential —
without it a tracked path is never reported ignored, which is the exact
state the check exists to catch.

The recognized-lines regex stays for the generator's append decision,
where a user's global excludes must NOT decide repo content.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 2 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread lib/generators/docs_kit/install/sync_report.rb
…ore rules

`ignored_by_git?` shelled out to `git check-ignore`, which also consults
.git/info/exclude and a global core.excludesFile — so the sync report's
drift warning (and its "the ignore entry is in place" guidance) could
differ per machine, contradicting the comment above the recognized-lines
regex. Replace it with `git ls-files --cached --ignored
--exclude-per-directory=.gitignore`: git's full pattern semantics, but
only the repo's own .gitignore files, and it reports tracked paths
directly (no --no-index dance). Reconcile the comments that still named
check-ignore.

Spec: a file tracked + ignored only via .git/info/exclude produces no
drift warning (machine-local excludes never decide the report).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Consider gitignoring the generated docs tailwind.sources.css fleet-wide

1 participant