fun_ci 1.2.1 → 2.0.1

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.
Files changed (228) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +236 -0
  3. data/README.md +182 -59
  4. data/lib/fun_ci/agent/age.rb +15 -0
  5. data/lib/fun_ci/agent/command_support.rb +27 -0
  6. data/lib/fun_ci/agent/commands.rb +27 -0
  7. data/lib/fun_ci/agent/context.rb +10 -0
  8. data/lib/fun_ci/agent/digest.rb +49 -0
  9. data/lib/fun_ci/agent/events.rb +47 -0
  10. data/lib/fun_ci/agent/events_command.rb +61 -0
  11. data/lib/fun_ci/agent/evidence_text.rb +46 -0
  12. data/lib/fun_ci/agent/exit_code.rb +11 -0
  13. data/lib/fun_ci/agent/git.rb +32 -0
  14. data/lib/fun_ci/agent/live_pipeline.rb +35 -0
  15. data/lib/fun_ci/agent/options.rb +75 -0
  16. data/lib/fun_ci/agent/output.rb +81 -0
  17. data/lib/fun_ci/agent/report_stage.rb +71 -0
  18. data/lib/fun_ci/agent/reports.rb +47 -0
  19. data/lib/fun_ci/agent/run_report.rb +30 -0
  20. data/lib/fun_ci/agent/runs_command.rb +34 -0
  21. data/lib/fun_ci/agent/runs_text.rb +27 -0
  22. data/lib/fun_ci/agent/snapshots.rb +39 -0
  23. data/lib/fun_ci/agent/stage_summary.rb +30 -0
  24. data/lib/fun_ci/agent/status_command.rb +36 -0
  25. data/lib/fun_ci/agent/status_json.rb +27 -0
  26. data/lib/fun_ci/agent/status_text.rb +37 -0
  27. data/lib/fun_ci/agent/system_clock.rb +11 -0
  28. data/lib/fun_ci/agent/verdict.rb +32 -0
  29. data/lib/fun_ci/agent/wait_command.rb +71 -0
  30. data/lib/fun_ci/agent/waiting.rb +32 -0
  31. data/lib/fun_ci/agent/why_command.rb +50 -0
  32. data/lib/fun_ci/agent/why_json.rb +35 -0
  33. data/lib/fun_ci/agent/why_text.rb +43 -0
  34. data/lib/fun_ci/cli.rb +72 -94
  35. data/lib/fun_ci/cli_help.rb +65 -0
  36. data/lib/fun_ci/console/board_data.rb +66 -0
  37. data/lib/fun_ci/console/board_heartbeat.rb +40 -0
  38. data/lib/fun_ci/console/console_events.rb +20 -0
  39. data/lib/fun_ci/console/console_log.rb +26 -0
  40. data/lib/fun_ci/console/console_loop.rb +41 -0
  41. data/lib/fun_ci/console/console_session.rb +82 -0
  42. data/lib/fun_ci/console/console_state.rb +42 -0
  43. data/lib/fun_ci/console/key_handler.rb +73 -0
  44. data/lib/fun_ci/console/launcher.rb +43 -0
  45. data/lib/fun_ci/console/milestone_events.rb +38 -0
  46. data/lib/fun_ci/console/milestones.rb +25 -0
  47. data/lib/fun_ci/console/renderer_lookup.rb +51 -0
  48. data/lib/fun_ci/console/renderer_process.rb +60 -0
  49. data/lib/fun_ci/console/run_message.rb +33 -0
  50. data/lib/fun_ci/console/stage_change_detector.rb +32 -0
  51. data/lib/fun_ci/console/stage_events.rb +31 -0
  52. data/lib/fun_ci/console/stop_report.rb +39 -0
  53. data/lib/fun_ci/console/streak_counter.rb +19 -0
  54. data/lib/fun_ci/console/view.rb +47 -0
  55. data/lib/fun_ci/evidence/about.rb +12 -0
  56. data/lib/fun_ci/evidence/about_stage.rb +29 -0
  57. data/lib/fun_ci/evidence/caps.rb +77 -0
  58. data/lib/fun_ci/evidence/catalog.rb +83 -0
  59. data/lib/fun_ci/evidence/collector.rb +95 -0
  60. data/lib/fun_ci/evidence/command_output.rb +45 -0
  61. data/lib/fun_ci/evidence/command_reading.rb +38 -0
  62. data/lib/fun_ci/evidence/command_runner.rb +75 -0
  63. data/lib/fun_ci/evidence/context.rb +21 -0
  64. data/lib/fun_ci/evidence/context_document.rb +29 -0
  65. data/lib/fun_ci/evidence/deadline.rb +15 -0
  66. data/lib/fun_ci/evidence/detection.rb +82 -0
  67. data/lib/fun_ci/evidence/document.rb +59 -0
  68. data/lib/fun_ci/evidence/extract_command.rb +83 -0
  69. data/lib/fun_ci/evidence/extract_options.rb +45 -0
  70. data/lib/fun_ci/evidence/extraction.rb +54 -0
  71. data/lib/fun_ci/evidence/extractors/command.rb +52 -0
  72. data/lib/fun_ci/evidence/extractors/grep.rb +49 -0
  73. data/lib/fun_ci/evidence/extractors/json_log.rb +45 -0
  74. data/lib/fun_ci/evidence/extractors/junit_files.rb +32 -0
  75. data/lib/fun_ci/evidence/extractors/last_lines.rb +25 -0
  76. data/lib/fun_ci/evidence/extractors/log_file.rb +62 -0
  77. data/lib/fun_ci/evidence/extractors/process_tree.rb +51 -0
  78. data/lib/fun_ci/evidence/extractors/section.rb +49 -0
  79. data/lib/fun_ci/evidence/findings.rb +14 -0
  80. data/lib/fun_ci/evidence/line_ranges.rb +21 -0
  81. data/lib/fun_ci/evidence/line_scan.rb +22 -0
  82. data/lib/fun_ci/evidence/log_record.rb +58 -0
  83. data/lib/fun_ci/evidence/masking.rb +55 -0
  84. data/lib/fun_ci/evidence/option_check.rb +53 -0
  85. data/lib/fun_ci/evidence/outcome.rb +15 -0
  86. data/lib/fun_ci/evidence/patterns.rb +22 -0
  87. data/lib/fun_ci/evidence/presets/README.md +7 -0
  88. data/lib/fun_ci/evidence/presets/bun-test.yml +6 -0
  89. data/lib/fun_ci/evidence/presets/cargo-test.yml +6 -0
  90. data/lib/fun_ci/evidence/presets/dart-test.yml +6 -0
  91. data/lib/fun_ci/evidence/presets/deno-test.yml +6 -0
  92. data/lib/fun_ci/evidence/presets/dotnet-test.yml +6 -0
  93. data/lib/fun_ci/evidence/presets/ecs.yml +3 -0
  94. data/lib/fun_ci/evidence/presets/eslint.yml +6 -0
  95. data/lib/fun_ci/evidence/presets/exunit.yml +6 -0
  96. data/lib/fun_ci/evidence/presets/gcc.yml +6 -0
  97. data/lib/fun_ci/evidence/presets/go-build.yml +5 -0
  98. data/lib/fun_ci/evidence/presets/go-test.yml +6 -0
  99. data/lib/fun_ci/evidence/presets/gradle.yml +6 -0
  100. data/lib/fun_ci/evidence/presets/gtest.yml +6 -0
  101. data/lib/fun_ci/evidence/presets/jest.yml +6 -0
  102. data/lib/fun_ci/evidence/presets/logstash.yml +3 -0
  103. data/lib/fun_ci/evidence/presets/maven.yml +6 -0
  104. data/lib/fun_ci/evidence/presets/minitest.yml +6 -0
  105. data/lib/fun_ci/evidence/presets/mocha.yml +6 -0
  106. data/lib/fun_ci/evidence/presets/mypy.yml +6 -0
  107. data/lib/fun_ci/evidence/presets/node-test.yml +6 -0
  108. data/lib/fun_ci/evidence/presets/phpunit.yml +6 -0
  109. data/lib/fun_ci/evidence/presets/pino.yml +5 -0
  110. data/lib/fun_ci/evidence/presets/prove.yml +6 -0
  111. data/lib/fun_ci/evidence/presets/pytest.yml +6 -0
  112. data/lib/fun_ci/evidence/presets/rspec.yml +6 -0
  113. data/lib/fun_ci/evidence/presets/rubocop.yml +6 -0
  114. data/lib/fun_ci/evidence/presets/ruff.yml +6 -0
  115. data/lib/fun_ci/evidence/presets/rustc.yml +6 -0
  116. data/lib/fun_ci/evidence/presets/shellcheck.yml +5 -0
  117. data/lib/fun_ci/evidence/presets/structlog.yml +4 -0
  118. data/lib/fun_ci/evidence/presets/swift-test.yml +5 -0
  119. data/lib/fun_ci/evidence/presets/tsc.yml +6 -0
  120. data/lib/fun_ci/evidence/presets/unittest.yml +6 -0
  121. data/lib/fun_ci/evidence/presets/vitest.yml +6 -0
  122. data/lib/fun_ci/evidence/presets.rb +30 -0
  123. data/lib/fun_ci/evidence/problem.rb +9 -0
  124. data/lib/fun_ci/evidence/process_table.rb +40 -0
  125. data/lib/fun_ci/evidence/saved_run.rb +22 -0
  126. data/lib/fun_ci/evidence/section_walk.rb +49 -0
  127. data/lib/fun_ci/evidence/settings.rb +64 -0
  128. data/lib/fun_ci/evidence/settings_check.rb +78 -0
  129. data/lib/fun_ci/evidence/source.rb +34 -0
  130. data/lib/fun_ci/evidence/sources.rb +21 -0
  131. data/lib/fun_ci/evidence/stage_context.rb +30 -0
  132. data/lib/fun_ci/evidence/stamp.rb +10 -0
  133. data/lib/fun_ci/evidence/start.rb +36 -0
  134. data/lib/fun_ci/evidence/worktree.rb +62 -0
  135. data/lib/fun_ci/persistence/active_runs.rb +69 -0
  136. data/lib/fun_ci/persistence/database.rb +63 -30
  137. data/lib/fun_ci/persistence/null_recorder.rb +25 -0
  138. data/lib/fun_ci/persistence/output_tail.rb +24 -0
  139. data/lib/fun_ci/persistence/pipeline_recorder.rb +78 -32
  140. data/lib/fun_ci/persistence/pipeline_run.rb +26 -17
  141. data/lib/fun_ci/persistence/project_runs.rb +52 -0
  142. data/lib/fun_ci/persistence/raw_outputs.rb +46 -0
  143. data/lib/fun_ci/persistence/retention.rb +25 -0
  144. data/lib/fun_ci/persistence/run_status.rb +31 -0
  145. data/lib/fun_ci/persistence/stage_job.rb +61 -14
  146. data/lib/fun_ci/persistence/state_dir.rb +26 -0
  147. data/lib/fun_ci/persistence/write_trouble.rb +46 -0
  148. data/lib/fun_ci/pipeline/background_fork.rb +42 -0
  149. data/lib/fun_ci/pipeline/command_executor.rb +58 -0
  150. data/lib/fun_ci/pipeline/gate.rb +35 -0
  151. data/lib/fun_ci/pipeline/git_environment.rb +16 -0
  152. data/lib/fun_ci/pipeline/head_part.rb +40 -0
  153. data/lib/fun_ci/pipeline/in_place.rb +17 -0
  154. data/lib/fun_ci/pipeline/output_window.rb +73 -0
  155. data/lib/fun_ci/pipeline/pipeline_forker.rb +18 -16
  156. data/lib/fun_ci/pipeline/process_runner.rb +90 -17
  157. data/lib/fun_ci/pipeline/run_canceller.rb +75 -0
  158. data/lib/fun_ci/pipeline/slot.rb +30 -0
  159. data/lib/fun_ci/pipeline/slot_lock.rb +13 -0
  160. data/lib/fun_ci/pipeline/slot_run.rb +86 -0
  161. data/lib/fun_ci/pipeline/stage_dir.rb +50 -0
  162. data/lib/fun_ci/pipeline/stage_end.rb +70 -0
  163. data/lib/fun_ci/pipeline/stage_execution.rb +67 -0
  164. data/lib/fun_ci/pipeline/stage_runner.rb +42 -65
  165. data/lib/fun_ci/pipeline/stale_pipeline_canceller.rb +16 -33
  166. data/lib/fun_ci/pipeline/tail_segments.rb +60 -0
  167. data/lib/fun_ci/pipeline/test_report.rb +48 -0
  168. data/lib/fun_ci/pipeline/trigger.rb +55 -115
  169. data/lib/fun_ci/pipeline/trigger_command.rb +62 -0
  170. data/lib/fun_ci/pipeline/trigger_params.rb +56 -0
  171. data/lib/fun_ci/pipeline/workspaces.rb +22 -0
  172. data/lib/fun_ci/pipeline/worktree_pool.rb +66 -0
  173. data/lib/fun_ci/pipeline/worktree_prune.rb +49 -0
  174. data/lib/fun_ci/pipeline/worktrees.rb +45 -0
  175. data/lib/fun_ci/setup/agent_instructions.rb +31 -0
  176. data/lib/fun_ci/setup/commands.rb +49 -0
  177. data/lib/fun_ci/setup/git_hooks.rb +20 -0
  178. data/lib/fun_ci/setup/hook_script.rb +47 -0
  179. data/lib/fun_ci/setup/hook_writer.rb +13 -31
  180. data/lib/fun_ci/setup/installer.rb +39 -23
  181. data/lib/fun_ci/setup/legacy_hooks.rb +38 -0
  182. data/lib/fun_ci/setup/project_config.rb +43 -17
  183. data/lib/fun_ci/setup/project_detector.rb +39 -7
  184. data/lib/fun_ci/setup/settings.rb +36 -0
  185. data/lib/fun_ci/setup/setup_checker.rb +18 -12
  186. data/lib/fun_ci/setup/stage_templates/javascript.rb +18 -0
  187. data/lib/fun_ci/setup/stage_templates/managed.rb +24 -0
  188. data/lib/fun_ci/setup/stage_templates/native.rb +25 -0
  189. data/lib/fun_ci/setup/stage_templates/scripting.rb +27 -0
  190. data/lib/fun_ci/setup/stage_templates/shell.rb +16 -0
  191. data/lib/fun_ci/setup/stage_templates.rb +25 -0
  192. data/lib/fun_ci/setup/template_writer.rb +11 -36
  193. data/lib/fun_ci/version.rb +1 -1
  194. data/lib/fun_ci.rb +0 -1
  195. metadata +205 -41
  196. data/exe/fun-ci-trigger +0 -19
  197. data/exe/fun-ci-tui +0 -23
  198. data/lib/fun_ci/animations/celebrate.rb +0 -210
  199. data/lib/fun_ci/animations/explosion.rb +0 -138
  200. data/lib/fun_ci/animations/flash.rb +0 -205
  201. data/lib/fun_ci/animations/idle.rb +0 -127
  202. data/lib/fun_ci/animations/leprechauns.rb +0 -240
  203. data/lib/fun_ci/animations/running.rb +0 -129
  204. data/lib/fun_ci/animations/success.rb +0 -281
  205. data/lib/fun_ci/animations/yay.rb +0 -169
  206. data/lib/fun_ci/persistence/state_machine.rb +0 -50
  207. data/lib/fun_ci/pipeline/background_wrapper.rb +0 -27
  208. data/lib/fun_ci/tui/admin_tui.rb +0 -90
  209. data/lib/fun_ci/tui/animation.rb +0 -49
  210. data/lib/fun_ci/tui/animation_compositor.rb +0 -107
  211. data/lib/fun_ci/tui/animation_frames.rb +0 -112
  212. data/lib/fun_ci/tui/animation_library.rb +0 -46
  213. data/lib/fun_ci/tui/animation_renderer.rb +0 -144
  214. data/lib/fun_ci/tui/ansi.rb +0 -34
  215. data/lib/fun_ci/tui/board_data.rb +0 -53
  216. data/lib/fun_ci/tui/board_renderer.rb +0 -105
  217. data/lib/fun_ci/tui/duration_formatter.rb +0 -24
  218. data/lib/fun_ci/tui/header_animation_manager.rb +0 -71
  219. data/lib/fun_ci/tui/header_animation_player.rb +0 -45
  220. data/lib/fun_ci/tui/key_handler.rb +0 -86
  221. data/lib/fun_ci/tui/looping_animation_player.rb +0 -45
  222. data/lib/fun_ci/tui/relative_time.rb +0 -22
  223. data/lib/fun_ci/tui/row_formatter.rb +0 -108
  224. data/lib/fun_ci/tui/screen.rb +0 -103
  225. data/lib/fun_ci/tui/spinner.rb +0 -24
  226. data/lib/fun_ci/tui/stage_change_detector.rb +0 -58
  227. data/lib/fun_ci/tui/streak_counter.rb +0 -29
  228. data/lib/fun_ci/tui/terminal_input.rb +0 -69
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fun_ci
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Erik Thyge Madsen
@@ -9,6 +9,20 @@ bindir: exe
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: rexml
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '3.2'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '3.2'
12
26
  - !ruby/object:Gem::Dependency
13
27
  name: sqlite3
14
28
  requirement: !ruby/object:Gem::Requirement
@@ -23,14 +37,23 @@ dependencies:
23
37
  - - "~>"
24
38
  - !ruby/object:Gem::Version
25
39
  version: '2.0'
26
- description: Opinionated local CI that checks your code before it leaves your machine.
27
- Runs a four-stage pipeline (lint, build, fast tests, slow tests) on every commit
28
- with strict time budgets. Hooks into git pre-commit and pre-push, stores results
29
- in SQLite, and includes a TUI dashboard for monitoring.
40
+ description: 'Opinionated local CI that checks your code before it leaves your machine.
41
+ After every commit a git hook runs four stages in a worktree at that commit: lint
42
+ and build in parallel, then a fast suite, with a slow suite in the background, each
43
+ held to a strict time budget (30 s, 30 s, 10 s and 5 minutes). The pre-push hook
44
+ stops a push whose lint, build or fast suite failed. There are two ways in. People
45
+ watch fun-ci console, a terminal dashboard drawn in 24-bit colour by a Rust renderer
46
+ (included in the Linux and macOS gems), where each milestone of a run plays its
47
+ own scene: a rocket while it runs, fireworks when it passes, an explosion when it
48
+ fails, and a quiet night scene when nothing has run for a while. Coding agents and
49
+ scripts ask with commands that answer in exit codes: fun-ci wait blocks until a
50
+ commit''s verdict is in, and fun-ci why prints what was kept about a failure (the
51
+ failures a test runner reported, excerpts picked out by presets for 34 tools, log
52
+ lines, the end of the output, with secrets masked), so nobody has to run a suite
53
+ again to see what broke. Results are kept in SQLite. Any language works, since the
54
+ stages are shell scripts; fun-ci init writes them for Ruby, Gradle and Maven projects.'
30
55
  executables:
31
56
  - fun-ci
32
- - fun-ci-trigger
33
- - fun-ci-tui
34
57
  extensions: []
35
58
  extra_rdoc_files: []
36
59
  files:
@@ -38,58 +61,198 @@ files:
38
61
  - LICENSE.txt
39
62
  - README.md
40
63
  - exe/fun-ci
41
- - exe/fun-ci-trigger
42
- - exe/fun-ci-tui
43
64
  - lib/fun_ci.rb
44
- - lib/fun_ci/animations/celebrate.rb
45
- - lib/fun_ci/animations/explosion.rb
46
- - lib/fun_ci/animations/flash.rb
47
- - lib/fun_ci/animations/idle.rb
48
- - lib/fun_ci/animations/leprechauns.rb
49
- - lib/fun_ci/animations/running.rb
50
- - lib/fun_ci/animations/success.rb
51
- - lib/fun_ci/animations/yay.rb
65
+ - lib/fun_ci/agent/age.rb
66
+ - lib/fun_ci/agent/command_support.rb
67
+ - lib/fun_ci/agent/commands.rb
68
+ - lib/fun_ci/agent/context.rb
69
+ - lib/fun_ci/agent/digest.rb
70
+ - lib/fun_ci/agent/events.rb
71
+ - lib/fun_ci/agent/events_command.rb
72
+ - lib/fun_ci/agent/evidence_text.rb
73
+ - lib/fun_ci/agent/exit_code.rb
74
+ - lib/fun_ci/agent/git.rb
75
+ - lib/fun_ci/agent/live_pipeline.rb
76
+ - lib/fun_ci/agent/options.rb
77
+ - lib/fun_ci/agent/output.rb
78
+ - lib/fun_ci/agent/report_stage.rb
79
+ - lib/fun_ci/agent/reports.rb
80
+ - lib/fun_ci/agent/run_report.rb
81
+ - lib/fun_ci/agent/runs_command.rb
82
+ - lib/fun_ci/agent/runs_text.rb
83
+ - lib/fun_ci/agent/snapshots.rb
84
+ - lib/fun_ci/agent/stage_summary.rb
85
+ - lib/fun_ci/agent/status_command.rb
86
+ - lib/fun_ci/agent/status_json.rb
87
+ - lib/fun_ci/agent/status_text.rb
88
+ - lib/fun_ci/agent/system_clock.rb
89
+ - lib/fun_ci/agent/verdict.rb
90
+ - lib/fun_ci/agent/wait_command.rb
91
+ - lib/fun_ci/agent/waiting.rb
92
+ - lib/fun_ci/agent/why_command.rb
93
+ - lib/fun_ci/agent/why_json.rb
94
+ - lib/fun_ci/agent/why_text.rb
52
95
  - lib/fun_ci/cli.rb
96
+ - lib/fun_ci/cli_help.rb
97
+ - lib/fun_ci/console/board_data.rb
98
+ - lib/fun_ci/console/board_heartbeat.rb
99
+ - lib/fun_ci/console/console_events.rb
100
+ - lib/fun_ci/console/console_log.rb
101
+ - lib/fun_ci/console/console_loop.rb
102
+ - lib/fun_ci/console/console_session.rb
103
+ - lib/fun_ci/console/console_state.rb
104
+ - lib/fun_ci/console/key_handler.rb
105
+ - lib/fun_ci/console/launcher.rb
106
+ - lib/fun_ci/console/milestone_events.rb
107
+ - lib/fun_ci/console/milestones.rb
108
+ - lib/fun_ci/console/renderer_lookup.rb
109
+ - lib/fun_ci/console/renderer_process.rb
110
+ - lib/fun_ci/console/run_message.rb
111
+ - lib/fun_ci/console/stage_change_detector.rb
112
+ - lib/fun_ci/console/stage_events.rb
113
+ - lib/fun_ci/console/stop_report.rb
114
+ - lib/fun_ci/console/streak_counter.rb
115
+ - lib/fun_ci/console/view.rb
116
+ - lib/fun_ci/evidence/about.rb
117
+ - lib/fun_ci/evidence/about_stage.rb
118
+ - lib/fun_ci/evidence/caps.rb
119
+ - lib/fun_ci/evidence/catalog.rb
120
+ - lib/fun_ci/evidence/collector.rb
121
+ - lib/fun_ci/evidence/command_output.rb
122
+ - lib/fun_ci/evidence/command_reading.rb
123
+ - lib/fun_ci/evidence/command_runner.rb
124
+ - lib/fun_ci/evidence/context.rb
125
+ - lib/fun_ci/evidence/context_document.rb
126
+ - lib/fun_ci/evidence/deadline.rb
127
+ - lib/fun_ci/evidence/detection.rb
128
+ - lib/fun_ci/evidence/document.rb
129
+ - lib/fun_ci/evidence/extract_command.rb
130
+ - lib/fun_ci/evidence/extract_options.rb
131
+ - lib/fun_ci/evidence/extraction.rb
132
+ - lib/fun_ci/evidence/extractors/command.rb
133
+ - lib/fun_ci/evidence/extractors/grep.rb
134
+ - lib/fun_ci/evidence/extractors/json_log.rb
135
+ - lib/fun_ci/evidence/extractors/junit_files.rb
136
+ - lib/fun_ci/evidence/extractors/last_lines.rb
137
+ - lib/fun_ci/evidence/extractors/log_file.rb
138
+ - lib/fun_ci/evidence/extractors/process_tree.rb
139
+ - lib/fun_ci/evidence/extractors/section.rb
140
+ - lib/fun_ci/evidence/findings.rb
141
+ - lib/fun_ci/evidence/line_ranges.rb
142
+ - lib/fun_ci/evidence/line_scan.rb
143
+ - lib/fun_ci/evidence/log_record.rb
144
+ - lib/fun_ci/evidence/masking.rb
145
+ - lib/fun_ci/evidence/option_check.rb
146
+ - lib/fun_ci/evidence/outcome.rb
147
+ - lib/fun_ci/evidence/patterns.rb
148
+ - lib/fun_ci/evidence/presets.rb
149
+ - lib/fun_ci/evidence/presets/README.md
150
+ - lib/fun_ci/evidence/presets/bun-test.yml
151
+ - lib/fun_ci/evidence/presets/cargo-test.yml
152
+ - lib/fun_ci/evidence/presets/dart-test.yml
153
+ - lib/fun_ci/evidence/presets/deno-test.yml
154
+ - lib/fun_ci/evidence/presets/dotnet-test.yml
155
+ - lib/fun_ci/evidence/presets/ecs.yml
156
+ - lib/fun_ci/evidence/presets/eslint.yml
157
+ - lib/fun_ci/evidence/presets/exunit.yml
158
+ - lib/fun_ci/evidence/presets/gcc.yml
159
+ - lib/fun_ci/evidence/presets/go-build.yml
160
+ - lib/fun_ci/evidence/presets/go-test.yml
161
+ - lib/fun_ci/evidence/presets/gradle.yml
162
+ - lib/fun_ci/evidence/presets/gtest.yml
163
+ - lib/fun_ci/evidence/presets/jest.yml
164
+ - lib/fun_ci/evidence/presets/logstash.yml
165
+ - lib/fun_ci/evidence/presets/maven.yml
166
+ - lib/fun_ci/evidence/presets/minitest.yml
167
+ - lib/fun_ci/evidence/presets/mocha.yml
168
+ - lib/fun_ci/evidence/presets/mypy.yml
169
+ - lib/fun_ci/evidence/presets/node-test.yml
170
+ - lib/fun_ci/evidence/presets/phpunit.yml
171
+ - lib/fun_ci/evidence/presets/pino.yml
172
+ - lib/fun_ci/evidence/presets/prove.yml
173
+ - lib/fun_ci/evidence/presets/pytest.yml
174
+ - lib/fun_ci/evidence/presets/rspec.yml
175
+ - lib/fun_ci/evidence/presets/rubocop.yml
176
+ - lib/fun_ci/evidence/presets/ruff.yml
177
+ - lib/fun_ci/evidence/presets/rustc.yml
178
+ - lib/fun_ci/evidence/presets/shellcheck.yml
179
+ - lib/fun_ci/evidence/presets/structlog.yml
180
+ - lib/fun_ci/evidence/presets/swift-test.yml
181
+ - lib/fun_ci/evidence/presets/tsc.yml
182
+ - lib/fun_ci/evidence/presets/unittest.yml
183
+ - lib/fun_ci/evidence/presets/vitest.yml
184
+ - lib/fun_ci/evidence/problem.rb
185
+ - lib/fun_ci/evidence/process_table.rb
186
+ - lib/fun_ci/evidence/saved_run.rb
187
+ - lib/fun_ci/evidence/section_walk.rb
188
+ - lib/fun_ci/evidence/settings.rb
189
+ - lib/fun_ci/evidence/settings_check.rb
190
+ - lib/fun_ci/evidence/source.rb
191
+ - lib/fun_ci/evidence/sources.rb
192
+ - lib/fun_ci/evidence/stage_context.rb
193
+ - lib/fun_ci/evidence/stamp.rb
194
+ - lib/fun_ci/evidence/start.rb
195
+ - lib/fun_ci/evidence/worktree.rb
196
+ - lib/fun_ci/persistence/active_runs.rb
53
197
  - lib/fun_ci/persistence/database.rb
198
+ - lib/fun_ci/persistence/null_recorder.rb
199
+ - lib/fun_ci/persistence/output_tail.rb
54
200
  - lib/fun_ci/persistence/pipeline_recorder.rb
55
201
  - lib/fun_ci/persistence/pipeline_run.rb
202
+ - lib/fun_ci/persistence/project_runs.rb
203
+ - lib/fun_ci/persistence/raw_outputs.rb
204
+ - lib/fun_ci/persistence/retention.rb
205
+ - lib/fun_ci/persistence/run_status.rb
56
206
  - lib/fun_ci/persistence/stage_job.rb
57
- - lib/fun_ci/persistence/state_machine.rb
58
- - lib/fun_ci/pipeline/background_wrapper.rb
207
+ - lib/fun_ci/persistence/state_dir.rb
208
+ - lib/fun_ci/persistence/write_trouble.rb
209
+ - lib/fun_ci/pipeline/background_fork.rb
210
+ - lib/fun_ci/pipeline/command_executor.rb
211
+ - lib/fun_ci/pipeline/gate.rb
212
+ - lib/fun_ci/pipeline/git_environment.rb
213
+ - lib/fun_ci/pipeline/head_part.rb
214
+ - lib/fun_ci/pipeline/in_place.rb
215
+ - lib/fun_ci/pipeline/output_window.rb
59
216
  - lib/fun_ci/pipeline/pipeline_forker.rb
60
217
  - lib/fun_ci/pipeline/process_runner.rb
61
218
  - lib/fun_ci/pipeline/progress_reporter.rb
219
+ - lib/fun_ci/pipeline/run_canceller.rb
220
+ - lib/fun_ci/pipeline/slot.rb
221
+ - lib/fun_ci/pipeline/slot_lock.rb
222
+ - lib/fun_ci/pipeline/slot_run.rb
223
+ - lib/fun_ci/pipeline/stage_dir.rb
224
+ - lib/fun_ci/pipeline/stage_end.rb
225
+ - lib/fun_ci/pipeline/stage_execution.rb
62
226
  - lib/fun_ci/pipeline/stage_runner.rb
63
227
  - lib/fun_ci/pipeline/stale_pipeline_canceller.rb
228
+ - lib/fun_ci/pipeline/tail_segments.rb
229
+ - lib/fun_ci/pipeline/test_report.rb
64
230
  - lib/fun_ci/pipeline/trigger.rb
231
+ - lib/fun_ci/pipeline/trigger_command.rb
232
+ - lib/fun_ci/pipeline/trigger_params.rb
233
+ - lib/fun_ci/pipeline/workspaces.rb
234
+ - lib/fun_ci/pipeline/worktree_pool.rb
235
+ - lib/fun_ci/pipeline/worktree_prune.rb
236
+ - lib/fun_ci/pipeline/worktrees.rb
237
+ - lib/fun_ci/setup/agent_instructions.rb
238
+ - lib/fun_ci/setup/commands.rb
239
+ - lib/fun_ci/setup/git_hooks.rb
240
+ - lib/fun_ci/setup/hook_script.rb
65
241
  - lib/fun_ci/setup/hook_writer.rb
66
242
  - lib/fun_ci/setup/installer.rb
243
+ - lib/fun_ci/setup/legacy_hooks.rb
67
244
  - lib/fun_ci/setup/maven_linter_detector.rb
68
245
  - lib/fun_ci/setup/project_config.rb
69
246
  - lib/fun_ci/setup/project_detector.rb
247
+ - lib/fun_ci/setup/settings.rb
70
248
  - lib/fun_ci/setup/setup_checker.rb
249
+ - lib/fun_ci/setup/stage_templates.rb
250
+ - lib/fun_ci/setup/stage_templates/javascript.rb
251
+ - lib/fun_ci/setup/stage_templates/managed.rb
252
+ - lib/fun_ci/setup/stage_templates/native.rb
253
+ - lib/fun_ci/setup/stage_templates/scripting.rb
254
+ - lib/fun_ci/setup/stage_templates/shell.rb
71
255
  - lib/fun_ci/setup/template_writer.rb
72
- - lib/fun_ci/tui/admin_tui.rb
73
- - lib/fun_ci/tui/animation.rb
74
- - lib/fun_ci/tui/animation_compositor.rb
75
- - lib/fun_ci/tui/animation_frames.rb
76
- - lib/fun_ci/tui/animation_library.rb
77
- - lib/fun_ci/tui/animation_renderer.rb
78
- - lib/fun_ci/tui/ansi.rb
79
- - lib/fun_ci/tui/board_data.rb
80
- - lib/fun_ci/tui/board_renderer.rb
81
- - lib/fun_ci/tui/duration_formatter.rb
82
- - lib/fun_ci/tui/header_animation_manager.rb
83
- - lib/fun_ci/tui/header_animation_player.rb
84
- - lib/fun_ci/tui/key_handler.rb
85
- - lib/fun_ci/tui/looping_animation_player.rb
86
- - lib/fun_ci/tui/relative_time.rb
87
- - lib/fun_ci/tui/row_formatter.rb
88
- - lib/fun_ci/tui/screen.rb
89
- - lib/fun_ci/tui/spinner.rb
90
- - lib/fun_ci/tui/stage_change_detector.rb
91
- - lib/fun_ci/tui/streak_counter.rb
92
- - lib/fun_ci/tui/terminal_input.rb
93
256
  - lib/fun_ci/version.rb
94
257
  homepage: https://github.com/beatmadsen/fun-ci
95
258
  licenses:
@@ -117,5 +280,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
280
  requirements: []
118
281
  rubygems_version: 4.0.9
119
282
  specification_version: 4
120
- summary: Opinionated local CI that checks your code before it leaves your machine
283
+ summary: Opinionated local CI that checks every commit on your machine, for you to
284
+ watch and for your coding agent to ask
121
285
  test_files: []
data/exe/fun-ci-trigger DELETED
@@ -1,19 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require_relative "../lib/fun_ci"
5
- require_relative "../lib/fun_ci/pipeline/trigger"
6
- require_relative "../lib/fun_ci/persistence/pipeline_recorder"
7
-
8
- require "tmpdir"
9
-
10
- db_dir = File.join(Dir.tmpdir, "fun-ci")
11
- Dir.mkdir(db_dir) unless Dir.exist?(db_dir)
12
- db_path = File.join(db_dir, "db.sqlite3")
13
-
14
- db = FunCi::Persistence::Database.connection(db_path)
15
- FunCi::Persistence::Database.migrate!(db)
16
-
17
- recorder = FunCi::Persistence::DbRecorder.new(db)
18
-
19
- exit FunCi::Pipeline::Trigger.run_from_args(ARGV, recorder: recorder)
data/exe/fun-ci-tui DELETED
@@ -1,23 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require_relative "../lib/fun_ci"
5
- require_relative "../lib/fun_ci/tui/admin_tui"
6
- require_relative "../lib/fun_ci/tui/animation_renderer"
7
-
8
- require "tmpdir"
9
- require "io/console"
10
-
11
- db_dir = File.join(Dir.tmpdir, "fun-ci")
12
- Dir.mkdir(db_dir) unless Dir.exist?(db_dir)
13
- db_path = File.join(db_dir, "db.sqlite3")
14
-
15
- db = FunCi::Persistence::Database.connection(db_path)
16
- FunCi::Persistence::Database.migrate!(db)
17
-
18
- tui = FunCi::Tui::AdminTui.new(
19
- db: db,
20
- width_provider: -> { IO.console&.winsize&.dig(1) || 80 },
21
- animation_renderer: FunCi::Tui::AnimationRenderer.new
22
- )
23
- tui.run
@@ -1,210 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FunCi
4
- module Animations
5
- module Celebrate
6
- # Horizontal colour expansion — success celebration
7
- # Run: ruby exe/animation-player animations/celebrate.rb
8
-
9
- w = "\e[1;37m" # bold white
10
- y = "\e[1;33m" # bold yellow
11
- Y = "\e[33m" # yellow
12
- g = "\e[1;32m" # bold green
13
- G = "\e[32m" # green
14
- d = "\e[2;32m" # dim green
15
- c = "\e[1;36m" # bold cyan
16
- C = "\e[36m" # cyan
17
- m = "\e[1;35m" # bold magenta
18
- M = "\e[35m" # magenta
19
- b = "\e[1;34m" # bold blue
20
- B = "\e[34m" # blue
21
- r = "\e[1;31m" # bold red
22
- o = "\e[38;5;208m" # orange
23
- x = "\e[0m" # reset
24
-
25
- raw_frames = [
26
- # Frame 1 — dark field, bright seed in the centre
27
- [
28
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
29
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
30
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
31
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
32
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
33
- " #{d}. . . . . . . . . . . .#{w}*#{d}. . . . . . . . . . .#{x}",
34
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
35
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
36
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
37
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
38
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
39
- ],
40
- # Frame 2 — first horizontal burst, gold/white core
41
- [
42
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
43
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
44
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
45
- " #{d}. . . . . . . . . . #{Y}* #{y}* #{Y}*#{d} . . . . . . . . .#{x}",
46
- " #{d}. . . . . . . . . #{y}* #{w}*#{y} @#{w} @#{y} *#{Y} *#{d} . . . . . . . .#{x}",
47
- " #{d}. . . . . . . . #{y}*#{w} @#{y} @#{w} # #{w}@#{y} @ #{w}*#{y} *#{d} . . . . . . .#{x}",
48
- " #{d}. . . . . . . . . #{y}* #{w}*#{y} @#{w} @#{y} *#{Y} *#{d} . . . . . . . .#{x}",
49
- " #{d}. . . . . . . . . . #{Y}* #{y}* #{Y}*#{d} . . . . . . . . .#{x}",
50
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
51
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
52
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
53
- ],
54
- # Frame 3 — wider, green/cyan ring appears
55
- [
56
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
57
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
58
- " #{d}. . . . . . . #{G}*#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{d} . . . . . . .#{x}",
59
- " #{d}. . . . . . #{g}*#{c} *#{C} *#{y} *#{Y} * #{y}*#{Y} * #{c}*#{C} *#{g} *#{d} . . . . . .#{x}",
60
- " #{d}. . . . . #{g}*#{c} *#{y} *#{w} @#{y} @#{w} ##{w} @#{y} @#{w} *#{y} *#{c} *#{g} *#{d} . . . . .#{x}",
61
- " #{d}. . . . #{g}*#{c} *#{y} *#{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} *#{y} *#{c} *#{g} *#{d} . . . .#{x}",
62
- " #{d}. . . . . #{g}*#{c} *#{y} *#{w} @#{y} @#{w} ##{w} @#{y} @#{w} *#{y} *#{c} *#{g} *#{d} . . . . .#{x}",
63
- " #{d}. . . . . . #{g}*#{c} *#{C} *#{y} *#{Y} * #{y}*#{Y} * #{c}*#{C} *#{g} *#{d} . . . . . .#{x}",
64
- " #{d}. . . . . . . #{G}*#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{d} . . . . . . .#{x}",
65
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
66
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
67
- ],
68
- # Frame 4 — colours spread wider, magenta/blue outer ring
69
- [
70
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
71
- " #{d}. . . . . #{B}*#{b} *#{B} *#{b} *#{B} *#{b} *#{B} *#{b} *#{B} *#{b} *#{B} *#{d} . . . . .#{x}",
72
- " #{d}. . . . #{b}*#{M} *#{m} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{m} *#{M} *#{b} *#{d} . . . .#{x}",
73
- " #{d}. . . #{b}*#{m} *#{g} *#{c} *#{C} *#{y} *#{Y} * #{y}*#{C} * #{c}*#{g} *#{m} *#{b} *#{d} . . .#{x}",
74
- " #{d}. . #{b}*#{m} *#{g} *#{c} *#{y} *#{w} @#{y} @#{w} ##{w} @#{y} @#{y} *#{c} *#{g} *#{m} *#{b} *#{d} . .#{x}",
75
- " #{d}. #{b}*#{m} *#{g} *#{c} *#{y} *#{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{y} *#{c} *#{g} *#{m} *#{b} *#{d} .#{x}",
76
- " #{d}. . #{b}*#{m} *#{g} *#{c} *#{y} *#{w} @#{y} @#{w} ##{w} @#{y} @#{y} *#{c} *#{g} *#{m} *#{b} *#{d} . .#{x}",
77
- " #{d}. . . #{b}*#{m} *#{g} *#{c} *#{C} *#{y} *#{Y} * #{y}*#{C} * #{c}*#{g} *#{m} *#{b} *#{d} . . .#{x}",
78
- " #{d}. . . . #{b}*#{M} *#{m} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{m} *#{M} *#{b} *#{d} . . . .#{x}",
79
- " #{d}. . . . . #{B}*#{b} *#{B} *#{b} *#{B} *#{b} *#{B} *#{b} *#{B} *#{b} *#{B} *#{d} . . . . .#{x}",
80
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
81
- ],
82
- # Frame 5 — nearly full width, rainbow bands
83
- [
84
- " #{d}. . . #{B}*#{b} *#{B} *#{b} *#{B} *#{b} *#{B} *#{b} *#{B} *#{b} *#{B} *#{b} *#{B} *#{b} *#{d} . . .#{x}",
85
- " #{d}. . #{b}*#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{b} *#{d} . .#{x}",
86
- " #{d}. #{m}*#{r} *#{o} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{o} *#{r} *#{m} *#{d} .#{x}",
87
- " #{m}*#{g} *#{c} *#{C} *#{c} *#{C} *#{y} *#{Y} *#{y} *#{Y} *#{c} *#{C} *#{c} *#{C} *#{c} *#{g} *#{m} *#{x}",
88
- " #{g}*#{c} *#{y} *#{Y} *#{w} @#{y} @#{w} ##{w} @#{w} ##{w} @#{y} @#{w} *#{Y} *#{y} *#{c} *#{g} *#{m} *#{x}",
89
- " #{g}*#{c} *#{y} *#{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} *#{y} *#{c} *#{g} *#{m} *#{x}",
90
- " #{g}*#{c} *#{y} *#{Y} *#{w} @#{y} @#{w} ##{w} @#{w} ##{w} @#{y} @#{w} *#{Y} *#{y} *#{c} *#{g} *#{m} *#{x}",
91
- " #{m}*#{g} *#{c} *#{C} *#{c} *#{C} *#{y} *#{Y} *#{y} *#{Y} *#{c} *#{C} *#{c} *#{C} *#{c} *#{g} *#{m} *#{x}",
92
- " #{d}. #{m}*#{r} *#{o} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{o} *#{r} *#{m} *#{d} .#{x}",
93
- " #{d}. . #{b}*#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{b} *#{d} . .#{x}",
94
- " #{d}. . . #{B}*#{b} *#{B} *#{b} *#{B} *#{b} *#{B} *#{b} *#{B} *#{b} *#{B} *#{b} *#{B} *#{b} *#{d} . . .#{x}",
95
- ],
96
- # Frame 6 — FULL WIDTH, every pixel lit, rainbow explosion
97
- [
98
- " #{B}*#{b} *#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{b} *#{B} *#{x}",
99
- " #{m}*#{r} *#{o} *#{r} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{r} *#{o} *#{r} *#{m} *#{b} *#{x}",
100
- " #{r}*#{o} *#{g} *#{c} *#{C} *#{c} *#{C} *#{c} *#{C} *#{c} *#{C} *#{c} *#{C} *#{g} *#{o} *#{r} *#{m} *#{x}",
101
- " #{g}*#{c} *#{C} *#{y} *#{Y} *#{y} *#{Y} *#{w} @#{Y} *#{y} *#{Y} *#{y} *#{C} *#{c} *#{g} *#{o} *#{r} *#{x}",
102
- " #{c}*#{y} *#{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} *#{y} *#{c} *#{g} *#{o} *#{x}",
103
- " #{y}*#{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{y} *#{c} *#{x}",
104
- " #{c}*#{y} *#{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} *#{y} *#{c} *#{g} *#{o} *#{x}",
105
- " #{g}*#{c} *#{C} *#{y} *#{Y} *#{y} *#{Y} *#{w} @#{Y} *#{y} *#{Y} *#{y} *#{C} *#{c} *#{g} *#{o} *#{r} *#{x}",
106
- " #{r}*#{o} *#{g} *#{c} *#{C} *#{c} *#{C} *#{c} *#{C} *#{c} *#{C} *#{c} *#{C} *#{g} *#{o} *#{r} *#{m} *#{x}",
107
- " #{m}*#{r} *#{o} *#{r} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{r} *#{o} *#{r} *#{m} *#{b} *#{x}",
108
- " #{B}*#{b} *#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{b} *#{B} *#{x}",
109
- ],
110
- # (hold)
111
- [
112
- " #{b}*#{M} *#{m} *#{M} *#{m} *#{r} *#{o} *#{r} *#{o} *#{r} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{b} *#{x}",
113
- " #{m}*#{r} *#{o} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{o} *#{r} *#{m} *#{x}",
114
- " #{o}*#{g} *#{c} *#{C} *#{c} *#{C} *#{y} *#{Y} *#{y} *#{Y} *#{c} *#{C} *#{c} *#{C} *#{g} *#{o} *#{r} *#{x}",
115
- " #{c}*#{C} *#{y} *#{Y} *#{y} *#{w} @#{w} ##{w} @#{w} ##{w} @#{y} *#{Y} *#{y} *#{C} *#{c} *#{g} *#{o} *#{x}",
116
- " #{y}*#{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} *#{y} *#{c} *#{g} *#{x}",
117
- " #{w}@#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{y} *#{x}",
118
- " #{y}*#{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} *#{y} *#{c} *#{g} *#{x}",
119
- " #{c}*#{C} *#{y} *#{Y} *#{y} *#{w} @#{w} ##{w} @#{w} ##{w} @#{y} *#{Y} *#{y} *#{C} *#{c} *#{g} *#{o} *#{x}",
120
- " #{o}*#{g} *#{c} *#{C} *#{c} *#{C} *#{y} *#{Y} *#{y} *#{Y} *#{c} *#{C} *#{c} *#{C} *#{g} *#{o} *#{r} *#{x}",
121
- " #{m}*#{r} *#{o} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{o} *#{r} *#{m} *#{x}",
122
- " #{b}*#{M} *#{m} *#{M} *#{m} *#{r} *#{o} *#{r} *#{o} *#{r} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{b} *#{x}",
123
- ],
124
- # Frame 7 — contracting, colours retreating
125
- [
126
- " #{d}. #{B}*#{b} *#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{b} *#{B} *#{d} .#{x}",
127
- " #{d}. . #{m}*#{r} *#{o} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{o} *#{r} *#{m} *#{d} . .#{x}",
128
- " #{d}. . . #{g}*#{c} *#{C} *#{c} *#{C} *#{y} *#{Y} *#{y} *#{C} *#{c} *#{C} *#{c} *#{g} *#{d} . . .#{x}",
129
- " #{d}. . . . #{c}*#{C} *#{y} *#{Y} *#{w} @#{w} ##{w} @#{Y} *#{y} *#{C} *#{c} *#{g} *#{d} . . . .#{x}",
130
- " #{d}. . . #{g}*#{c} *#{y} *#{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} *#{y} *#{c} *#{g} *#{d} . . .#{x}",
131
- " #{d}. . #{g}*#{c} *#{y} *#{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{y} *#{c} *#{g} *#{d} . .#{x}",
132
- " #{d}. . . #{g}*#{c} *#{y} *#{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} *#{y} *#{c} *#{g} *#{d} . . .#{x}",
133
- " #{d}. . . . #{c}*#{C} *#{y} *#{Y} *#{w} @#{w} ##{w} @#{Y} *#{y} *#{C} *#{c} *#{g} *#{d} . . . .#{x}",
134
- " #{d}. . . #{g}*#{c} *#{C} *#{c} *#{C} *#{y} *#{Y} *#{y} *#{C} *#{c} *#{C} *#{c} *#{g} *#{d} . . .#{x}",
135
- " #{d}. . #{m}*#{r} *#{o} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{o} *#{r} *#{m} *#{d} . .#{x}",
136
- " #{d}. #{B}*#{b} *#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{m} *#{M} *#{b} *#{B} *#{d} .#{x}",
137
- ],
138
- # Frame 8 — second pulse outward, fresh colours
139
- [
140
- " #{d}. . #{b}*#{m} *#{r} *#{o} *#{g} *#{c} *#{g} *#{c} *#{g} *#{o} *#{r} *#{m} *#{b} *#{d} . . .#{x}",
141
- " #{d}. #{m}*#{g} *#{c} *#{C} *#{c} *#{C} *#{c} *#{C} *#{c} *#{C} *#{c} *#{C} *#{c} *#{g} *#{m} *#{d} .#{x}",
142
- " #{m}*#{g} *#{c} *#{C} *#{y} *#{Y} *#{y} *#{Y} *#{y} *#{Y} *#{y} *#{Y} *#{C} *#{c} *#{g} *#{m} *#{b} *#{x}",
143
- " #{g}*#{c} *#{y} *#{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} *#{y} *#{c} *#{g} *#{m} *#{x}",
144
- " #{c}*#{y} *#{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} *#{y} *#{c} *#{g} *#{x}",
145
- " #{y}*#{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{y} *#{c} *#{x}",
146
- " #{c}*#{y} *#{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} *#{y} *#{c} *#{g} *#{x}",
147
- " #{g}*#{c} *#{y} *#{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} *#{y} *#{c} *#{g} *#{m} *#{x}",
148
- " #{m}*#{g} *#{c} *#{C} *#{y} *#{Y} *#{y} *#{Y} *#{y} *#{Y} *#{y} *#{Y} *#{C} *#{c} *#{g} *#{m} *#{b} *#{x}",
149
- " #{d}. #{m}*#{g} *#{c} *#{C} *#{c} *#{C} *#{c} *#{C} *#{c} *#{C} *#{c} *#{C} *#{c} *#{g} *#{m} *#{d} .#{x}",
150
- " #{d}. . #{b}*#{m} *#{r} *#{o} *#{g} *#{c} *#{g} *#{c} *#{g} *#{o} *#{r} *#{m} *#{b} *#{d} . . .#{x}",
151
- ],
152
- # Frame 9 — settling, warm glow
153
- [
154
- " #{d}. . . . #{b}*#{m} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{m} *#{b} *#{d} . . . . .#{x}",
155
- " #{d}. . . #{m}*#{g} *#{c} *#{C} *#{c} *#{C} *#{c} *#{C} *#{c} *#{C} *#{c} *#{g} *#{m} *#{d} . . .#{x}",
156
- " #{d}. . #{g}*#{c} *#{C} *#{y} *#{Y} *#{y} *#{Y} *#{y} *#{Y} *#{y} *#{C} *#{c} *#{g} *#{d} . . .#{x}",
157
- " #{d}. #{g}*#{c} *#{y} *#{Y} *#{y} *#{w} @#{y} *#{w} @#{y} *#{Y} *#{y} *#{c} *#{g} *#{m} *#{d} . .#{x}",
158
- " #{d}. #{c}*#{y} *#{w} @#{y} @#{w} ##{w} @#{w} ##{w} @#{w} ##{y} @#{w} *#{y} *#{c} *#{g} *#{d} . . .#{x}",
159
- " #{g}*#{c} *#{y} *#{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{w} ##{w} @#{y} *#{y} *#{c} *#{g} *#{d} .#{x}",
160
- " #{d}. #{c}*#{y} *#{w} @#{y} @#{w} ##{w} @#{w} ##{w} @#{w} ##{y} @#{w} *#{y} *#{c} *#{g} *#{d} . . .#{x}",
161
- " #{d}. #{g}*#{c} *#{y} *#{Y} *#{y} *#{w} @#{y} *#{w} @#{y} *#{Y} *#{y} *#{c} *#{g} *#{m} *#{d} . .#{x}",
162
- " #{d}. . #{g}*#{c} *#{C} *#{y} *#{Y} *#{y} *#{Y} *#{y} *#{Y} *#{y} *#{C} *#{c} *#{g} *#{d} . . .#{x}",
163
- " #{d}. . . #{m}*#{g} *#{c} *#{C} *#{c} *#{C} *#{c} *#{C} *#{c} *#{C} *#{c} *#{g} *#{m} *#{d} . . .#{x}",
164
- " #{d}. . . . #{b}*#{m} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{m} *#{b} *#{d} . . . . .#{x}",
165
- ],
166
- # Frame 10 — fading to green glow
167
- [
168
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
169
- " #{d}. . . . . . #{G}*#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{d} . . . . . .#{x}",
170
- " #{d}. . . . . #{g}*#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{d} . . . . .#{x}",
171
- " #{d}. . . . #{g}*#{c} *#{g} *#{c} *#{g} *#{Y} *#{g} *#{c} *#{g} *#{c} *#{g} *#{d} . . . . . .#{x}",
172
- " #{d}. . . #{g}*#{c} *#{C} *#{y} *#{Y} *#{y} *#{Y} *#{y} *#{C} *#{c} *#{g} *#{d} . . . . . . .#{x}",
173
- " #{d}. . . #{g}*#{c} *#{y} *#{Y} *#{y} *#{w} @#{y} *#{Y} *#{y} *#{c} *#{g} *#{d} . . . . . . .#{x}",
174
- " #{d}. . . #{g}*#{c} *#{C} *#{y} *#{Y} *#{y} *#{Y} *#{y} *#{C} *#{c} *#{g} *#{d} . . . . . . .#{x}",
175
- " #{d}. . . . #{g}*#{c} *#{g} *#{c} *#{g} *#{Y} *#{g} *#{c} *#{g} *#{c} *#{g} *#{d} . . . . . .#{x}",
176
- " #{d}. . . . . #{g}*#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{d} . . . . .#{x}",
177
- " #{d}. . . . . . #{G}*#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{d} . . . . . .#{x}",
178
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
179
- ],
180
- # Frame 11 — almost gone, warm ember
181
- [
182
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
183
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
184
- " #{d}. . . . . . . . #{G}*#{g} *#{G} *#{g} *#{G} *#{g} *#{d} . . . . . . . .#{x}",
185
- " #{d}. . . . . . . #{g}*#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{d} . . . . . . .#{x}",
186
- " #{d}. . . . . . . #{g}*#{c} *#{g} *#{Y} *#{g} *#{c} *#{g} *#{d} . . . . . . .#{x}",
187
- " #{d}. . . . . . . . #{g}*#{G} *#{g} *#{G} *#{g} *#{d} . . . . . . . . .#{x}",
188
- " #{d}. . . . . . . . . #{G}*#{g} *#{G} *#{d} . . . . . . . . . . .#{x}",
189
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
190
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
191
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
192
- " #{d}. . . . . . . . . . . . . . . . . . . . . . . .#{x}",
193
- ],
194
- ]
195
-
196
- # Pad lines so all rows in each frame have equal stripped length —
197
- # prevents the player's per-line centering from misaligning the art.
198
- max = raw_frames.flatten.map { |l| l.gsub(/\e\[[0-9;]*m/, "").length }.max
199
- raw_frames.each do |frame|
200
- frame.map! { |l| l + " " * (max - l.gsub(/\e\[[0-9;]*m/, "").length) }
201
- end
202
-
203
- DATA = {
204
- name: "Celebrate",
205
- fps: 8,
206
- frames: raw_frames
207
- }.freeze
208
- end
209
- end
210
- end