feat(generator): gitignore the generated tailwind.sources.css fleet-wide - #72
feat(generator): gitignore the generated tailwind.sources.css fleet-wide#72mhenrixon wants to merge 7 commits into
Conversation
## 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
There was a problem hiding this comment.
All reported issues were addressed across 4 files
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
…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.
There was a problem hiding this comment.
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
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.
There was a problem hiding this comment.
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
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.
There was a problem hiding this comment.
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
…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).
Closes #71 — raised by cubic on glyphs#11 and locallingo#6.
Summary
bin/build-cssregeneratesapp/assets/stylesheets/tailwind.sources.csson every build viabundle show, so a committed copy churns with machine-specific absolute gem paths (/Users/<user>/.gem/ruby/<version>/...) — and no build path consumes it (.dockerignoreexcludes it; every build runsbin/build-cssfirst). This ships Option 1 (gitignore it fleet-wide) through the generator, not per-site hand edits: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 —--syncis exactly how existing sites pick up the convention.SyncReportdrift item — atailwind.sources.cssstill tracked by git (gitignore doesn't untrack) is flagged with the exactgit rm --cached app/assets/stylesheets/tailwind.sources.csscommand. Warn-only: the generator never mutates git state. The check usesgit -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".docs-kit newneeds nothing extra: it runsdocs_kit:install, andrails new's.gitignoregets the appended entry. The dogfood site (docs/) already ignores the file and doesn't track it.Test plan
.gitignore/ created when absent; idempotent re-run and unslashed hand-added variant add no duplicate;--syncadds it too.git rm --cachedcommand when the file is tracked (realgit init+git addin the tmp skeleton), asserts the index is left untouched; silent when the site isn't a repo.bundle exec rakegreen (99 generator examples; 94.5% line coverage; RuboCop clean).Deviations & judgment calls
Migrationentry, generator step only — the issue said "generator +--syncmigration", but--syncre-runs every unguarded generator method, so an idempotentignore_generated_css_sourcesstep already covers both fresh installs and syncs; a registryMigrationdoing 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 --cachedis 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..dockerignoreexcludes it; every build runsbin/build-cssfirst), so making it portable would still commit a file nothing reads.Summary by cubic
Gitignores the generated
app/assets/stylesheets/tailwind.sources.cssfleet‑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, usinggit ls-files --cached --ignored --exclude-per-directory=.gitignoreso only repo.gitignorerules influence the warning and honoring an explicit!opt‑out.ignore_generated_css_sources: appends a commented entry to.gitignoreor 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.SyncReportdrift item: when the file is tracked and effectively ignored by repo rules (scoped to committed.gitignorefiles viagit ls-files --cached --ignored --exclude-per-directory=.gitignore), printsgit rm --cached app/assets/stylesheets/tailwind.sources.css(warn‑only). Suppressed when an effective!negation exists.zoolutionsorg.Rollout
app/assets/stylesheets/tailwind.sources.css, run:git rm --cached app/assets/stylesheets/tailwind.sources.cssand commit.bin/rails g docs_kit:install --sync.Written for commit 7b6b7c6. Summary will update on new commits.