source_monitor 0.3.3 → 0.4.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/commands/release.md +101 -58
- data/.claude/skills/sm-configure/SKILL.md +13 -2
- data/.claude/skills/sm-configure/reference/configuration-reference.md +33 -0
- data/.claude/skills/sm-host-setup/SKILL.md +15 -1
- data/.claude/skills/sm-host-setup/reference/setup-checklist.md +33 -0
- data/.claude/skills/sm-job/SKILL.md +1 -1
- data/.vbw-planning/REQUIREMENTS.md +22 -0
- data/.vbw-planning/ROADMAP.md +125 -0
- data/.vbw-planning/STATE.md +43 -0
- data/.vbw-planning/config.json +3 -1
- data/.vbw-planning/discovery.json +3 -1
- data/.vbw-planning/phases/01-generator-steps/01-CONTEXT.md +33 -0
- data/.vbw-planning/phases/01-generator-steps/01-VERIFICATION.md +86 -0
- data/.vbw-planning/phases/01-generator-steps/PLAN-01-SUMMARY.md +61 -0
- data/.vbw-planning/phases/01-generator-steps/PLAN-01.md +380 -0
- data/.vbw-planning/phases/02-verification/02-VERIFICATION.md +78 -0
- data/.vbw-planning/phases/02-verification/PLAN-01-SUMMARY.md +46 -0
- data/.vbw-planning/phases/02-verification/PLAN-01.md +500 -0
- data/.vbw-planning/phases/03-docs-alignment/03-VERIFICATION.md +89 -0
- data/.vbw-planning/phases/03-docs-alignment/PLAN-01-SUMMARY.md +48 -0
- data/.vbw-planning/phases/03-docs-alignment/PLAN-01.md +456 -0
- data/.vbw-planning/phases/04-dashboard-ux/04-VERIFICATION.md +129 -0
- data/.vbw-planning/phases/04-dashboard-ux/PLAN-01-SUMMARY.md +70 -0
- data/.vbw-planning/phases/04-dashboard-ux/PLAN-01.md +747 -0
- data/.vbw-planning/phases/05-active-storage-images/05-VERIFICATION.md +156 -0
- data/.vbw-planning/phases/05-active-storage-images/PLAN-01-SUMMARY.md +69 -0
- data/.vbw-planning/phases/05-active-storage-images/PLAN-01.md +455 -0
- data/.vbw-planning/phases/05-active-storage-images/PLAN-02-SUMMARY.md +39 -0
- data/.vbw-planning/phases/05-active-storage-images/PLAN-02.md +488 -0
- data/.vbw-planning/phases/06-netflix-feed-fix/06-VERIFICATION.md +100 -0
- data/.vbw-planning/phases/06-netflix-feed-fix/PLAN-01-SUMMARY.md +37 -0
- data/.vbw-planning/phases/06-netflix-feed-fix/PLAN-01.md +345 -0
- data/CHANGELOG.md +31 -0
- data/Gemfile.lock +1 -1
- data/VERSION +1 -1
- data/app/assets/builds/source_monitor/application.css +9 -0
- data/app/helpers/source_monitor/application_helper.rb +38 -0
- data/app/jobs/source_monitor/download_content_images_job.rb +72 -0
- data/app/models/source_monitor/item_content.rb +2 -0
- data/app/views/source_monitor/dashboard/_recent_activity.html.erb +9 -0
- data/app/views/source_monitor/items/_details.html.erb +2 -2
- data/app/views/source_monitor/logs/index.html.erb +9 -0
- data/app/views/source_monitor/sources/_details.html.erb +2 -2
- data/app/views/source_monitor/sources/_row.html.erb +1 -1
- data/docs/setup.md +10 -1
- data/docs/troubleshooting.md +38 -7
- data/lib/generators/source_monitor/install/install_generator.rb +101 -0
- data/lib/source_monitor/configuration/http_settings.rb +7 -1
- data/lib/source_monitor/configuration/images_settings.rb +37 -0
- data/lib/source_monitor/configuration.rb +3 -1
- data/lib/source_monitor/dashboard/queries/recent_activity_query.rb +16 -7
- data/lib/source_monitor/dashboard/recent_activity.rb +1 -0
- data/lib/source_monitor/dashboard/recent_activity_presenter.rb +15 -2
- data/lib/source_monitor/fetching/feed_fetcher/entry_processor.rb +13 -0
- data/lib/source_monitor/http.rb +23 -0
- data/lib/source_monitor/images/content_rewriter.rb +81 -0
- data/lib/source_monitor/images/downloader.rb +82 -0
- data/lib/source_monitor/logs/table_presenter.rb +25 -0
- data/lib/source_monitor/setup/procfile_patcher.rb +31 -0
- data/lib/source_monitor/setup/queue_config_patcher.rb +84 -0
- data/lib/source_monitor/setup/verification/recurring_schedule_verifier.rb +102 -0
- data/lib/source_monitor/setup/verification/runner.rb +1 -1
- data/lib/source_monitor/setup/verification/solid_queue_verifier.rb +1 -1
- data/lib/source_monitor/setup/workflow.rb +10 -0
- data/lib/source_monitor/version.rb +1 -1
- data/lib/source_monitor.rb +8 -0
- metadata +31 -1
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# PLAN-01 Verification Report: recurring-schedule-verifier
|
|
2
|
+
|
|
3
|
+
**Verifier:** QA Agent (deep tier, 30 checks)
|
|
4
|
+
**Date:** 2026-02-11
|
|
5
|
+
**Verdict:** PASS
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Functional Checks (1-5)
|
|
10
|
+
|
|
11
|
+
| # | Check | Result | Details |
|
|
12
|
+
|---|-------|--------|---------|
|
|
13
|
+
| 1 | `PARALLEL_WORKERS=1 bin/rails test test/lib/source_monitor/setup/verification/` | PASS | 19 runs, 65 assertions, 0 failures, 0 errors |
|
|
14
|
+
| 2 | `bin/rails test` (full suite) | PASS | 874 runs, 2926 assertions, 0 failures, 0 errors |
|
|
15
|
+
| 3 | `bin/rubocop` (modified files) | PASS | 6 files inspected, 0 offenses |
|
|
16
|
+
| 4 | `bin/brakeman --no-pager` | PASS | 0 warnings, 0 errors |
|
|
17
|
+
| 5 | `PARALLEL_WORKERS=1 bin/rails test test/lib/source_monitor/setup/verification/runner_test.rb` | PASS | 2 runs, 8 assertions, 0 failures |
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Code Review (6-20)
|
|
22
|
+
|
|
23
|
+
| # | Check | Result | Details |
|
|
24
|
+
|---|-------|--------|---------|
|
|
25
|
+
| 6 | RecurringScheduleVerifier follows same pattern as SolidQueueVerifier | PASS | Same structure: constructor with DI defaults, `call` with guard clauses + branching + rescue, private helpers, Result factory methods. Module nesting matches: `SourceMonitor::Setup::Verification::RecurringScheduleVerifier` |
|
|
26
|
+
| 7 | Constructor uses dependency injection (`task_relation`, `connection`) | PASS | `def initialize(task_relation: default_task_relation, connection: default_connection)` -- keyword args with private default methods, identical pattern to SolidQueueVerifier's `process_relation:` / `connection:` |
|
|
27
|
+
| 8 | `call` method returns Result with proper key/name/status | PASS | All paths return `Result.new(key: :recurring_schedule, name: "Recurring Schedule", status: ...)` via `ok_result`, `warning_result`, `error_result` helpers |
|
|
28
|
+
| 9 | All 5 branches covered (ok, 2x warning, 2x error + rescue) | PASS | Lines 16 (missing gem error), 17 (missing table error), 22-23 (ok), 24-28 (warning: non-SM tasks), 29-33 (warning: no tasks), 35-39 (rescue error). Six distinct branches total (5 explicit + 1 rescue), all tested |
|
|
29
|
+
| 10 | SourceMonitor task detection logic (key prefix, class_name, command) | PASS | `source_monitor_tasks` method checks: `task.key.start_with?(SOURCE_MONITOR_KEY_PREFIX)` OR `task.class_name.to_s.start_with?(SOURCE_MONITOR_NAMESPACE)` OR `task.command.to_s.include?(SOURCE_MONITOR_NAMESPACE)`. `.to_s` on class_name/command handles nil safely |
|
|
30
|
+
| 11 | `frozen_string_literal` on new files | PASS | Both `recurring_schedule_verifier.rb` (line 1) and `recurring_schedule_verifier_test.rb` (line 1) have `# frozen_string_literal: true` |
|
|
31
|
+
| 12 | Private methods properly scoped | PASS | `private` keyword at line 42, followed by `attr_reader`, `default_task_relation`, `default_connection`, `tables_present?`, `all_tasks`, `source_monitor_tasks`, `missing_gem_result`, `missing_tables_result`, `ok_result`, `warning_result`, `error_result` -- all correctly private |
|
|
32
|
+
| 13 | SolidQueueVerifier remediation mentions Procfile.dev (REQ-20) | PASS | Line 24: `"Start a Solid Queue worker with \`bin/rails solid_queue:start\` or add \`jobs: bundle exec rake solid_queue:start\` to Procfile.dev and run \`bin/dev\`"` |
|
|
33
|
+
| 14 | Runner includes RecurringScheduleVerifier in default_verifiers | PASS | `runner.rb` line 21: `[ SolidQueueVerifier.new, RecurringScheduleVerifier.new, ActionCableVerifier.new ]` |
|
|
34
|
+
| 15 | Autoload entry in lib/source_monitor.rb | PASS | Line 174: `autoload :RecurringScheduleVerifier, "source_monitor/setup/verification/recurring_schedule_verifier"` -- correctly placed within the `module Verification` block |
|
|
35
|
+
| 16 | Tests use mocked/stubbed relations (no real DB) | PASS | `FakeTask` (Struct), `FakeTaskRelation` (custom class with `all`/`to_a`), `FakeConnection` (custom class with `table_exists?`) -- no ActiveRecord, no database queries |
|
|
36
|
+
| 17 | Tests cover all branches | PASS | 7 tests: ok (key prefix), ok (command), warning (non-SM tasks), warning (no tasks), error (missing gem), error (missing table), error (unexpected exception) |
|
|
37
|
+
| 18 | No hardcoded paths | PASS | Table name comes from `task_relation.table_name`, no filesystem paths. Constants are strings ("source_monitor_", "SourceMonitor::") which are correct domain identifiers, not paths |
|
|
38
|
+
| 19 | Error handling (rescue StandardError) | PASS | Line 35: `rescue StandardError => e` wraps the entire `call` body. Returns error_result with `e.message` interpolated. Test "rescues unexpected failures" covers this with a `raise "boom"` |
|
|
39
|
+
| 20 | Result key is `:recurring_schedule` | PASS | All three result helpers (`ok_result`, `warning_result`, `error_result`) use `key: :recurring_schedule` |
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Edge Cases (21-25)
|
|
44
|
+
|
|
45
|
+
| # | Check | Result | Details |
|
|
46
|
+
|---|-------|--------|---------|
|
|
47
|
+
| 21 | What if `SolidQueue::RecurringTask` doesn't exist? | PASS | `default_task_relation` returns `nil` via `defined?` guard. `call` hits `return missing_gem_result unless task_relation` on line 16. Test "errors when solid queue gem is missing" covers this with `task_relation: nil` |
|
|
48
|
+
| 22 | What if table exists but is empty? | PASS | `all_tasks` returns `[]`, `source_monitor_tasks([])` returns `[]`, falls through to `else` branch on line 29: "No recurring tasks are registered". Test "warns when no recurring tasks are registered" covers this |
|
|
49
|
+
| 23 | What if tasks exist but none match SourceMonitor? | PASS | `sm_tasks` is empty, `tasks.any?` is true, hits `elsif` on line 24: "Recurring tasks exist but none belong to SourceMonitor". Test "warns when tasks exist but none belong to source monitor" covers this |
|
|
50
|
+
| 24 | What if connection is nil? | PASS | `tables_present?` returns `false` on line 57 (`return false unless connection`), which triggers `missing_tables_result`. If `task_relation` is also nil, the missing gem guard on line 16 fires first. Both paths are safe |
|
|
51
|
+
| 25 | What if an exception is raised during verification? | PASS | `rescue StandardError => e` at line 35 catches any exception from `all_tasks`, `source_monitor_tasks`, or `tables_present?`. Test "rescues unexpected failures" triggers this with `def all = raise "boom"` |
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Requirements (26-30)
|
|
56
|
+
|
|
57
|
+
| # | Check | Result | Details |
|
|
58
|
+
|---|-------|--------|---------|
|
|
59
|
+
| 26 | REQ-19: RecurringScheduleVerifier checks recurring task registration | PASS | Verifier queries `SolidQueue::RecurringTask`, filters by key prefix / class_name / command namespace, returns ok/warning/error based on findings |
|
|
60
|
+
| 27 | REQ-20: SolidQueueVerifier mentions Procfile.dev | PASS | Remediation string includes `Procfile.dev` and `bin/dev`. Test assertion `assert_match(/Procfile\.dev/, result.remediation)` confirms |
|
|
61
|
+
| 28 | Test count increased (was 867, should be 874+) | PASS | 874 runs (was 867 before plan, +7 new RecurringScheduleVerifier tests) |
|
|
62
|
+
| 29 | No regressions in existing tests | PASS | Full suite: 874 runs, 2926 assertions, 0 failures, 0 errors, 0 skips |
|
|
63
|
+
| 30 | Verification integrates properly with Runner flow | PASS | Runner `default_verifiers` returns 3 verifiers in order: SolidQueue, RecurringSchedule, ActionCable. Runner test stubs all 3, asserts 3 results, confirms each called exactly once |
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Summary
|
|
68
|
+
|
|
69
|
+
- **30/30 checks passed**
|
|
70
|
+
- **0 issues found**
|
|
71
|
+
- Full test suite: 874 runs, 2926 assertions, 0 failures
|
|
72
|
+
- RuboCop: 0 offenses across all modified files
|
|
73
|
+
- Brakeman: 0 warnings
|
|
74
|
+
- RecurringScheduleVerifier follows established verifier patterns exactly
|
|
75
|
+
- All branches (6 paths) tested with appropriate fakes/stubs
|
|
76
|
+
- Both REQ-19 and REQ-20 satisfied
|
|
77
|
+
|
|
78
|
+
**VERDICT: PASS**
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# PLAN-01 Summary: recurring-schedule-verifier
|
|
2
|
+
|
|
3
|
+
## Status: COMPLETE
|
|
4
|
+
|
|
5
|
+
## What Was Done
|
|
6
|
+
|
|
7
|
+
### Task 1: Create RecurringScheduleVerifier
|
|
8
|
+
- Created `lib/source_monitor/setup/verification/recurring_schedule_verifier.rb`
|
|
9
|
+
- Follows exact same pattern as SolidQueueVerifier and ActionCableVerifier
|
|
10
|
+
- Constructor accepts `task_relation:` and `connection:` for dependency injection
|
|
11
|
+
- Detects SourceMonitor tasks by key prefix (`source_monitor_`), class_name namespace (`SourceMonitor::`), or command namespace
|
|
12
|
+
- Five outcomes: ok (SM tasks found), warning (tasks exist but no SM ones), warning (no tasks at all), error (gem missing), error (table missing), plus rescue for unexpected failures
|
|
13
|
+
|
|
14
|
+
### Task 2: Enhance SolidQueueVerifier Remediation
|
|
15
|
+
- Updated remediation message in `solid_queue_verifier.rb` line 24 to mention `Procfile.dev` and `bin/dev` workflow (REQ-20)
|
|
16
|
+
- Updated test assertion to verify Procfile.dev appears in remediation
|
|
17
|
+
|
|
18
|
+
### Task 3: Add RecurringScheduleVerifier Tests
|
|
19
|
+
- Created `test/lib/source_monitor/setup/verification/recurring_schedule_verifier_test.rb`
|
|
20
|
+
- 7 tests covering all branches: ok (by key prefix), ok (by command), warning (non-SM tasks), warning (no tasks), error (missing gem), error (missing table), error (unexpected exception)
|
|
21
|
+
|
|
22
|
+
### Task 4: Wire Into Runner + Autoload
|
|
23
|
+
- Added `RecurringScheduleVerifier.new` to `Runner#default_verifiers` between SolidQueue and ActionCable
|
|
24
|
+
- Added autoload declaration in `lib/source_monitor.rb` Verification module block
|
|
25
|
+
- Updated runner_test.rb to stub 3 verifiers and assert 3 results
|
|
26
|
+
|
|
27
|
+
### Task 5: Full Suite Verification
|
|
28
|
+
- 874 runs, 2926 assertions, 0 failures, 0 errors
|
|
29
|
+
- RuboCop: 0 offenses
|
|
30
|
+
- Brakeman: 0 warnings
|
|
31
|
+
|
|
32
|
+
## Files Modified
|
|
33
|
+
- `lib/source_monitor/setup/verification/recurring_schedule_verifier.rb` (new)
|
|
34
|
+
- `lib/source_monitor/setup/verification/solid_queue_verifier.rb` (remediation update)
|
|
35
|
+
- `lib/source_monitor/setup/verification/runner.rb` (added to default_verifiers)
|
|
36
|
+
- `lib/source_monitor.rb` (autoload declaration)
|
|
37
|
+
- `test/lib/source_monitor/setup/verification/recurring_schedule_verifier_test.rb` (new, 7 tests)
|
|
38
|
+
- `test/lib/source_monitor/setup/verification/solid_queue_verifier_test.rb` (Procfile.dev assertion)
|
|
39
|
+
- `test/lib/source_monitor/setup/verification/runner_test.rb` (3-verifier expectation)
|
|
40
|
+
|
|
41
|
+
## Commit
|
|
42
|
+
- `d03e3b9` feat(verification): add RecurringScheduleVerifier and enhance SolidQueue remediation
|
|
43
|
+
|
|
44
|
+
## Requirements Satisfied
|
|
45
|
+
- REQ-19: RecurringScheduleVerifier checks SolidQueue recurring tasks registration
|
|
46
|
+
- REQ-20: SolidQueueVerifier remediation mentions Procfile.dev and bin/dev
|
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
---
|
|
2
|
+
phase: 2
|
|
3
|
+
plan: "01"
|
|
4
|
+
title: recurring-schedule-verifier
|
|
5
|
+
type: execute
|
|
6
|
+
wave: 1
|
|
7
|
+
depends_on: []
|
|
8
|
+
cross_phase_deps:
|
|
9
|
+
- phase: 1
|
|
10
|
+
artifact: "lib/source_monitor/setup/verification/solid_queue_verifier.rb"
|
|
11
|
+
reason: "Phase 2 modifies this file's remediation message (REQ-20)"
|
|
12
|
+
autonomous: true
|
|
13
|
+
effort_override: thorough
|
|
14
|
+
skills_used: []
|
|
15
|
+
files_modified:
|
|
16
|
+
- lib/source_monitor/setup/verification/recurring_schedule_verifier.rb
|
|
17
|
+
- lib/source_monitor/setup/verification/solid_queue_verifier.rb
|
|
18
|
+
- lib/source_monitor/setup/verification/runner.rb
|
|
19
|
+
- lib/source_monitor.rb
|
|
20
|
+
- test/lib/source_monitor/setup/verification/recurring_schedule_verifier_test.rb
|
|
21
|
+
- test/lib/source_monitor/setup/verification/solid_queue_verifier_test.rb
|
|
22
|
+
- test/lib/source_monitor/setup/verification/runner_test.rb
|
|
23
|
+
must_haves:
|
|
24
|
+
truths:
|
|
25
|
+
- "Running `PARALLEL_WORKERS=1 bin/rails test test/lib/source_monitor/setup/verification/recurring_schedule_verifier_test.rb` exits 0 with 0 failures"
|
|
26
|
+
- "Running `PARALLEL_WORKERS=1 bin/rails test test/lib/source_monitor/setup/verification/solid_queue_verifier_test.rb` exits 0 with 0 failures"
|
|
27
|
+
- "Running `PARALLEL_WORKERS=1 bin/rails test test/lib/source_monitor/setup/verification/runner_test.rb` exits 0 with 0 failures"
|
|
28
|
+
- "Running `bin/rubocop lib/source_monitor/setup/verification/recurring_schedule_verifier.rb lib/source_monitor/setup/verification/solid_queue_verifier.rb lib/source_monitor/setup/verification/runner.rb` exits 0 with no offenses"
|
|
29
|
+
- "Running `bin/rails test` exits 0 with 867+ runs and 0 failures"
|
|
30
|
+
artifacts:
|
|
31
|
+
- path: "lib/source_monitor/setup/verification/recurring_schedule_verifier.rb"
|
|
32
|
+
provides: "Verifier that checks SolidQueue recurring tasks registration (REQ-19)"
|
|
33
|
+
contains: "class RecurringScheduleVerifier"
|
|
34
|
+
- path: "lib/source_monitor/setup/verification/solid_queue_verifier.rb"
|
|
35
|
+
provides: "Enhanced remediation mentioning Procfile.dev (REQ-20)"
|
|
36
|
+
contains: "Procfile.dev"
|
|
37
|
+
- path: "lib/source_monitor/setup/verification/runner.rb"
|
|
38
|
+
provides: "Runner wires RecurringScheduleVerifier into default_verifiers"
|
|
39
|
+
contains: "RecurringScheduleVerifier"
|
|
40
|
+
- path: "lib/source_monitor.rb"
|
|
41
|
+
provides: "Autoload declaration for RecurringScheduleVerifier"
|
|
42
|
+
contains: "autoload :RecurringScheduleVerifier"
|
|
43
|
+
- path: "test/lib/source_monitor/setup/verification/recurring_schedule_verifier_test.rb"
|
|
44
|
+
provides: "Tests covering all RecurringScheduleVerifier branches"
|
|
45
|
+
contains: "class RecurringScheduleVerifierTest"
|
|
46
|
+
key_links:
|
|
47
|
+
- from: "recurring_schedule_verifier.rb"
|
|
48
|
+
to: "REQ-19"
|
|
49
|
+
via: "Checks whether recurring tasks are registered with SolidQueue dispatchers"
|
|
50
|
+
- from: "solid_queue_verifier.rb#warning_result remediation"
|
|
51
|
+
to: "REQ-20"
|
|
52
|
+
via: "Remediation now suggests Procfile.dev for bin/dev users"
|
|
53
|
+
- from: "runner.rb#default_verifiers"
|
|
54
|
+
to: "recurring_schedule_verifier.rb"
|
|
55
|
+
via: "Runner includes RecurringScheduleVerifier in the default verifier set"
|
|
56
|
+
---
|
|
57
|
+
<objective>
|
|
58
|
+
Add a RecurringScheduleVerifier to the verification suite that checks whether recurring tasks are registered with Solid Queue (REQ-19), and enhance the SolidQueueVerifier remediation message to suggest Procfile.dev when workers are not detected (REQ-20). Wire the new verifier into the Runner and autoload system.
|
|
59
|
+
</objective>
|
|
60
|
+
<context>
|
|
61
|
+
@lib/source_monitor/setup/verification/solid_queue_verifier.rb -- The existing verifier to enhance. Constructor accepts `process_relation:`, `connection:`, `clock:` with defaults. The `call` method returns a Result via helper methods `ok_result`, `warning_result`, `error_result`. Key change: line 24's warning_result remediation string must be updated to mention Procfile.dev. Follow the exact same pattern for the new verifier. Key: `:solid_queue`, name: `"Solid Queue"`.
|
|
62
|
+
|
|
63
|
+
@lib/source_monitor/setup/verification/action_cable_verifier.rb -- Pattern reference for verifier design. Shows constructor dependency injection, `call` method with case/when branching, rescue StandardError, and Result helpers. The new RecurringScheduleVerifier should follow the same structure.
|
|
64
|
+
|
|
65
|
+
@lib/source_monitor/setup/verification/result.rb -- Result struct with `key`, `name`, `status`, `details`, `remediation` and status predicates (`ok?`, `warning?`, `error?`). Summary aggregates results. The new verifier should use key: `:recurring_schedule`, name: `"Recurring Schedule"`.
|
|
66
|
+
|
|
67
|
+
@lib/source_monitor/setup/verification/runner.rb -- Orchestrator with `default_verifiers` returning an array. Currently `[SolidQueueVerifier.new, ActionCableVerifier.new]`. Add `RecurringScheduleVerifier.new` to this array.
|
|
68
|
+
|
|
69
|
+
@test/lib/source_monitor/setup/verification/solid_queue_verifier_test.rb -- Test pattern: uses FakeRelation and FakeConnection structs, tests all branches (ok, warning, error for missing gem, missing tables, unexpected failure). The "warns when no recent workers" test should be updated to assert the new remediation mentions Procfile.dev.
|
|
70
|
+
|
|
71
|
+
@test/lib/source_monitor/setup/verification/runner_test.rb -- Tests Runner with stub verifiers. The "uses default verifiers" test stubs SolidQueueVerifier and ActionCableVerifier via `.stub(:new, ...)`. Must add a third stub for RecurringScheduleVerifier and update assertions to expect 3 results.
|
|
72
|
+
|
|
73
|
+
@lib/source_monitor.rb lines 169-177 -- Autoload declarations for Setup::Verification module. Add `autoload :RecurringScheduleVerifier` here.
|
|
74
|
+
|
|
75
|
+
@lib/source_monitor/engine.rb lines 54-60 -- Shows how `SolidQueue::RecurringTask` is used elsewhere in the codebase. The model has columns: key, class_name, command, schedule, queue_name, static. Tasks with `class_name` starting with "SourceMonitor::" or `command` containing "SourceMonitor::" are SourceMonitor-owned entries.
|
|
76
|
+
|
|
77
|
+
@test/dummy/config/recurring.yml -- Shows the 5 recurring tasks configured for the dummy app: source_monitor_schedule_fetches, source_monitor_schedule_scrapes, source_monitor_item_cleanup, source_monitor_log_cleanup, clear_solid_queue_finished_jobs. The first 4 are SourceMonitor-owned (keys start with `source_monitor_` or class_name/command references SourceMonitor::).
|
|
78
|
+
|
|
79
|
+
**Rationale:** The RecurringScheduleVerifier checks that recurring tasks (defined in recurring.yml) are actually loaded into the solid_queue_recurring_tasks table. This catches the common failure where a user has the YAML file but the dispatcher is not configured with `recurring_schedule: config/recurring.yml`, so tasks never get registered. The verifier queries `SolidQueue::RecurringTask` and looks for entries whose key starts with `source_monitor_` OR whose class_name/command references `SourceMonitor::`.
|
|
80
|
+
|
|
81
|
+
**Key design decisions:**
|
|
82
|
+
1. Check for `SolidQueue::RecurringTask` availability (same pattern as SolidQueueVerifier checking Process)
|
|
83
|
+
2. Check table existence before querying (same pattern)
|
|
84
|
+
3. Query for any recurring tasks, then filter for SourceMonitor-specific ones
|
|
85
|
+
4. Four outcomes: (a) ok if SM tasks found, (b) warning if tasks exist but no SM ones, (c) warning if no tasks at all, (d) error if SolidQueue unavailable
|
|
86
|
+
5. SourceMonitor task detection: key starts with `source_monitor_` OR class_name starts with `SourceMonitor::` OR command contains `SourceMonitor::`
|
|
87
|
+
6. Inject `task_relation:` and `connection:` via constructor for testability
|
|
88
|
+
</context>
|
|
89
|
+
<tasks>
|
|
90
|
+
<task type="auto">
|
|
91
|
+
<name>create-recurring-schedule-verifier</name>
|
|
92
|
+
<files>
|
|
93
|
+
lib/source_monitor/setup/verification/recurring_schedule_verifier.rb
|
|
94
|
+
</files>
|
|
95
|
+
<action>
|
|
96
|
+
Create a new file `lib/source_monitor/setup/verification/recurring_schedule_verifier.rb` following the exact pattern of SolidQueueVerifier and ActionCableVerifier.
|
|
97
|
+
|
|
98
|
+
```ruby
|
|
99
|
+
# frozen_string_literal: true
|
|
100
|
+
|
|
101
|
+
module SourceMonitor
|
|
102
|
+
module Setup
|
|
103
|
+
module Verification
|
|
104
|
+
class RecurringScheduleVerifier
|
|
105
|
+
SOURCE_MONITOR_KEY_PREFIX = "source_monitor_"
|
|
106
|
+
SOURCE_MONITOR_NAMESPACE = "SourceMonitor::"
|
|
107
|
+
|
|
108
|
+
def initialize(task_relation: default_task_relation, connection: default_connection)
|
|
109
|
+
@task_relation = task_relation
|
|
110
|
+
@connection = connection
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def call
|
|
114
|
+
return missing_gem_result unless task_relation
|
|
115
|
+
return missing_tables_result unless tables_present?
|
|
116
|
+
|
|
117
|
+
tasks = all_tasks
|
|
118
|
+
sm_tasks = source_monitor_tasks(tasks)
|
|
119
|
+
|
|
120
|
+
if sm_tasks.any?
|
|
121
|
+
ok_result("#{sm_tasks.size} SourceMonitor recurring task(s) registered")
|
|
122
|
+
elsif tasks.any?
|
|
123
|
+
warning_result(
|
|
124
|
+
"Recurring tasks exist but none belong to SourceMonitor",
|
|
125
|
+
"Add SourceMonitor entries to config/recurring.yml and ensure the dispatcher has `recurring_schedule: config/recurring.yml`"
|
|
126
|
+
)
|
|
127
|
+
else
|
|
128
|
+
warning_result(
|
|
129
|
+
"No recurring tasks are registered with Solid Queue",
|
|
130
|
+
"Configure a dispatcher with `recurring_schedule: config/recurring.yml` in config/queue.yml and ensure recurring.yml contains SourceMonitor task entries"
|
|
131
|
+
)
|
|
132
|
+
end
|
|
133
|
+
rescue StandardError => e
|
|
134
|
+
error_result(
|
|
135
|
+
"Recurring schedule verification failed: #{e.message}",
|
|
136
|
+
"Verify Solid Queue migrations are up to date and the dispatcher is configured with recurring_schedule"
|
|
137
|
+
)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
private
|
|
141
|
+
|
|
142
|
+
attr_reader :task_relation, :connection
|
|
143
|
+
|
|
144
|
+
def default_task_relation
|
|
145
|
+
SolidQueue::RecurringTask if defined?(SolidQueue::RecurringTask)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def default_connection
|
|
149
|
+
SolidQueue::RecurringTask.connection if defined?(SolidQueue::RecurringTask)
|
|
150
|
+
rescue StandardError
|
|
151
|
+
nil
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def tables_present?
|
|
155
|
+
return false unless connection
|
|
156
|
+
|
|
157
|
+
connection.table_exists?(task_relation.table_name)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def all_tasks
|
|
161
|
+
task_relation.all.to_a
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def source_monitor_tasks(tasks)
|
|
165
|
+
tasks.select do |task|
|
|
166
|
+
task.key.start_with?(SOURCE_MONITOR_KEY_PREFIX) ||
|
|
167
|
+
task.class_name.to_s.start_with?(SOURCE_MONITOR_NAMESPACE) ||
|
|
168
|
+
task.command.to_s.include?(SOURCE_MONITOR_NAMESPACE)
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def missing_gem_result
|
|
173
|
+
error_result(
|
|
174
|
+
"Solid Queue gem is not available",
|
|
175
|
+
"Add `solid_queue` to your Gemfile and bundle install"
|
|
176
|
+
)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def missing_tables_result
|
|
180
|
+
error_result(
|
|
181
|
+
"Solid Queue recurring tasks table is missing",
|
|
182
|
+
"Run `rails solid_queue:install` or copy the engine's Solid Queue migration"
|
|
183
|
+
)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def ok_result(details)
|
|
187
|
+
Result.new(key: :recurring_schedule, name: "Recurring Schedule", status: :ok, details: details)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def warning_result(details, remediation)
|
|
191
|
+
Result.new(key: :recurring_schedule, name: "Recurring Schedule", status: :warning, details: details, remediation: remediation)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def error_result(details, remediation)
|
|
195
|
+
Result.new(key: :recurring_schedule, name: "Recurring Schedule", status: :error, details: details, remediation: remediation)
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Key design points:
|
|
204
|
+
- Constructor accepts `task_relation:` and `connection:` for dependency injection (testability)
|
|
205
|
+
- Defaults to `SolidQueue::RecurringTask` if available
|
|
206
|
+
- `all_tasks` fetches all recurring tasks, then `source_monitor_tasks` filters by key prefix, class_name namespace, or command namespace
|
|
207
|
+
- Three-tier result: ok (SM tasks found), warning (tasks exist but no SM ones OR no tasks at all), error (gem/table missing or unexpected failure)
|
|
208
|
+
- Same rescue StandardError pattern as other verifiers
|
|
209
|
+
</action>
|
|
210
|
+
<verify>
|
|
211
|
+
Read the created file and confirm: (a) class is in the correct module nesting, (b) constructor follows dependency injection pattern, (c) `call` method handles all 5 outcomes (missing gem, missing tables, SM tasks found, non-SM tasks only, no tasks), (d) helper methods are private, (e) Result key is `:recurring_schedule`.
|
|
212
|
+
</verify>
|
|
213
|
+
<done>
|
|
214
|
+
RecurringScheduleVerifier created with full branch coverage: missing gem, missing tables, SM tasks found (ok), non-SM tasks only (warning), no tasks (warning), unexpected error.
|
|
215
|
+
</done>
|
|
216
|
+
</task>
|
|
217
|
+
<task type="auto">
|
|
218
|
+
<name>enhance-solid-queue-verifier-remediation</name>
|
|
219
|
+
<files>
|
|
220
|
+
lib/source_monitor/setup/verification/solid_queue_verifier.rb
|
|
221
|
+
test/lib/source_monitor/setup/verification/solid_queue_verifier_test.rb
|
|
222
|
+
</files>
|
|
223
|
+
<action>
|
|
224
|
+
**Modify `lib/source_monitor/setup/verification/solid_queue_verifier.rb`:**
|
|
225
|
+
|
|
226
|
+
Change the remediation string on line 24 from:
|
|
227
|
+
```ruby
|
|
228
|
+
"Start a Solid Queue worker with `bin/rails solid_queue:start` and ensure it stays running"
|
|
229
|
+
```
|
|
230
|
+
to:
|
|
231
|
+
```ruby
|
|
232
|
+
"Start a Solid Queue worker with `bin/rails solid_queue:start` or add `jobs: bundle exec rake solid_queue:start` to Procfile.dev and run `bin/dev`"
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
This is a single-line change in the `call` method's warning_result call (the "no recent workers" branch).
|
|
236
|
+
|
|
237
|
+
**Modify `test/lib/source_monitor/setup/verification/solid_queue_verifier_test.rb`:**
|
|
238
|
+
|
|
239
|
+
Update the "warns when no recent workers" test to also assert the remediation message mentions Procfile.dev:
|
|
240
|
+
```ruby
|
|
241
|
+
assert_match(/Procfile\.dev/, result.remediation)
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Add this assertion after the existing `assert_match(/No Solid Queue workers/, result.details)` line.
|
|
245
|
+
</action>
|
|
246
|
+
<verify>
|
|
247
|
+
Run `PARALLEL_WORKERS=1 bin/rails test test/lib/source_monitor/setup/verification/solid_queue_verifier_test.rb` -- all 5 tests pass. Run `bin/rubocop lib/source_monitor/setup/verification/solid_queue_verifier.rb` -- 0 offenses. Grep for "Procfile.dev" in the verifier file confirms the new remediation text.
|
|
248
|
+
</verify>
|
|
249
|
+
<done>
|
|
250
|
+
SolidQueueVerifier remediation now mentions Procfile.dev with the `bin/dev` workflow. Existing test updated to assert the new message content. REQ-20 satisfied.
|
|
251
|
+
</done>
|
|
252
|
+
</task>
|
|
253
|
+
<task type="auto">
|
|
254
|
+
<name>add-recurring-schedule-verifier-tests</name>
|
|
255
|
+
<files>
|
|
256
|
+
test/lib/source_monitor/setup/verification/recurring_schedule_verifier_test.rb
|
|
257
|
+
</files>
|
|
258
|
+
<action>
|
|
259
|
+
Create a new test file following the exact pattern from `solid_queue_verifier_test.rb`:
|
|
260
|
+
|
|
261
|
+
```ruby
|
|
262
|
+
# frozen_string_literal: true
|
|
263
|
+
|
|
264
|
+
require "test_helper"
|
|
265
|
+
|
|
266
|
+
module SourceMonitor
|
|
267
|
+
module Setup
|
|
268
|
+
module Verification
|
|
269
|
+
class RecurringScheduleVerifierTest < ActiveSupport::TestCase
|
|
270
|
+
# Fake task struct matching SolidQueue::RecurringTask's interface
|
|
271
|
+
FakeTask = Struct.new(:key, :class_name, :command, keyword_init: true)
|
|
272
|
+
|
|
273
|
+
# Fake relation that returns tasks and supports table_name
|
|
274
|
+
class FakeTaskRelation
|
|
275
|
+
attr_reader :table_name
|
|
276
|
+
|
|
277
|
+
def initialize(tasks, table_name: "solid_queue_recurring_tasks")
|
|
278
|
+
@tasks = tasks
|
|
279
|
+
@table_name = table_name
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def all
|
|
283
|
+
self
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def to_a
|
|
287
|
+
@tasks
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
class FakeConnection
|
|
292
|
+
def initialize(tables: [])
|
|
293
|
+
@tables = tables
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def table_exists?(name)
|
|
297
|
+
@tables.include?(name)
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
test "returns ok when source monitor recurring tasks are registered" do
|
|
302
|
+
tasks = [
|
|
303
|
+
FakeTask.new(key: "source_monitor_schedule_fetches", class_name: "SourceMonitor::ScheduleFetchesJob", command: nil),
|
|
304
|
+
FakeTask.new(key: "source_monitor_item_cleanup", class_name: "SourceMonitor::ItemCleanupJob", command: nil)
|
|
305
|
+
]
|
|
306
|
+
relation = FakeTaskRelation.new(tasks)
|
|
307
|
+
connection = FakeConnection.new(tables: ["solid_queue_recurring_tasks"])
|
|
308
|
+
|
|
309
|
+
result = RecurringScheduleVerifier.new(task_relation: relation, connection: connection).call
|
|
310
|
+
|
|
311
|
+
assert_equal :ok, result.status
|
|
312
|
+
assert_match(/2 SourceMonitor recurring task/, result.details)
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
test "returns ok when source monitor tasks detected by command" do
|
|
316
|
+
tasks = [
|
|
317
|
+
FakeTask.new(key: "source_monitor_schedule_scrapes", class_name: nil, command: "SourceMonitor::Scraping::Scheduler.run(limit: 100)")
|
|
318
|
+
]
|
|
319
|
+
relation = FakeTaskRelation.new(tasks)
|
|
320
|
+
connection = FakeConnection.new(tables: ["solid_queue_recurring_tasks"])
|
|
321
|
+
|
|
322
|
+
result = RecurringScheduleVerifier.new(task_relation: relation, connection: connection).call
|
|
323
|
+
|
|
324
|
+
assert_equal :ok, result.status
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
test "warns when tasks exist but none belong to source monitor" do
|
|
328
|
+
tasks = [
|
|
329
|
+
FakeTask.new(key: "other_app_cleanup", class_name: "OtherApp::CleanupJob", command: nil)
|
|
330
|
+
]
|
|
331
|
+
relation = FakeTaskRelation.new(tasks)
|
|
332
|
+
connection = FakeConnection.new(tables: ["solid_queue_recurring_tasks"])
|
|
333
|
+
|
|
334
|
+
result = RecurringScheduleVerifier.new(task_relation: relation, connection: connection).call
|
|
335
|
+
|
|
336
|
+
assert_equal :warning, result.status
|
|
337
|
+
assert_match(/none belong to SourceMonitor/, result.details)
|
|
338
|
+
assert_match(/recurring\.yml/, result.remediation)
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
test "warns when no recurring tasks are registered" do
|
|
342
|
+
relation = FakeTaskRelation.new([])
|
|
343
|
+
connection = FakeConnection.new(tables: ["solid_queue_recurring_tasks"])
|
|
344
|
+
|
|
345
|
+
result = RecurringScheduleVerifier.new(task_relation: relation, connection: connection).call
|
|
346
|
+
|
|
347
|
+
assert_equal :warning, result.status
|
|
348
|
+
assert_match(/No recurring tasks are registered/, result.details)
|
|
349
|
+
assert_match(/recurring_schedule/, result.remediation)
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
test "errors when solid queue gem is missing" do
|
|
353
|
+
result = RecurringScheduleVerifier.new(task_relation: nil, connection: nil).call
|
|
354
|
+
|
|
355
|
+
assert_equal :error, result.status
|
|
356
|
+
assert_match(/gem is not available/, result.details)
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
test "errors when recurring tasks table is missing" do
|
|
360
|
+
relation = FakeTaskRelation.new([], table_name: "solid_queue_recurring_tasks")
|
|
361
|
+
connection = FakeConnection.new(tables: [])
|
|
362
|
+
|
|
363
|
+
result = RecurringScheduleVerifier.new(task_relation: relation, connection: connection).call
|
|
364
|
+
|
|
365
|
+
assert_equal :error, result.status
|
|
366
|
+
assert_match(/table is missing/, result.details)
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
test "rescues unexpected failures and reports remediation" do
|
|
370
|
+
relation = Class.new do
|
|
371
|
+
def table_name = "solid_queue_recurring_tasks"
|
|
372
|
+
def all = raise "boom"
|
|
373
|
+
end.new
|
|
374
|
+
connection = FakeConnection.new(tables: ["solid_queue_recurring_tasks"])
|
|
375
|
+
|
|
376
|
+
result = RecurringScheduleVerifier.new(task_relation: relation, connection: connection).call
|
|
377
|
+
|
|
378
|
+
assert_equal :error, result.status
|
|
379
|
+
assert_match(/verification failed/i, result.details)
|
|
380
|
+
assert_match(/dispatcher/, result.remediation)
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
7 tests covering all branches: ok (by key prefix), ok (by command), warning (non-SM tasks), warning (no tasks), error (missing gem), error (missing table), error (unexpected exception).
|
|
389
|
+
</action>
|
|
390
|
+
<verify>
|
|
391
|
+
Run `PARALLEL_WORKERS=1 bin/rails test test/lib/source_monitor/setup/verification/recurring_schedule_verifier_test.rb` -- all 7 tests pass. Run `bin/rubocop test/lib/source_monitor/setup/verification/recurring_schedule_verifier_test.rb` -- 0 offenses.
|
|
392
|
+
</verify>
|
|
393
|
+
<done>
|
|
394
|
+
7 tests covering all RecurringScheduleVerifier branches pass. RuboCop clean.
|
|
395
|
+
</done>
|
|
396
|
+
</task>
|
|
397
|
+
<task type="auto">
|
|
398
|
+
<name>wire-into-runner-and-autoload</name>
|
|
399
|
+
<files>
|
|
400
|
+
lib/source_monitor/setup/verification/runner.rb
|
|
401
|
+
lib/source_monitor.rb
|
|
402
|
+
test/lib/source_monitor/setup/verification/runner_test.rb
|
|
403
|
+
</files>
|
|
404
|
+
<action>
|
|
405
|
+
**Modify `lib/source_monitor/setup/verification/runner.rb`:**
|
|
406
|
+
|
|
407
|
+
Add `RecurringScheduleVerifier.new` to the `default_verifiers` array (line 21). The array should become:
|
|
408
|
+
```ruby
|
|
409
|
+
def default_verifiers
|
|
410
|
+
[ SolidQueueVerifier.new, RecurringScheduleVerifier.new, ActionCableVerifier.new ]
|
|
411
|
+
end
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
Place RecurringScheduleVerifier between SolidQueue and ActionCable -- it logically groups with SolidQueue (both check SQ state) and should run after the worker heartbeat check but before the ActionCable check.
|
|
415
|
+
|
|
416
|
+
**Modify `lib/source_monitor.rb`:**
|
|
417
|
+
|
|
418
|
+
Add the autoload declaration in the `module Verification` block (around line 174), after the ActionCableVerifier line:
|
|
419
|
+
```ruby
|
|
420
|
+
autoload :RecurringScheduleVerifier, "source_monitor/setup/verification/recurring_schedule_verifier"
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
**Modify `test/lib/source_monitor/setup/verification/runner_test.rb`:**
|
|
424
|
+
|
|
425
|
+
Update the "uses default verifiers" test:
|
|
426
|
+
1. Add a recurring_result: `recurring_result = Result.new(key: :recurring_schedule, name: "Recurring Schedule", status: :ok, details: "ok")`
|
|
427
|
+
2. Add a recurring_double: `recurring_double = verifier_double.new(recurring_result)`
|
|
428
|
+
3. Add a third stub inside the existing stub blocks: `RecurringScheduleVerifier.stub(:new, ->(*) { recurring_double }) do`
|
|
429
|
+
4. Update assertion: `assert_equal 3, summary.results.size`
|
|
430
|
+
5. Add: `assert_equal 1, recurring_double.calls`
|
|
431
|
+
</action>
|
|
432
|
+
<verify>
|
|
433
|
+
Run `PARALLEL_WORKERS=1 bin/rails test test/lib/source_monitor/setup/verification/runner_test.rb` -- all tests pass. Grep for `RecurringScheduleVerifier` in runner.rb and source_monitor.rb confirms wiring.
|
|
434
|
+
</verify>
|
|
435
|
+
<done>
|
|
436
|
+
RecurringScheduleVerifier wired into Runner.default_verifiers and autoloaded from lib/source_monitor.rb. Runner test updated to expect 3 verifiers.
|
|
437
|
+
</done>
|
|
438
|
+
</task>
|
|
439
|
+
<task type="auto">
|
|
440
|
+
<name>full-suite-verification</name>
|
|
441
|
+
<files>
|
|
442
|
+
lib/source_monitor/setup/verification/recurring_schedule_verifier.rb
|
|
443
|
+
lib/source_monitor/setup/verification/solid_queue_verifier.rb
|
|
444
|
+
lib/source_monitor/setup/verification/runner.rb
|
|
445
|
+
test/lib/source_monitor/setup/verification/recurring_schedule_verifier_test.rb
|
|
446
|
+
test/lib/source_monitor/setup/verification/solid_queue_verifier_test.rb
|
|
447
|
+
test/lib/source_monitor/setup/verification/runner_test.rb
|
|
448
|
+
</files>
|
|
449
|
+
<action>
|
|
450
|
+
Run the full test suite and linting to confirm no regressions:
|
|
451
|
+
|
|
452
|
+
1. `PARALLEL_WORKERS=1 bin/rails test test/lib/source_monitor/setup/verification/` -- all verification tests pass (existing + new)
|
|
453
|
+
2. `bin/rails test` -- full suite passes with 867+ runs and 0 failures
|
|
454
|
+
3. `bin/rubocop lib/source_monitor/setup/verification/ test/lib/source_monitor/setup/verification/` -- zero offenses
|
|
455
|
+
4. `bin/brakeman --no-pager` -- zero warnings
|
|
456
|
+
5. Review the final state of all modified files to confirm:
|
|
457
|
+
- RecurringScheduleVerifier follows the exact same pattern as SolidQueueVerifier
|
|
458
|
+
- SolidQueueVerifier remediation mentions Procfile.dev
|
|
459
|
+
- Runner.default_verifiers includes all 3 verifiers
|
|
460
|
+
- Autoload declaration is in the correct module block
|
|
461
|
+
- All tests cover the expected branches
|
|
462
|
+
|
|
463
|
+
If any test failures or RuboCop offenses are found, fix them before completing.
|
|
464
|
+
</action>
|
|
465
|
+
<verify>
|
|
466
|
+
`bin/rails test` exits 0 with 867+ runs, 0 failures. `bin/rubocop` exits 0 with 0 offenses. `bin/brakeman --no-pager` exits 0 with 0 warnings.
|
|
467
|
+
</verify>
|
|
468
|
+
<done>
|
|
469
|
+
Full test suite passes. RuboCop clean. Brakeman clean. All REQ-19, REQ-20 acceptance criteria met.
|
|
470
|
+
</done>
|
|
471
|
+
</task>
|
|
472
|
+
</tasks>
|
|
473
|
+
<verification>
|
|
474
|
+
1. `PARALLEL_WORKERS=1 bin/rails test test/lib/source_monitor/setup/verification/recurring_schedule_verifier_test.rb` -- 7 tests pass
|
|
475
|
+
2. `PARALLEL_WORKERS=1 bin/rails test test/lib/source_monitor/setup/verification/solid_queue_verifier_test.rb` -- 5 tests pass with updated assertion
|
|
476
|
+
3. `PARALLEL_WORKERS=1 bin/rails test test/lib/source_monitor/setup/verification/runner_test.rb` -- 2 tests pass with 3-verifier expectation
|
|
477
|
+
4. `bin/rails test` -- 867+ runs, 0 failures
|
|
478
|
+
5. `bin/rubocop` -- 0 offenses
|
|
479
|
+
6. `bin/brakeman --no-pager` -- 0 warnings
|
|
480
|
+
7. `grep -n 'class RecurringScheduleVerifier' lib/source_monitor/setup/verification/recurring_schedule_verifier.rb` returns a match
|
|
481
|
+
8. `grep -n 'Procfile.dev' lib/source_monitor/setup/verification/solid_queue_verifier.rb` returns a match
|
|
482
|
+
9. `grep -n 'RecurringScheduleVerifier' lib/source_monitor/setup/verification/runner.rb` returns a match
|
|
483
|
+
10. `grep -n 'RecurringScheduleVerifier' lib/source_monitor.rb` returns a match
|
|
484
|
+
</verification>
|
|
485
|
+
<success_criteria>
|
|
486
|
+
- RecurringScheduleVerifier returns ok when SourceMonitor recurring tasks are registered (REQ-19)
|
|
487
|
+
- RecurringScheduleVerifier warns when recurring tasks exist but none belong to SourceMonitor (REQ-19)
|
|
488
|
+
- RecurringScheduleVerifier warns when no recurring tasks are registered at all (REQ-19)
|
|
489
|
+
- RecurringScheduleVerifier errors when SolidQueue gem is missing (REQ-19)
|
|
490
|
+
- RecurringScheduleVerifier errors when recurring tasks table is missing (REQ-19)
|
|
491
|
+
- SolidQueueVerifier remediation mentions Procfile.dev and bin/dev (REQ-20)
|
|
492
|
+
- RecurringScheduleVerifier is included in Runner.default_verifiers
|
|
493
|
+
- RecurringScheduleVerifier is autoloaded from lib/source_monitor.rb
|
|
494
|
+
- All existing tests continue to pass (no regressions)
|
|
495
|
+
- 7+ new RecurringScheduleVerifier tests cover all branches
|
|
496
|
+
- RuboCop clean, Brakeman clean
|
|
497
|
+
</success_criteria>
|
|
498
|
+
<output>
|
|
499
|
+
.vbw-planning/phases/02-verification/PLAN-01-SUMMARY.md
|
|
500
|
+
</output>
|