source_monitor 0.13.1 → 0.14.0
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/.claude/skills/sm-configuration-setting/reference/settings-catalog.md +1 -0
- data/.claude/skills/sm-configure/SKILL.md +8 -1
- data/.claude/skills/sm-configure/reference/configuration-reference.md +11 -0
- data/.claude/skills/sm-host-setup/SKILL.md +13 -3
- data/.claude/skills/sm-host-setup/reference/initializer-template.md +11 -0
- data/.claude/skills/sm-host-setup/reference/setup-checklist.md +9 -1
- data/.claude/skills/sm-upgrade/reference/version-history.md +12 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile.lock +1 -1
- data/README.md +3 -3
- data/VERSION +1 -1
- data/app/controllers/source_monitor/application_controller.rb +73 -14
- data/app/views/layouts/source_monitor/application.html.erb +6 -0
- data/docs/configuration.md +18 -1
- data/docs/deployment.md +1 -1
- data/docs/goals/engine-hardening/.goalbuddy-board/app.js +543 -0
- data/docs/goals/engine-hardening/.goalbuddy-board/goalbuddy-mark.png +0 -0
- data/docs/goals/engine-hardening/.goalbuddy-board/index.html +111 -0
- data/docs/goals/engine-hardening/.goalbuddy-board/styles.css +991 -0
- data/docs/goals/engine-hardening/goal.md +97 -0
- data/docs/goals/engine-hardening/notes/T001-spec-validation.md +37 -0
- data/docs/goals/engine-hardening/state.yaml +324 -0
- data/docs/setup.md +3 -3
- data/docs/upgrade.md +27 -0
- data/lib/generators/source_monitor/install/templates/source_monitor.rb.tt +10 -0
- data/lib/source_monitor/configuration/authentication_settings.rb +5 -1
- data/lib/source_monitor/security/authentication.rb +10 -0
- data/lib/source_monitor/version.rb +1 -1
- data/source_monitor.gemspec +7 -2
- metadata +8 -65
- data/.claude/agent-memory/vbw-vbw-debugger/MEMORY.md +0 -15
- data/.claude/agent-memory/vbw-vbw-dev/MEMORY.md +0 -34
- data/.claude/agent-memory/vbw-vbw-lead/MEMORY.md +0 -49
- data/.claude/agents/rails-concern.md +0 -464
- data/.claude/agents/rails-controller.md +0 -424
- data/.claude/agents/rails-hotwire.md +0 -446
- data/.claude/agents/rails-implement.md +0 -374
- data/.claude/agents/rails-job.md +0 -334
- data/.claude/agents/rails-lint.md +0 -294
- data/.claude/agents/rails-mailer.md +0 -371
- data/.claude/agents/rails-migration.md +0 -449
- data/.claude/agents/rails-model.md +0 -420
- data/.claude/agents/rails-policy.md +0 -443
- data/.claude/agents/rails-presenter.md +0 -427
- data/.claude/agents/rails-query.md +0 -412
- data/.claude/agents/rails-review.md +0 -490
- data/.claude/agents/rails-service.md +0 -458
- data/.claude/agents/rails-state-records.md +0 -465
- data/.claude/agents/rails-tdd.md +0 -314
- data/.claude/agents/rails-test.md +0 -441
- data/.claude/agents/rails-view-component.md +0 -418
- data/.claude/commands/rails-audit.md +0 -77
- data/.claude/commands/release.md +0 -366
- data/.claude/hooks/block-secrets.sh +0 -52
- data/.claude/settings.json +0 -85
- data/.claude/skills/action-cable-patterns/SKILL.md +0 -296
- data/.claude/skills/action-mailer-patterns/SKILL.md +0 -295
- data/.claude/skills/active-storage-setup/SKILL.md +0 -311
- data/.claude/skills/api-versioning/SKILL.md +0 -294
- data/.claude/skills/authentication-flow/SKILL.md +0 -335
- data/.claude/skills/authentication-flow/reference/current.md +0 -248
- data/.claude/skills/authentication-flow/reference/passwordless.md +0 -253
- data/.claude/skills/authentication-flow/reference/sessions.md +0 -201
- data/.claude/skills/authorization-pundit/SKILL.md +0 -462
- data/.claude/skills/caching-strategies/SKILL.md +0 -350
- data/.claude/skills/database-migrations/SKILL.md +0 -354
- data/.claude/skills/form-object-patterns/SKILL.md +0 -399
- data/.claude/skills/hotwire-patterns/SKILL.md +0 -247
- data/.claude/skills/hotwire-patterns/reference/stimulus.md +0 -307
- data/.claude/skills/hotwire-patterns/reference/tailwind-integration.md +0 -112
- data/.claude/skills/hotwire-patterns/reference/turbo-frames.md +0 -158
- data/.claude/skills/hotwire-patterns/reference/turbo-streams.md +0 -218
- data/.claude/skills/i18n-patterns/SKILL.md +0 -320
- data/.claude/skills/install/SKILL.md +0 -367
- data/.claude/skills/performance-optimization/SKILL.md +0 -311
- data/.claude/skills/rails-architecture/SKILL.md +0 -259
- data/.claude/skills/rails-architecture/reference/error-handling.md +0 -333
- data/.claude/skills/rails-architecture/reference/event-tracking.md +0 -142
- data/.claude/skills/rails-architecture/reference/layer-interactions.md +0 -417
- data/.claude/skills/rails-architecture/reference/multi-tenancy.md +0 -152
- data/.claude/skills/rails-architecture/reference/query-patterns.md +0 -342
- data/.claude/skills/rails-architecture/reference/service-patterns.md +0 -286
- data/.claude/skills/rails-architecture/reference/state-records.md +0 -250
- data/.claude/skills/rails-architecture/reference/testing-strategy.md +0 -326
- data/.claude/skills/rails-concern/SKILL.md +0 -399
- data/.claude/skills/rails-controller/SKILL.md +0 -336
- data/.claude/skills/rails-model-generator/SKILL.md +0 -321
- data/.claude/skills/rails-model-generator/reference/validations.md +0 -298
- data/.claude/skills/rails-presenter/SKILL.md +0 -274
- data/.claude/skills/rails-query-object/SKILL.md +0 -289
- data/.claude/skills/rails-service-object/SKILL.md +0 -349
- data/.claude/skills/solid-queue-setup/SKILL.md +0 -307
- data/.claude/skills/tdd-cycle/SKILL.md +0 -359
- data/.claude/skills/viewcomponent-patterns/SKILL.md +0 -333
data/.claude/commands/release.md
DELETED
|
@@ -1,366 +0,0 @@
|
|
|
1
|
-
# Release: PR, CI, Merge, and Gem Build
|
|
2
|
-
|
|
3
|
-
Orchestrate a full release cycle for the source_monitor gem. This command handles changelog generation, documentation audit, version bumping, PR creation, CI monitoring, auto-merge on success, release tagging, and gem build with push instructions.
|
|
4
|
-
|
|
5
|
-
## Inputs
|
|
6
|
-
|
|
7
|
-
- `$ARGUMENTS` -- Optional: version bump description or release notes summary. If empty, derive from commits since last tag.
|
|
8
|
-
|
|
9
|
-
## Known Gotchas (Read Before Starting)
|
|
10
|
-
|
|
11
|
-
These are real issues encountered in previous releases. Each step below accounts for them, but keep them in mind:
|
|
12
|
-
|
|
13
|
-
1. **Two version files**: Both `lib/source_monitor/version.rb` AND the top-level `VERSION` file must be bumped. The VBW pre-push hook checks for changes to `VERSION` (the top-level file).
|
|
14
|
-
2. **Gemfile.lock sync**: After bumping the version in `version.rb`, you MUST run `bundle install` to update `Gemfile.lock`. CI runs `bundle install --frozen` which fails if the lockfile is stale.
|
|
15
|
-
3. **VBW volatile files**: Files in `.vbw-planning/` (`.cost-ledger.json`, `.notification-log.jsonl`, `.session-log.jsonl`, `.hook-errors.log`) are continuously modified by VBW hooks. They should be in `.gitignore`. If they aren't, add them before proceeding.
|
|
16
|
-
4. **Pre-push hook**: The VBW pre-push hook at `.git/hooks/pre-push` requires the `VERSION` file to appear in the diff for any push. For new branches, it compares the commit against the working tree -- any dirty files will trigger a false positive. For force-pushes to existing branches where `VERSION` hasn't changed since the last push, use `--no-verify`.
|
|
17
|
-
5. **Single squashed commit**: Always create ONE commit on the release branch with ALL changes (version bump, changelog, Gemfile.lock, any fixes). Multiple commits cause pre-push hook issues.
|
|
18
|
-
6. **Diff coverage CI gate**: The `test` CI job enforces diff coverage. Any changed lines in source code (not just test files) must have test coverage. **This applies to ALL changes in the PR diff vs main, including unpushed commits made before the release started.** If the release includes source code changes (bug fixes, features), every changed source line must be covered.
|
|
19
|
-
7. **Local main divergence after merge**: After the PR merges, `gh pr merge --merge --delete-branch` will attempt to fast-forward local main. This usually succeeds automatically. If it doesn't (divergent history), you must `git reset --hard origin/main` to sync -- this requires user approval since the sandbox blocks it.
|
|
20
|
-
8. **Run FULL local CI suite BEFORE pushing**: Always run ALL of these locally before the first push to the release branch:
|
|
21
|
-
- `bin/rubocop` -- Ruby lint
|
|
22
|
-
- `PARALLEL_WORKERS=1 bin/rails test` -- tests + diff coverage readiness
|
|
23
|
-
- `bin/brakeman --no-pager` -- security scan
|
|
24
|
-
- `yarn build` -- rebuild JS assets (catches ESLint issues; CI runs ESLint separately on JS files)
|
|
25
|
-
Each CI roundtrip (fail → fix → amend → force-push → re-run) costs ~5 minutes. In v0.7.0, skipping local checks caused two wasted CI cycles. In v0.8.0, skipping ESLint (`yarn build`) and diff coverage pre-checks caused another two wasted cycles: first for ESLint `no-undef` on browser globals (MutationObserver, requestAnimationFrame), then for 13 uncovered rescue/error path lines across 3 files.
|
|
26
|
-
9. **ESLint browser globals**: Any JS file using browser APIs (MutationObserver, requestAnimationFrame, cancelAnimationFrame, IntersectionObserver, etc.) MUST declare them with a `/* global ... */` comment at the top. ESLint's `no-undef` rule in CI will reject them otherwise.
|
|
27
|
-
10. **Diff coverage rescue paths**: Every `rescue`/fallback/error handling branch in changed source code needs test coverage. Common blind spots: `rescue StandardError => e` logging, `rescue URI::InvalidURIError` returning nil, fallback `false` returns. Write targeted tests for these BEFORE creating the release commit.
|
|
28
|
-
11. **Zsh glob nomatch**: Commands like `rm -f *.gem` fail in zsh when no files match. Always use `rm -f *.gem 2>/dev/null || true` or check existence first with `ls`.
|
|
29
|
-
12. **Documentation drift**: Features, config options, and behavioral changes often land across milestone work without corresponding doc updates. Step 4 now spawns agents to both audit AND fix all stale docs automatically. In v0.9.x, 14 files needed updates; in v0.12.0, 7 files were stale (README version refs, docs/setup version refs, docs/upgrade missing section, 4 skill references). Always assume docs are stale.
|
|
30
|
-
13. **test-coverage script health_suite**: The `bin/test-coverage` script runs a second "health_suite" pass with specific test files. If you add new test files for health/service classes, you MUST add them to the `TARGETED_TESTS` array in `bin/test-coverage` or SimpleCov's merged report will show 0% coverage for those files even though the main suite covers them. In v0.12.0, `source_health_check_orchestrator_test.rb` showed 31% coverage on CI despite 100% locally because it wasn't in the health_suite list.
|
|
31
|
-
|
|
32
|
-
## Step 1: Git Hygiene
|
|
33
|
-
|
|
34
|
-
Run these checks. If ANY fail, STOP and report the issue to the user.
|
|
35
|
-
|
|
36
|
-
1. **VBW volatile files gitignored**: Check that `.gitignore` contains these entries:
|
|
37
|
-
```
|
|
38
|
-
.vbw-planning/.cost-ledger.json
|
|
39
|
-
.vbw-planning/.notification-log.jsonl
|
|
40
|
-
.vbw-planning/.session-log.jsonl
|
|
41
|
-
.vbw-planning/.hook-errors.log
|
|
42
|
-
```
|
|
43
|
-
If any are missing, add them. If any of these files are tracked by git, remove them from tracking with `git rm --cached <file>`.
|
|
44
|
-
|
|
45
|
-
2. **Working tree clean**: `git status --porcelain` must be empty (ignoring the VBW volatile files which should now be gitignored). If not, list the dirty files and ask the user whether to commit, stash, or abort.
|
|
46
|
-
|
|
47
|
-
3. **On main branch**: `git branch --show-current` must be `main`. If not, ask the user if they want to continue from the current branch or switch.
|
|
48
|
-
|
|
49
|
-
4. **Fetch latest**: `git fetch origin main`
|
|
50
|
-
|
|
51
|
-
5. **Up to date with remote**: Compare `git rev-parse HEAD` with `git rev-parse origin/main`. If behind, ask the user whether to pull.
|
|
52
|
-
|
|
53
|
-
6. **No unpushed commits**: Compare local HEAD with `origin/main`. If ahead, note how many commits are unpushed -- these will be included in the release.
|
|
54
|
-
|
|
55
|
-
Report a summary:
|
|
56
|
-
```
|
|
57
|
-
Git Status:
|
|
58
|
-
Branch: main
|
|
59
|
-
Clean: yes
|
|
60
|
-
VBW files gitignored: yes
|
|
61
|
-
Synced with origin: yes
|
|
62
|
-
Unpushed commits: N
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Step 2: Version Check
|
|
66
|
-
|
|
67
|
-
1. Read `lib/source_monitor/version.rb` to get the current VERSION constant.
|
|
68
|
-
2. Read the top-level `VERSION` file to verify it matches. If they differ, sync them before proceeding.
|
|
69
|
-
3. Read the latest git tag with `git tag --sort=-v:refname | head -1`.
|
|
70
|
-
4. If the VERSION matches the latest tag (e.g., both are `0.3.2`), the version hasn't been bumped. Ask the user:
|
|
71
|
-
- "Current version is X.Y.Z which already has a tag. What should the new version be?"
|
|
72
|
-
- Offer options: patch (X.Y.Z+1), minor (X.Y+1.0), major (X+1.0.0), or custom.
|
|
73
|
-
- Update BOTH `lib/source_monitor/version.rb` AND the top-level `VERSION` file with the new version.
|
|
74
|
-
5. If VERSION is ahead of the latest tag, proceed with the current version.
|
|
75
|
-
|
|
76
|
-
Store the release version for later steps. Do NOT commit yet -- that happens after the changelog is updated.
|
|
77
|
-
|
|
78
|
-
## Step 3: Update CHANGELOG.md
|
|
79
|
-
|
|
80
|
-
The changelog follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format. The file is at `CHANGELOG.md` in the project root.
|
|
81
|
-
|
|
82
|
-
1. **Gather commit history** since the last tag:
|
|
83
|
-
```
|
|
84
|
-
git log vPREVIOUS..HEAD --oneline --no-merges
|
|
85
|
-
```
|
|
86
|
-
2. **Categorize commits** into Keep a Changelog sections based on commit prefixes and content:
|
|
87
|
-
- `feat:`, `add:` --> **Added**
|
|
88
|
-
- `fix:`, `bugfix:` --> **Fixed**
|
|
89
|
-
- `chore:`, `refactor:`, `perf:` --> **Changed**
|
|
90
|
-
- `docs:` --> **Documentation** (only include if substantive)
|
|
91
|
-
- `BREAKING:` or `!:` --> **Breaking Changes** (at the top)
|
|
92
|
-
- `remove:`, `deprecate:` --> **Removed**
|
|
93
|
-
- Skip merge commits, version bumps, and CI-only changes.
|
|
94
|
-
- If `$ARGUMENTS` was provided, use it to inform/supplement the categorization.
|
|
95
|
-
|
|
96
|
-
3. **Draft the changelog entry** and present it to the user for review:
|
|
97
|
-
```
|
|
98
|
-
## [X.Y.Z] - YYYY-MM-DD
|
|
99
|
-
|
|
100
|
-
### Added
|
|
101
|
-
- <items>
|
|
102
|
-
|
|
103
|
-
### Fixed
|
|
104
|
-
- <items>
|
|
105
|
-
|
|
106
|
-
### Changed
|
|
107
|
-
- <items>
|
|
108
|
-
```
|
|
109
|
-
Each bullet should be a concise, user-facing description (not a raw commit message). Consolidate related commits into single bullets where it makes sense.
|
|
110
|
-
|
|
111
|
-
4. **Ask the user to approve** the changelog entry. Offer to edit if they want changes.
|
|
112
|
-
|
|
113
|
-
5. **Write the entry** into `CHANGELOG.md`:
|
|
114
|
-
- Replace the `## [Unreleased]` section contents with `- No unreleased changes yet.`
|
|
115
|
-
- Insert the new versioned entry immediately after the `## [Unreleased]` block and before the previous release entry.
|
|
116
|
-
- Preserve all existing entries below.
|
|
117
|
-
|
|
118
|
-
## Step 4: Documentation Update (Mandatory)
|
|
119
|
-
|
|
120
|
-
**This step is NON-OPTIONAL.** Every release MUST update all documentation to reflect the current codebase state. Documentation drift is the #1 blind spot in milestone-based work — in v0.9.x, 14 files needed updates; in v0.12.0, 7 files were stale. Always assume docs are stale and verify.
|
|
121
|
-
|
|
122
|
-
### 4a. Gather what changed
|
|
123
|
-
|
|
124
|
-
```
|
|
125
|
-
git log vPREVIOUS..HEAD --oneline --no-merges
|
|
126
|
-
git diff vPREVIOUS..HEAD --name-only -- lib/ app/ config/
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
Summarize the key changes: new classes, extracted services, new components, new model methods, new migrations, config changes, breaking changes.
|
|
130
|
-
|
|
131
|
-
### 4b. Spawn Explore agent to audit all docs
|
|
132
|
-
|
|
133
|
-
Spawn an Explore agent (subagent_type: "Explore", thoroughness: "very thorough") to compare documentation against the actual source code. The agent MUST check ALL of these files:
|
|
134
|
-
|
|
135
|
-
**Project docs:**
|
|
136
|
-
|
|
137
|
-
| File | What to verify |
|
|
138
|
-
|------|---------------|
|
|
139
|
-
| `README.md` | Version references match new version, feature descriptions current, install instructions accurate |
|
|
140
|
-
| `docs/setup.md` | Version references match, setup steps accurate |
|
|
141
|
-
| `docs/upgrade.md` | Has upgrade section for THIS version with migrations, action items, breaking changes |
|
|
142
|
-
| `docs/configuration.md` | All config options documented, defaults match source code |
|
|
143
|
-
| `docs/deployment.md` | Worker/queue descriptions match current queues and job assignments |
|
|
144
|
-
| `docs/troubleshooting.md` | Covers known failure modes from recent changes |
|
|
145
|
-
|
|
146
|
-
**Skills reference files** (engine-specific documentation for Claude Code):
|
|
147
|
-
|
|
148
|
-
| Skill Reference | What to verify |
|
|
149
|
-
|----------------|---------------|
|
|
150
|
-
| `sm-configure/reference/configuration-reference.md` | All config settings and their defaults |
|
|
151
|
-
| `sm-configuration-setting/reference/settings-catalog.md` | Settings catalog with types, defaults, descriptions |
|
|
152
|
-
| `sm-job/reference/job-conventions.md` | Queue names, job assignments, concurrency defaults, service class delegation |
|
|
153
|
-
| `sm-pipeline-stage/reference/completion-handlers.md` | Pipeline handler code matches actual implementation |
|
|
154
|
-
| `sm-upgrade/reference/version-history.md` | Version transition notes for the new release |
|
|
155
|
-
| `sm-host-setup/reference/initializer-template.md` | Initializer template shows all configurable options |
|
|
156
|
-
| `sm-architecture/reference/module-map.md` | All modules, classes, components, presenters listed |
|
|
157
|
-
| `sm-domain-model/reference/model-graph.md` | All model methods, validations, scopes, associations |
|
|
158
|
-
|
|
159
|
-
The Explore agent should output a structured report: files that are current, files that need updates (with specific stale content), and what each update should contain.
|
|
160
|
-
|
|
161
|
-
### 4c. Spawn Docs agent to fix all stale files
|
|
162
|
-
|
|
163
|
-
Based on the Explore agent's report, spawn a Docs agent (subagent_type: "vbw:vbw-docs", model: "sonnet") to update ALL stale files. The Docs agent MUST:
|
|
164
|
-
|
|
165
|
-
- Read each file before editing (targeted edits, not full rewrites)
|
|
166
|
-
- Update version references to the new release version
|
|
167
|
-
- Add upgrade section for this version (migrations, action items, breaking changes)
|
|
168
|
-
- Update module maps, model graphs, job conventions to reflect current source code
|
|
169
|
-
- Add entries for any new classes, components, concerns, or model methods
|
|
170
|
-
|
|
171
|
-
### 4d. Verify and report
|
|
172
|
-
|
|
173
|
-
After the Docs agent completes, verify all files were updated:
|
|
174
|
-
```
|
|
175
|
-
git diff --name-only # Should show the updated doc files
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
Report:
|
|
179
|
-
```
|
|
180
|
-
Documentation Update: Updated N files.
|
|
181
|
-
- <file>: <what was updated>
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
If the Explore agent found 0 stale files, report:
|
|
185
|
-
```
|
|
186
|
-
Documentation Update: All files current. No updates needed.
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
Do NOT commit documentation updates separately -- they will be included in the single release commit in Step 7.
|
|
190
|
-
|
|
191
|
-
## Step 5: Sync Gemfile.lock
|
|
192
|
-
|
|
193
|
-
**CRITICAL**: After updating `version.rb`, the gemspec version changes and `Gemfile.lock` becomes stale.
|
|
194
|
-
|
|
195
|
-
1. Run `bundle install` to update `Gemfile.lock`.
|
|
196
|
-
2. Verify the output shows the new version: `Using source_monitor X.Y.Z (was X.Y.Z-1)`.
|
|
197
|
-
3. If `bundle install` fails, resolve the issue before proceeding.
|
|
198
|
-
|
|
199
|
-
## Step 6: Local Pre-flight Checks
|
|
200
|
-
|
|
201
|
-
**CRITICAL**: Run the FULL local CI equivalent BEFORE creating the release branch and pushing. Each CI failure → fix → amend → force-push cycle wastes ~5 minutes. In v0.7.0, skipping this step caused two wasted CI roundtrips. In v0.8.0, skipping ESLint and diff coverage pre-checks caused another two wasted cycles.
|
|
202
|
-
|
|
203
|
-
1. **RuboCop**: Run `bin/rubocop` and fix any violations. Auto-fix with `bin/rubocop -a` if needed. This catches lint issues (like `SpaceInsideArrayLiteralBrackets`) that would fail the CI lint job.
|
|
204
|
-
|
|
205
|
-
2. **Tests**: Run `PARALLEL_WORKERS=1 bin/rails test` and ensure all tests pass.
|
|
206
|
-
|
|
207
|
-
3. **Diff coverage pre-check**: If the release includes source code changes beyond version/changelog/lockfile (check with `git diff --name-only origin/main`), review those files for uncovered branches. The CI diff coverage gate will reject any changed source lines without test coverage. Common blind spots:
|
|
208
|
-
- `rescue StandardError` logging/fallback paths
|
|
209
|
-
- `rescue URI::InvalidURIError` nil returns
|
|
210
|
-
- Guard clauses returning early (e.g., `return if blank?`)
|
|
211
|
-
- Fallback/else branches in new methods
|
|
212
|
-
If you find uncovered source lines, write tests for them NOW before creating the release commit — it's far cheaper than a CI roundtrip.
|
|
213
|
-
|
|
214
|
-
4. **Brakeman**: Run `bin/brakeman --no-pager` and ensure zero warnings.
|
|
215
|
-
|
|
216
|
-
5. **ESLint / JS build**: If any `.js` files were changed, run `yarn build` to rebuild assets. CI runs ESLint separately on JS files and will catch issues RuboCop doesn't:
|
|
217
|
-
- Browser globals (MutationObserver, requestAnimationFrame, cancelAnimationFrame, IntersectionObserver, etc.) must be declared with `/* global ... */` comments at the top of the file.
|
|
218
|
-
- Missing `/* global */` declarations cause ESLint `no-undef` failures.
|
|
219
|
-
|
|
220
|
-
Only proceed to Step 7 when ALL five checks pass.
|
|
221
|
-
|
|
222
|
-
## Step 7: Create Release Branch with Single Squashed Commit
|
|
223
|
-
|
|
224
|
-
**IMPORTANT**: All release changes MUST be in a single commit on the release branch. This avoids pre-push hook issues where individual commits are checked for VERSION changes.
|
|
225
|
-
|
|
226
|
-
1. Create the release branch from main: `git checkout -b release/vX.Y.Z`
|
|
227
|
-
2. Stage ALL release files in one commit:
|
|
228
|
-
```
|
|
229
|
-
git add lib/source_monitor/version.rb VERSION CHANGELOG.md Gemfile.lock
|
|
230
|
-
```
|
|
231
|
-
Also stage any other files that were changed (updated skills, docs, etc.).
|
|
232
|
-
3. Create a single commit:
|
|
233
|
-
```
|
|
234
|
-
chore(release): release vX.Y.Z
|
|
235
|
-
```
|
|
236
|
-
4. Push the branch: `git push -u origin release/vX.Y.Z`
|
|
237
|
-
- If the pre-push hook blocks with a false positive (e.g., VBW files dirty in working tree despite being gitignored), use `git push -u --no-verify origin release/vX.Y.Z`. This is safe because we've verified VERSION is in the commit.
|
|
238
|
-
5. If the push fails for other reasons, diagnose and fix before proceeding.
|
|
239
|
-
|
|
240
|
-
## Step 8: Create PR
|
|
241
|
-
|
|
242
|
-
1. Create the PR using `gh pr create`:
|
|
243
|
-
- Title: `Release vX.Y.Z`
|
|
244
|
-
- Body format:
|
|
245
|
-
```
|
|
246
|
-
## Release vX.Y.Z
|
|
247
|
-
|
|
248
|
-
<paste the CHANGELOG.md entry content here>
|
|
249
|
-
|
|
250
|
-
### Release Checklist
|
|
251
|
-
- [x] Version bumped in `lib/source_monitor/version.rb` and `VERSION`
|
|
252
|
-
- [x] CHANGELOG.md updated
|
|
253
|
-
- [x] Documentation audited and updated
|
|
254
|
-
- [x] Gemfile.lock synced
|
|
255
|
-
- [ ] CI passes (lint, security, test, release_verification)
|
|
256
|
-
|
|
257
|
-
---
|
|
258
|
-
Auto-generated release PR by `/release` command.
|
|
259
|
-
```
|
|
260
|
-
- Base: `main`
|
|
261
|
-
2. Report the PR URL to the user.
|
|
262
|
-
|
|
263
|
-
## Step 9: Monitor CI Pipeline
|
|
264
|
-
|
|
265
|
-
Poll the CI status using repeated `gh pr checks <PR_NUMBER>` calls. The CI has 4 required jobs: `lint`, `security`, `test`, `release_verification` (release_verification only runs after test passes).
|
|
266
|
-
|
|
267
|
-
1. Tell the user: "Monitoring CI pipeline for PR #N... This typically takes 3-5 minutes."
|
|
268
|
-
2. Wait 30 seconds before first poll (give CI time to start).
|
|
269
|
-
3. Poll with `gh pr checks <PR_NUMBER>` every 60 seconds, up to 15 minutes.
|
|
270
|
-
4. After each poll, report progress if any jobs completed or failed.
|
|
271
|
-
|
|
272
|
-
### If CI PASSES (all checks green):
|
|
273
|
-
|
|
274
|
-
Continue to Step 10. If Step 6 (local pre-flight) was done properly, CI should pass on the first attempt.
|
|
275
|
-
|
|
276
|
-
### If CI FAILS:
|
|
277
|
-
|
|
278
|
-
1. Get the failure details: `gh pr checks <PR_NUMBER>` to identify which jobs failed.
|
|
279
|
-
2. For each failed job, fetch the log summary. Note: logs are only available after the **entire run** completes (not just one job). If `gh run view <RUN_ID> --log-failed` says "still in progress", wait and retry:
|
|
280
|
-
```
|
|
281
|
-
gh run view <RUN_ID> --log-failed | tail -80
|
|
282
|
-
```
|
|
283
|
-
3. **Common failure: diff coverage** -- If the `test` job fails on "Enforce diff coverage", it means changed source lines lack test coverage. Read the error to identify uncovered files/lines, write tests, and add them to the release commit.
|
|
284
|
-
4. **Common failure: Gemfile.lock frozen** -- If `bundle install` fails in CI with "frozen mode", you forgot to run `bundle install` locally (Step 5). Amend the commit with the updated lockfile.
|
|
285
|
-
5. **Common failure: RuboCop lint** -- If the `lint` job fails, a RuboCop violation slipped through. This should have been caught in Step 6.
|
|
286
|
-
6. **IMPORTANT: When fixing CI failures, run ALL local checks again before re-pushing.** Don't just fix the one failure — run `bin/rubocop` AND `PARALLEL_WORKERS=1 bin/rails test` to catch cascading issues. In v0.7.0, fixing a diff coverage failure introduced a RuboCop violation, requiring a third CI cycle.
|
|
287
|
-
7. Present failure details to the user and ask what to do:
|
|
288
|
-
- "Fix the issues and re-push" -- Fix issues, run ALL local checks (rubocop + tests), amend the commit (`git commit --amend --no-edit`), force push (`git push --force-with-lease --no-verify origin release/vX.Y.Z`), and restart CI monitoring.
|
|
289
|
-
- "Close the PR and abort" -- Close the PR, delete the branch, switch back to main.
|
|
290
|
-
- "Investigate manually" -- Stop and let the user handle it.
|
|
291
|
-
|
|
292
|
-
**Note on force pushes**: When force-pushing the release branch after amending, always use `--no-verify` because the pre-push hook will see the diff between old and new branch tips, and `VERSION` won't appear as changed (it's the same in both). This is expected and safe.
|
|
293
|
-
|
|
294
|
-
## Step 10: Auto-Merge PR
|
|
295
|
-
|
|
296
|
-
Once CI is green:
|
|
297
|
-
|
|
298
|
-
1. Merge the PR: `gh pr merge <PR_NUMBER> --merge --delete-branch`
|
|
299
|
-
- The `--delete-branch` flag also fetches and fast-forwards local main in most cases.
|
|
300
|
-
|
|
301
|
-
2. **Sync local main with remote**:
|
|
302
|
-
- Switch to main: `git checkout main`
|
|
303
|
-
- The `gh pr merge` command usually auto-syncs local main via fast-forward. Verify with `git log --oneline -3` that local matches remote (`git rev-parse HEAD` == `git rev-parse origin/main`).
|
|
304
|
-
- If local is behind or diverged, try `git pull origin main`.
|
|
305
|
-
- If pull fails with conflicts or divergence (rare): ask the user to run `git reset --hard origin/main` (the sandbox blocks this command). Explain this is safe because the PR is merged and all changes are on origin/main.
|
|
306
|
-
|
|
307
|
-
3. Report: "PR #N merged successfully."
|
|
308
|
-
|
|
309
|
-
## Step 11: Tag the Release
|
|
310
|
-
|
|
311
|
-
1. Verify you're on main and synced with origin.
|
|
312
|
-
2. Create an annotated tag:
|
|
313
|
-
```
|
|
314
|
-
git tag -a vX.Y.Z -m "Release vX.Y.Z"
|
|
315
|
-
```
|
|
316
|
-
3. Push the tag: `git push origin vX.Y.Z`
|
|
317
|
-
4. Create a GitHub release from the tag:
|
|
318
|
-
```
|
|
319
|
-
gh release create vX.Y.Z --title "vX.Y.Z" --notes "<changelog entry from Step 3>"
|
|
320
|
-
```
|
|
321
|
-
5. Report the release URL.
|
|
322
|
-
|
|
323
|
-
## Step 12: Build the Gem
|
|
324
|
-
|
|
325
|
-
1. Clean any old gem files. **Note**: zsh fails on `rm -f *.gem` when no files match due to `nomatch`. Use:
|
|
326
|
-
```
|
|
327
|
-
find . -maxdepth 1 -name 'source_monitor-*.gem' -delete
|
|
328
|
-
```
|
|
329
|
-
2. Build the gem: `gem build source_monitor.gemspec`
|
|
330
|
-
3. Verify the gem was built: check for `source_monitor-X.Y.Z.gem` in the project root.
|
|
331
|
-
4. Show the file size: `ls -la source_monitor-X.Y.Z.gem`
|
|
332
|
-
|
|
333
|
-
## Step 13: Gem Push Instructions
|
|
334
|
-
|
|
335
|
-
Present the final instructions to the user:
|
|
336
|
-
|
|
337
|
-
```
|
|
338
|
-
Release vX.Y.Z Complete!
|
|
339
|
-
|
|
340
|
-
Git tag: vX.Y.Z (pushed)
|
|
341
|
-
GitHub: <release URL>
|
|
342
|
-
PR: <PR URL> (merged)
|
|
343
|
-
Gem built: source_monitor-X.Y.Z.gem
|
|
344
|
-
|
|
345
|
-
To publish to RubyGems:
|
|
346
|
-
|
|
347
|
-
gem push source_monitor-X.Y.Z.gem
|
|
348
|
-
|
|
349
|
-
You'll be prompted for your RubyGems OTP code (check your authenticator app).
|
|
350
|
-
The gem has `rubygems_mfa_required` enabled, so the OTP is mandatory.
|
|
351
|
-
|
|
352
|
-
After pushing, verify at:
|
|
353
|
-
https://rubygems.org/gems/source_monitor/versions/X.Y.Z
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
Do NOT run `gem push` automatically -- always let the user handle the OTP-protected push manually.
|
|
357
|
-
|
|
358
|
-
## Error Recovery
|
|
359
|
-
|
|
360
|
-
- If any step fails unexpectedly, report what happened and where things stand.
|
|
361
|
-
- If a release branch already exists, ask the user whether to reuse or recreate it.
|
|
362
|
-
- If the tag already exists, skip tagging and inform the user.
|
|
363
|
-
- If the pre-push hook blocks, check whether `VERSION` (top-level) is in the commit diff. If it is and the hook still blocks (working tree drift from VBW), use `--no-verify`.
|
|
364
|
-
- If local main diverges from origin after merge, ask the user to run `git reset --hard origin/main`.
|
|
365
|
-
- Always leave the user on the `main` branch in a clean state when possible.
|
|
366
|
-
- If `gem build` warns about duplicate URIs (homepage_uri/source_code_uri), this is cosmetic and safe to ignore.
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
#
|
|
3
|
-
# PreToolUse hook: Block access to sensitive Rails files.
|
|
4
|
-
# Exit codes: 0 = allow, 2 = block
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
INPUT=$(cat)
|
|
8
|
-
|
|
9
|
-
# Extract file_path from JSON input
|
|
10
|
-
FILE_PATH=$(echo "$INPUT" | ruby -rjson -e 'puts JSON.parse(STDIN.read).dig("tool_input", "file_path").to_s' 2>/dev/null || echo "")
|
|
11
|
-
|
|
12
|
-
if [ -z "$FILE_PATH" ]; then
|
|
13
|
-
exit 0
|
|
14
|
-
fi
|
|
15
|
-
|
|
16
|
-
BASENAME=$(basename "$FILE_PATH")
|
|
17
|
-
|
|
18
|
-
# Block .env files
|
|
19
|
-
case "$BASENAME" in
|
|
20
|
-
.env|.env.*)
|
|
21
|
-
echo "BLOCKED: Environment file access ($BASENAME)" >&2
|
|
22
|
-
echo "Use .env.example for templates. Use Rails credentials for secrets." >&2
|
|
23
|
-
exit 2
|
|
24
|
-
;;
|
|
25
|
-
esac
|
|
26
|
-
|
|
27
|
-
# Block Rails credentials/keys
|
|
28
|
-
case "$FILE_PATH" in
|
|
29
|
-
*config/master.key|*config/credentials.yml.enc|*config/credentials/*.key)
|
|
30
|
-
echo "BLOCKED: Rails credentials file ($BASENAME)" >&2
|
|
31
|
-
echo "Use: bin/rails credentials:edit" >&2
|
|
32
|
-
exit 2
|
|
33
|
-
;;
|
|
34
|
-
esac
|
|
35
|
-
|
|
36
|
-
# Block Kamal secrets
|
|
37
|
-
case "$FILE_PATH" in
|
|
38
|
-
*.kamal/secrets)
|
|
39
|
-
echo "BLOCKED: Kamal secrets file" >&2
|
|
40
|
-
exit 2
|
|
41
|
-
;;
|
|
42
|
-
esac
|
|
43
|
-
|
|
44
|
-
# Block private keys
|
|
45
|
-
case "$BASENAME" in
|
|
46
|
-
*.pem|*.key|*.p12|*.pfx|id_rsa|id_ed25519|id_ecdsa)
|
|
47
|
-
echo "BLOCKED: Private key file ($BASENAME)" >&2
|
|
48
|
-
exit 2
|
|
49
|
-
;;
|
|
50
|
-
esac
|
|
51
|
-
|
|
52
|
-
exit 0
|
data/.claude/settings.json
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"permissions": {
|
|
3
|
-
"allow": [
|
|
4
|
-
"Bash(bin/rails test:*)",
|
|
5
|
-
"Bash(bin/rails test)",
|
|
6
|
-
"Bash(bin/rails generate:*)",
|
|
7
|
-
"Bash(bin/rails g:*)",
|
|
8
|
-
"Bash(bin/rails destroy:*)",
|
|
9
|
-
"Bash(bin/rails d:*)",
|
|
10
|
-
"Bash(bin/rails db:migrate:*)",
|
|
11
|
-
"Bash(bin/rails db:migrate)",
|
|
12
|
-
"Bash(bin/rails db:rollback:*)",
|
|
13
|
-
"Bash(bin/rails db:seed:*)",
|
|
14
|
-
"Bash(bin/rails db:schema:*)",
|
|
15
|
-
"Bash(bin/rails db:test:prepare:*)",
|
|
16
|
-
"Bash(bin/rails routes:*)",
|
|
17
|
-
"Bash(bin/rails console:*)",
|
|
18
|
-
"Bash(bin/rails runner:*)",
|
|
19
|
-
"Bash(bin/rails assets:*)",
|
|
20
|
-
"Bash(bin/rails tmp:*)",
|
|
21
|
-
"Bash(bin/rails log:*)",
|
|
22
|
-
"Bash(bin/rails server:*)",
|
|
23
|
-
"Bash(bin/dev:*)",
|
|
24
|
-
"Bash(bin/setup:*)",
|
|
25
|
-
"Bash(bin/ci:*)",
|
|
26
|
-
"Bash(bin/rubocop:*)",
|
|
27
|
-
"Bash(bin/brakeman:*)",
|
|
28
|
-
"Bash(bin/bundler-audit:*)",
|
|
29
|
-
"Bash(bundle exec:*)",
|
|
30
|
-
"Bash(bundle install:*)",
|
|
31
|
-
"Bash(bundle update:*)",
|
|
32
|
-
"Bash(bundle check:*)",
|
|
33
|
-
"Bash(bundle add:*)",
|
|
34
|
-
"Bash(bundle audit:*)",
|
|
35
|
-
"Bash(git status:*)",
|
|
36
|
-
"Bash(git log:*)",
|
|
37
|
-
"Bash(git diff:*)",
|
|
38
|
-
"Bash(git show:*)",
|
|
39
|
-
"Bash(git branch:*)",
|
|
40
|
-
"Bash(git stash:*)",
|
|
41
|
-
"Bash(ls:*)",
|
|
42
|
-
"Bash(tree:*)",
|
|
43
|
-
"Bash(wc:*)",
|
|
44
|
-
"Bash(which:*)",
|
|
45
|
-
"Bash(pwd:*)",
|
|
46
|
-
"Bash(yarn:*)",
|
|
47
|
-
"Bash(npm:*)",
|
|
48
|
-
"Bash(npx:*)",
|
|
49
|
-
"Bash(ruby:*)",
|
|
50
|
-
"Bash(bin/importmap:*)"
|
|
51
|
-
],
|
|
52
|
-
"deny": [
|
|
53
|
-
"Bash(git push --force:*)",
|
|
54
|
-
"Bash(git push -f:*)",
|
|
55
|
-
"Bash(git reset --hard:*)",
|
|
56
|
-
"Bash(sudo:*)",
|
|
57
|
-
"Bash(rm -rf /:*)",
|
|
58
|
-
"Bash(rm -rf ~:*)",
|
|
59
|
-
"Bash(rm -rf ..:*)",
|
|
60
|
-
"Bash(chmod 777:*)",
|
|
61
|
-
"Read(.env)",
|
|
62
|
-
"Read(.env.*)",
|
|
63
|
-
"Read(config/master.key)",
|
|
64
|
-
"Read(config/credentials.yml.enc)",
|
|
65
|
-
"Read(.kamal/secrets)"
|
|
66
|
-
]
|
|
67
|
-
},
|
|
68
|
-
"hooks": {
|
|
69
|
-
"PreToolUse": [
|
|
70
|
-
{
|
|
71
|
-
"matcher": "Read|Edit|Write",
|
|
72
|
-
"hooks": [
|
|
73
|
-
{
|
|
74
|
-
"type": "command",
|
|
75
|
-
"command": "bash .claude/hooks/block-secrets.sh"
|
|
76
|
-
}
|
|
77
|
-
]
|
|
78
|
-
}
|
|
79
|
-
]
|
|
80
|
-
},
|
|
81
|
-
"enabledPlugins": {
|
|
82
|
-
"frontend-design@claude-plugins-official": true,
|
|
83
|
-
"vbw@vbw-marketplace": true
|
|
84
|
-
}
|
|
85
|
-
}
|