fun_ci 1.2.1 → 2.0.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/CHANGELOG.md +218 -0
- data/README.md +180 -59
- data/lib/fun_ci/agent/age.rb +15 -0
- data/lib/fun_ci/agent/command_support.rb +27 -0
- data/lib/fun_ci/agent/commands.rb +27 -0
- data/lib/fun_ci/agent/context.rb +10 -0
- data/lib/fun_ci/agent/digest.rb +49 -0
- data/lib/fun_ci/agent/events.rb +47 -0
- data/lib/fun_ci/agent/events_command.rb +61 -0
- data/lib/fun_ci/agent/evidence_text.rb +46 -0
- data/lib/fun_ci/agent/exit_code.rb +11 -0
- data/lib/fun_ci/agent/git.rb +31 -0
- data/lib/fun_ci/agent/live_pipeline.rb +35 -0
- data/lib/fun_ci/agent/options.rb +75 -0
- data/lib/fun_ci/agent/output.rb +81 -0
- data/lib/fun_ci/agent/report_stage.rb +73 -0
- data/lib/fun_ci/agent/reports.rb +47 -0
- data/lib/fun_ci/agent/run_report.rb +30 -0
- data/lib/fun_ci/agent/runs_command.rb +34 -0
- data/lib/fun_ci/agent/runs_text.rb +27 -0
- data/lib/fun_ci/agent/snapshots.rb +39 -0
- data/lib/fun_ci/agent/stage_summary.rb +30 -0
- data/lib/fun_ci/agent/status_command.rb +36 -0
- data/lib/fun_ci/agent/status_json.rb +27 -0
- data/lib/fun_ci/agent/status_text.rb +37 -0
- data/lib/fun_ci/agent/system_clock.rb +11 -0
- data/lib/fun_ci/agent/verdict.rb +32 -0
- data/lib/fun_ci/agent/wait_command.rb +71 -0
- data/lib/fun_ci/agent/waiting.rb +32 -0
- data/lib/fun_ci/agent/why_command.rb +50 -0
- data/lib/fun_ci/agent/why_json.rb +35 -0
- data/lib/fun_ci/agent/why_text.rb +43 -0
- data/lib/fun_ci/cli.rb +72 -94
- data/lib/fun_ci/cli_help.rb +65 -0
- data/lib/fun_ci/console/board_data.rb +66 -0
- data/lib/fun_ci/console/board_heartbeat.rb +40 -0
- data/lib/fun_ci/console/console_events.rb +20 -0
- data/lib/fun_ci/console/console_log.rb +26 -0
- data/lib/fun_ci/console/console_loop.rb +41 -0
- data/lib/fun_ci/console/console_session.rb +82 -0
- data/lib/fun_ci/console/console_state.rb +42 -0
- data/lib/fun_ci/console/key_handler.rb +73 -0
- data/lib/fun_ci/console/launcher.rb +43 -0
- data/lib/fun_ci/console/milestone_events.rb +38 -0
- data/lib/fun_ci/console/milestones.rb +25 -0
- data/lib/fun_ci/console/renderer_lookup.rb +51 -0
- data/lib/fun_ci/console/renderer_process.rb +60 -0
- data/lib/fun_ci/console/run_message.rb +33 -0
- data/lib/fun_ci/console/stage_change_detector.rb +32 -0
- data/lib/fun_ci/console/stage_events.rb +31 -0
- data/lib/fun_ci/console/stop_report.rb +39 -0
- data/lib/fun_ci/console/streak_counter.rb +19 -0
- data/lib/fun_ci/console/view.rb +47 -0
- data/lib/fun_ci/evidence/about.rb +12 -0
- data/lib/fun_ci/evidence/about_stage.rb +29 -0
- data/lib/fun_ci/evidence/caps.rb +77 -0
- data/lib/fun_ci/evidence/catalog.rb +83 -0
- data/lib/fun_ci/evidence/collector.rb +95 -0
- data/lib/fun_ci/evidence/command_output.rb +45 -0
- data/lib/fun_ci/evidence/command_reading.rb +38 -0
- data/lib/fun_ci/evidence/command_runner.rb +75 -0
- data/lib/fun_ci/evidence/context.rb +21 -0
- data/lib/fun_ci/evidence/context_document.rb +29 -0
- data/lib/fun_ci/evidence/deadline.rb +15 -0
- data/lib/fun_ci/evidence/detection.rb +82 -0
- data/lib/fun_ci/evidence/document.rb +59 -0
- data/lib/fun_ci/evidence/extract_command.rb +83 -0
- data/lib/fun_ci/evidence/extract_options.rb +45 -0
- data/lib/fun_ci/evidence/extraction.rb +54 -0
- data/lib/fun_ci/evidence/extractors/command.rb +52 -0
- data/lib/fun_ci/evidence/extractors/grep.rb +49 -0
- data/lib/fun_ci/evidence/extractors/json_log.rb +45 -0
- data/lib/fun_ci/evidence/extractors/junit_files.rb +32 -0
- data/lib/fun_ci/evidence/extractors/last_lines.rb +25 -0
- data/lib/fun_ci/evidence/extractors/log_file.rb +62 -0
- data/lib/fun_ci/evidence/extractors/process_tree.rb +51 -0
- data/lib/fun_ci/evidence/extractors/section.rb +49 -0
- data/lib/fun_ci/evidence/findings.rb +14 -0
- data/lib/fun_ci/evidence/line_ranges.rb +21 -0
- data/lib/fun_ci/evidence/line_scan.rb +22 -0
- data/lib/fun_ci/evidence/log_record.rb +58 -0
- data/lib/fun_ci/evidence/masking.rb +55 -0
- data/lib/fun_ci/evidence/option_check.rb +53 -0
- data/lib/fun_ci/evidence/outcome.rb +15 -0
- data/lib/fun_ci/evidence/patterns.rb +22 -0
- data/lib/fun_ci/evidence/presets/README.md +7 -0
- data/lib/fun_ci/evidence/presets/bun-test.yml +6 -0
- data/lib/fun_ci/evidence/presets/cargo-test.yml +6 -0
- data/lib/fun_ci/evidence/presets/dart-test.yml +6 -0
- data/lib/fun_ci/evidence/presets/deno-test.yml +6 -0
- data/lib/fun_ci/evidence/presets/dotnet-test.yml +6 -0
- data/lib/fun_ci/evidence/presets/ecs.yml +3 -0
- data/lib/fun_ci/evidence/presets/eslint.yml +6 -0
- data/lib/fun_ci/evidence/presets/exunit.yml +6 -0
- data/lib/fun_ci/evidence/presets/gcc.yml +6 -0
- data/lib/fun_ci/evidence/presets/go-build.yml +5 -0
- data/lib/fun_ci/evidence/presets/go-test.yml +6 -0
- data/lib/fun_ci/evidence/presets/gradle.yml +6 -0
- data/lib/fun_ci/evidence/presets/gtest.yml +6 -0
- data/lib/fun_ci/evidence/presets/jest.yml +6 -0
- data/lib/fun_ci/evidence/presets/logstash.yml +3 -0
- data/lib/fun_ci/evidence/presets/maven.yml +6 -0
- data/lib/fun_ci/evidence/presets/minitest.yml +6 -0
- data/lib/fun_ci/evidence/presets/mocha.yml +6 -0
- data/lib/fun_ci/evidence/presets/mypy.yml +6 -0
- data/lib/fun_ci/evidence/presets/node-test.yml +6 -0
- data/lib/fun_ci/evidence/presets/phpunit.yml +6 -0
- data/lib/fun_ci/evidence/presets/pino.yml +5 -0
- data/lib/fun_ci/evidence/presets/prove.yml +6 -0
- data/lib/fun_ci/evidence/presets/pytest.yml +6 -0
- data/lib/fun_ci/evidence/presets/rspec.yml +6 -0
- data/lib/fun_ci/evidence/presets/rubocop.yml +6 -0
- data/lib/fun_ci/evidence/presets/ruff.yml +6 -0
- data/lib/fun_ci/evidence/presets/rustc.yml +6 -0
- data/lib/fun_ci/evidence/presets/shellcheck.yml +5 -0
- data/lib/fun_ci/evidence/presets/structlog.yml +4 -0
- data/lib/fun_ci/evidence/presets/swift-test.yml +5 -0
- data/lib/fun_ci/evidence/presets/tsc.yml +6 -0
- data/lib/fun_ci/evidence/presets/unittest.yml +6 -0
- data/lib/fun_ci/evidence/presets/vitest.yml +6 -0
- data/lib/fun_ci/evidence/presets.rb +30 -0
- data/lib/fun_ci/evidence/problem.rb +9 -0
- data/lib/fun_ci/evidence/process_table.rb +40 -0
- data/lib/fun_ci/evidence/saved_run.rb +22 -0
- data/lib/fun_ci/evidence/section_walk.rb +49 -0
- data/lib/fun_ci/evidence/settings.rb +64 -0
- data/lib/fun_ci/evidence/settings_check.rb +78 -0
- data/lib/fun_ci/evidence/source.rb +34 -0
- data/lib/fun_ci/evidence/sources.rb +21 -0
- data/lib/fun_ci/evidence/stage_context.rb +30 -0
- data/lib/fun_ci/evidence/stamp.rb +10 -0
- data/lib/fun_ci/evidence/start.rb +36 -0
- data/lib/fun_ci/evidence/worktree.rb +62 -0
- data/lib/fun_ci/persistence/active_runs.rb +69 -0
- data/lib/fun_ci/persistence/database.rb +59 -30
- data/lib/fun_ci/persistence/null_recorder.rb +25 -0
- data/lib/fun_ci/persistence/output_tail.rb +24 -0
- data/lib/fun_ci/persistence/pipeline_recorder.rb +78 -32
- data/lib/fun_ci/persistence/pipeline_run.rb +26 -17
- data/lib/fun_ci/persistence/project_runs.rb +52 -0
- data/lib/fun_ci/persistence/raw_outputs.rb +46 -0
- data/lib/fun_ci/persistence/retention.rb +25 -0
- data/lib/fun_ci/persistence/run_status.rb +31 -0
- data/lib/fun_ci/persistence/stage_job.rb +58 -13
- data/lib/fun_ci/persistence/state_dir.rb +26 -0
- data/lib/fun_ci/persistence/write_trouble.rb +46 -0
- data/lib/fun_ci/pipeline/background_fork.rb +42 -0
- data/lib/fun_ci/pipeline/command_executor.rb +58 -0
- data/lib/fun_ci/pipeline/gate.rb +35 -0
- data/lib/fun_ci/pipeline/git_environment.rb +16 -0
- data/lib/fun_ci/pipeline/head_part.rb +40 -0
- data/lib/fun_ci/pipeline/in_place.rb +17 -0
- data/lib/fun_ci/pipeline/output_window.rb +73 -0
- data/lib/fun_ci/pipeline/pipeline_forker.rb +18 -16
- data/lib/fun_ci/pipeline/process_runner.rb +90 -17
- data/lib/fun_ci/pipeline/run_canceller.rb +75 -0
- data/lib/fun_ci/pipeline/slot.rb +30 -0
- data/lib/fun_ci/pipeline/slot_lock.rb +13 -0
- data/lib/fun_ci/pipeline/slot_run.rb +86 -0
- data/lib/fun_ci/pipeline/stage_dir.rb +50 -0
- data/lib/fun_ci/pipeline/stage_end.rb +70 -0
- data/lib/fun_ci/pipeline/stage_execution.rb +67 -0
- data/lib/fun_ci/pipeline/stage_runner.rb +42 -65
- data/lib/fun_ci/pipeline/stale_pipeline_canceller.rb +16 -33
- data/lib/fun_ci/pipeline/tail_segments.rb +60 -0
- data/lib/fun_ci/pipeline/test_report.rb +48 -0
- data/lib/fun_ci/pipeline/trigger.rb +55 -115
- data/lib/fun_ci/pipeline/trigger_command.rb +62 -0
- data/lib/fun_ci/pipeline/trigger_params.rb +48 -0
- data/lib/fun_ci/pipeline/workspaces.rb +22 -0
- data/lib/fun_ci/pipeline/worktree_pool.rb +66 -0
- data/lib/fun_ci/pipeline/worktree_prune.rb +49 -0
- data/lib/fun_ci/pipeline/worktrees.rb +45 -0
- data/lib/fun_ci/setup/agent_instructions.rb +31 -0
- data/lib/fun_ci/setup/commands.rb +49 -0
- data/lib/fun_ci/setup/git_hooks.rb +20 -0
- data/lib/fun_ci/setup/hook_script.rb +47 -0
- data/lib/fun_ci/setup/hook_writer.rb +13 -31
- data/lib/fun_ci/setup/installer.rb +39 -23
- data/lib/fun_ci/setup/legacy_hooks.rb +38 -0
- data/lib/fun_ci/setup/project_config.rb +43 -17
- data/lib/fun_ci/setup/project_detector.rb +39 -7
- data/lib/fun_ci/setup/settings.rb +36 -0
- data/lib/fun_ci/setup/setup_checker.rb +18 -12
- data/lib/fun_ci/setup/stage_templates/javascript.rb +18 -0
- data/lib/fun_ci/setup/stage_templates/managed.rb +24 -0
- data/lib/fun_ci/setup/stage_templates/native.rb +25 -0
- data/lib/fun_ci/setup/stage_templates/scripting.rb +27 -0
- data/lib/fun_ci/setup/stage_templates/shell.rb +16 -0
- data/lib/fun_ci/setup/stage_templates.rb +25 -0
- data/lib/fun_ci/setup/template_writer.rb +11 -36
- data/lib/fun_ci/version.rb +1 -1
- data/lib/fun_ci.rb +0 -1
- metadata +205 -41
- data/exe/fun-ci-trigger +0 -19
- data/exe/fun-ci-tui +0 -23
- data/lib/fun_ci/animations/celebrate.rb +0 -210
- data/lib/fun_ci/animations/explosion.rb +0 -138
- data/lib/fun_ci/animations/flash.rb +0 -205
- data/lib/fun_ci/animations/idle.rb +0 -127
- data/lib/fun_ci/animations/leprechauns.rb +0 -240
- data/lib/fun_ci/animations/running.rb +0 -129
- data/lib/fun_ci/animations/success.rb +0 -281
- data/lib/fun_ci/animations/yay.rb +0 -169
- data/lib/fun_ci/persistence/state_machine.rb +0 -50
- data/lib/fun_ci/pipeline/background_wrapper.rb +0 -27
- data/lib/fun_ci/tui/admin_tui.rb +0 -90
- data/lib/fun_ci/tui/animation.rb +0 -49
- data/lib/fun_ci/tui/animation_compositor.rb +0 -107
- data/lib/fun_ci/tui/animation_frames.rb +0 -112
- data/lib/fun_ci/tui/animation_library.rb +0 -46
- data/lib/fun_ci/tui/animation_renderer.rb +0 -144
- data/lib/fun_ci/tui/ansi.rb +0 -34
- data/lib/fun_ci/tui/board_data.rb +0 -53
- data/lib/fun_ci/tui/board_renderer.rb +0 -105
- data/lib/fun_ci/tui/duration_formatter.rb +0 -24
- data/lib/fun_ci/tui/header_animation_manager.rb +0 -71
- data/lib/fun_ci/tui/header_animation_player.rb +0 -45
- data/lib/fun_ci/tui/key_handler.rb +0 -86
- data/lib/fun_ci/tui/looping_animation_player.rb +0 -45
- data/lib/fun_ci/tui/relative_time.rb +0 -22
- data/lib/fun_ci/tui/row_formatter.rb +0 -108
- data/lib/fun_ci/tui/screen.rb +0 -103
- data/lib/fun_ci/tui/spinner.rb +0 -24
- data/lib/fun_ci/tui/stage_change_detector.rb +0 -58
- data/lib/fun_ci/tui/streak_counter.rb +0 -29
- data/lib/fun_ci/tui/terminal_input.rb +0 -69
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module FunCi
|
|
4
|
-
module Animations
|
|
5
|
-
module Yay
|
|
6
|
-
# YAY! wide banner — white letters, green and blue celebration
|
|
7
|
-
# Run: ruby exe/animation-player animations/yay.rb
|
|
8
|
-
|
|
9
|
-
w = "\e[1;37m" # bold white (letters only)
|
|
10
|
-
g = "\e[1;32m" # bold green
|
|
11
|
-
G = "\e[32m" # green
|
|
12
|
-
d = "\e[2;32m" # dim green
|
|
13
|
-
c = "\e[1;36m" # bold cyan
|
|
14
|
-
C = "\e[36m" # cyan
|
|
15
|
-
b = "\e[1;34m" # bold blue
|
|
16
|
-
B = "\e[34m" # blue
|
|
17
|
-
D = "\e[2;37m" # dim white (fading letters)
|
|
18
|
-
x = "\e[0m" # reset
|
|
19
|
-
|
|
20
|
-
raw_frames = [
|
|
21
|
-
# Frame 1 — dark field, spark
|
|
22
|
-
[
|
|
23
|
-
" #{d}. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .#{x}",
|
|
24
|
-
" #{d}. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .#{x}",
|
|
25
|
-
" #{d}. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .#{x}",
|
|
26
|
-
" #{d}. . . . . . . . . . . . . . . . . #{w}*#{d} . . . . . . . . . . . . . . .#{x}",
|
|
27
|
-
" #{d}. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .#{x}",
|
|
28
|
-
" #{d}. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .#{x}",
|
|
29
|
-
" #{d}. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .#{x}",
|
|
30
|
-
" #{d}. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .#{x}",
|
|
31
|
-
],
|
|
32
|
-
# Frame 2 — middle rows of letters flash in
|
|
33
|
-
[
|
|
34
|
-
" #{d}. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .#{x}",
|
|
35
|
-
" #{d}. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .#{x}",
|
|
36
|
-
" #{d}. . #{G}. . . . .#{d} . #{G}. . . . . . . . . .#{d} . #{G}. . . . .#{d} . . . . . . . .#{x}",
|
|
37
|
-
" #{d}. . . #{G}---#{w}#####{G}---#{d} . #{G}--#{w}#########{G}--#{d} . #{G}---#{w}#####{G}---#{d} . . . . . . . .#{x}",
|
|
38
|
-
" #{d}. . . . #{G}--#{w}###{G}--#{d} . . #{G}-#{w}#########{G}-#{d} . . #{G}--#{w}###{G}--#{d} . . . . . . . . .#{x}",
|
|
39
|
-
" #{d}. . #{G}' ' ' ' '#{d} . #{G}' ' ' ' ' ' ' ' '#{d} . #{G}' ' ' ' '#{d} . . . . . . . .#{x}",
|
|
40
|
-
" #{d}. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .#{x}",
|
|
41
|
-
" #{d}. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .#{x}",
|
|
42
|
-
],
|
|
43
|
-
# Frame 3 — letters expand vertically
|
|
44
|
-
[
|
|
45
|
-
" #{d}. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .#{x}",
|
|
46
|
-
" #{d}. #{G}*#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{d} . . . .#{x}",
|
|
47
|
-
" #{d}. . #{w}\\###{d} . #{w}/\\###{d} . #{w}#####{d} . #{w}#####{d} . #{w}\\###{d} . #{w}/\\###{d} . #{w}#####{d} . . . . .#{x}",
|
|
48
|
-
" #{d}. . #{G}*#{g} *#{w}#####{g} *#{G} *#{g} *#{w}#########{g} *#{G} *#{g} *#{w}#####{g} *#{G} *#{w}#####{d} . . . .#{x}",
|
|
49
|
-
" #{d}. . . . #{G}*#{g} #{w}###{g} *#{G} *#{d} . #{w}###{d} . . . . #{w}###{d} . . #{G}*#{g} #{w}###{g} *#{G} *#{d} . . . . . . .#{x}",
|
|
50
|
-
" #{d}. . #{w}/###{d} . . #{w}\\###{d} . #{w}###{d} . . . . #{w}###{d} . #{w}/###{d} . . #{w}\\###{d} . #{w}#####{d} . . . .#{x}",
|
|
51
|
-
" #{d}. #{G}'#{g} '#{G} '#{g} '#{G} '#{g} '#{G} '#{g} '#{G} '#{g} '#{G} '#{g} '#{G} '#{g} '#{G} '#{g} '#{G} '#{g} '#{G} '#{d} . . . .#{x}",
|
|
52
|
-
" #{d}. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .#{x}",
|
|
53
|
-
],
|
|
54
|
-
# Frame 4 — full letters revealed, green/cyan border
|
|
55
|
-
[
|
|
56
|
-
" #{g}*#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{x}",
|
|
57
|
-
" #{c}*#{G} . #{w}###{G} . . . . #{w}###{G} . . . #{w}#####{G} . . . #{w}###{G} . . . . #{w}###{G} . #{w}#####{G} . #{c}*#{x}",
|
|
58
|
-
" #{c}*#{G} . . #{w}###{G} . . #{w}/\\###{G} . #{w}###{G} . . #{w}###{G} . . #{w}###{G} . . #{w}/\\###{G} . #{w}#####{G} . #{c}*#{x}",
|
|
59
|
-
" #{c}*#{G} . . . #{w}#####{G} . . #{w}###{G} . . . . #{w}###{G} . . . #{w}#####{G} . . . #{w}#####{G} . #{c}*#{x}",
|
|
60
|
-
" #{c}*#{G} . . . . #{w}###{G} . . #{w}#########{G} . . . . #{w}###{G} . . . . . . . . . #{c}*#{x}",
|
|
61
|
-
" #{c}*#{G} . . . . #{w}###{G} . . #{w}###{G} . . . . #{w}###{G} . . . . #{w}###{G} . . . #{w}#####{G} . #{c}*#{x}",
|
|
62
|
-
" #{c}*#{G} . . . . #{w}###{G} . . #{w}###{G} . . . . #{w}###{G} . . . . #{w}###{G} . . . #{w}#####{G} . #{c}*#{x}",
|
|
63
|
-
" #{g}'#{c} '#{g} '#{c} '#{g} '#{c} '#{g} '#{c} '#{g} '#{c} '#{g} '#{c} '#{g} '#{c} '#{g} '#{c} '#{g} '#{c} '#{g} '#{c} '#{g} '#{c} '#{x}",
|
|
64
|
-
],
|
|
65
|
-
# (hold with colour shift)
|
|
66
|
-
[
|
|
67
|
-
" #{c}*#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{x}",
|
|
68
|
-
" #{g}*#{G} . #{w}###{G} . . . . #{w}###{G} . . . #{w}#####{G} . . . #{w}###{G} . . . . #{w}###{G} . #{w}#####{G} . #{g}*#{x}",
|
|
69
|
-
" #{g}*#{G} . . #{w}###{G} . . #{w}/\\###{G} . #{w}###{G} . . #{w}###{G} . . #{w}###{G} . . #{w}/\\###{G} . #{w}#####{G} . #{g}*#{x}",
|
|
70
|
-
" #{g}*#{G} . . . #{w}#####{G} . . #{w}###{G} . . . . #{w}###{G} . . . #{w}#####{G} . . . #{w}#####{G} . #{g}*#{x}",
|
|
71
|
-
" #{g}*#{G} . . . . #{w}###{G} . . #{w}#########{G} . . . . #{w}###{G} . . . . . . . . . #{g}*#{x}",
|
|
72
|
-
" #{g}*#{G} . . . . #{w}###{G} . . #{w}###{G} . . . . #{w}###{G} . . . . #{w}###{G} . . . #{w}#####{G} . #{g}*#{x}",
|
|
73
|
-
" #{g}*#{G} . . . . #{w}###{G} . . #{w}###{G} . . . . #{w}###{G} . . . . #{w}###{G} . . . #{w}#####{G} . #{g}*#{x}",
|
|
74
|
-
" #{c}'#{g} '#{c} '#{g} '#{c} '#{g} '#{c} '#{g} '#{c} '#{g} '#{c} '#{g} '#{c} '#{g} '#{c} '#{g} '#{c} '#{g} '#{c} '#{g} '#{c} '#{g} '#{x}",
|
|
75
|
-
],
|
|
76
|
-
# Frame 5 — colour explosion, green/blue/cyan ring
|
|
77
|
-
[
|
|
78
|
-
" #{b}*#{B} *#{b} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{b} *#{B} *#{b} *#{B} *#{x}",
|
|
79
|
-
" #{B}*#{g} *#{c} #{w}###{c} *#{g} *#{c} *#{w}###{c} *#{g} *#{c} #{w}#####{c} *#{g} *#{c} #{w}###{c} *#{g} *#{c} *#{w}###{c} * #{w}#####{c} *#{B} *#{x}",
|
|
80
|
-
" #{b}*#{c} *#{C} *#{w}###{C} *#{c} #{w}/\\###{c} *#{w}###{C} *#{c} #{w}###{C} *#{c} #{w}###{C} *#{c} #{w}/\\###{C} * #{w}#####{C} *#{b} *#{x}",
|
|
81
|
-
" #{g}*#{c} *#{G} *#{g} #{w}#####{g} *#{G} #{w}###{G} *#{g} *#{G} *#{w}###{G} *#{g} *#{w}#####{g} *#{G} *#{w}#####{g} *#{c} *#{x}",
|
|
82
|
-
" #{c}*#{g} *#{c} *#{g} *#{w}###{g} *#{c} #{w}#########{c} *#{g} *#{c} #{w}###{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{x}",
|
|
83
|
-
" #{b}*#{c} *#{C} *#{g} #{w}###{C} *#{c} *#{w}###{C} *#{c} *#{C} *#{w}###{C} *#{c} *#{C} *#{w}###{C} *#{c} * #{w}#####{C} *#{b} *#{x}",
|
|
84
|
-
" #{B}*#{g} *#{c} *#{C} *#{w}###{c} *#{g} *#{w}###{c} *#{g} *#{c} *#{w}###{c} *#{g} *#{c} *#{w}###{c} *#{g} * #{w}#####{c} *#{B} *#{x}",
|
|
85
|
-
" #{b}*#{B} *#{b} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{b} *#{B} *#{b} *#{B} *#{x}",
|
|
86
|
-
],
|
|
87
|
-
# Frame 6 — FULL CELEBRATION, dense green/blue, white letters
|
|
88
|
-
[
|
|
89
|
-
" #{b}*#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{b} *#{B} *#{x}",
|
|
90
|
-
" #{g}*#{c} *#{g} #{w}###{g} *#{c} *#{g} *#{w}###{g} *#{c} *#{g} #{w}#####{g} *#{c} *#{g} #{w}###{g} *#{c} *#{g} *#{w}###{g} * #{w}#####{g} *#{c} *#{x}",
|
|
91
|
-
" #{c}*#{g} *#{c} *#{w}###{c} *#{g} #{w}/\\###{c} *#{w}###{g} *#{c} #{w}###{g} *#{c} #{w}###{c} *#{g} #{w}/\\###{g} * #{w}#####{c} *#{g} *#{x}",
|
|
92
|
-
" #{g}*#{c} *#{g} *#{c} #{w}#####{c} *#{g} #{w}###{g} *#{c} *#{g} *#{w}###{g} *#{c} *#{w}#####{c} *#{g} *#{w}#####{c} *#{c} *#{x}",
|
|
93
|
-
" #{c}*#{g} *#{c} *#{g} *#{w}###{g} *#{c} #{w}#########{c} *#{g} *#{c} #{w}###{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{x}",
|
|
94
|
-
" #{g}*#{c} *#{g} *#{c} #{w}###{c} *#{g} *#{w}###{g} *#{c} *#{g} *#{w}###{g} *#{c} *#{g} *#{w}###{g} *#{c} * #{w}#####{c} *#{c} *#{x}",
|
|
95
|
-
" #{c}*#{g} *#{c} *#{g} #{w}###{g} *#{c} *#{w}###{c} *#{g} *#{c} *#{w}###{c} *#{g} *#{c} *#{w}###{g} *#{c} * #{w}#####{g} *#{g} *#{x}",
|
|
96
|
-
" #{b}*#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{b} *#{B} *#{x}",
|
|
97
|
-
],
|
|
98
|
-
# (hold — green/cyan shimmer)
|
|
99
|
-
[
|
|
100
|
-
" #{c}*#{g} *#{c} *#{g} *#{b} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{b} *#{g} *#{c} *#{g} *#{c} *#{b} *#{x}",
|
|
101
|
-
" #{g}*#{G} *#{c} #{w}###{G} *#{g} *#{G} *#{w}###{g} *#{G} *#{g} #{w}#####{G} *#{g} *#{G} #{w}###{g} *#{G} *#{g} *#{w}###{G} * #{w}#####{g} *#{g} *#{x}",
|
|
102
|
-
" #{c}*#{C} *#{g} *#{w}###{g} *#{C} #{w}/\\###{g} *#{w}###{C} *#{g} #{w}###{C} *#{g} #{w}###{g} *#{C} #{w}/\\###{C} * #{w}#####{g} *#{c} *#{x}",
|
|
103
|
-
" #{g}*#{G} *#{c} *#{g} #{w}#####{g} *#{G} #{w}###{G} *#{g} *#{G} *#{w}###{G} *#{g} *#{w}#####{g} *#{G} *#{w}#####{g} *#{g} *#{x}",
|
|
104
|
-
" #{c}*#{C} *#{g} *#{c} *#{w}###{c} *#{C} #{w}#########{C} *#{c} *#{C} #{w}###{c} *#{C} *#{c} *#{C} *#{c} *#{C} *#{c} *#{x}",
|
|
105
|
-
" #{g}*#{G} *#{c} *#{g} #{w}###{g} *#{G} *#{w}###{G} *#{g} *#{G} *#{w}###{G} *#{g} *#{G} *#{w}###{G} *#{g} * #{w}#####{g} *#{g} *#{x}",
|
|
106
|
-
" #{c}*#{C} *#{g} *#{c} #{w}###{c} *#{C} *#{w}###{C} *#{c} *#{C} *#{w}###{C} *#{c} *#{C} *#{w}###{c} *#{C} * #{w}#####{c} *#{c} *#{x}",
|
|
107
|
-
" #{c}*#{g} *#{c} *#{g} *#{b} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{b} *#{g} *#{c} *#{g} *#{c} *#{b} *#{x}",
|
|
108
|
-
],
|
|
109
|
-
# (hold — blue accent shift)
|
|
110
|
-
[
|
|
111
|
-
" #{B}*#{b} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{b} *#{B} *#{b} *#{B} *#{x}",
|
|
112
|
-
" #{b}*#{c} *#{g} #{w}###{c} *#{g} *#{c} *#{w}###{g} *#{c} *#{g} #{w}#####{c} *#{g} *#{c} #{w}###{g} *#{c} *#{g} *#{w}###{c} * #{w}#####{g} *#{b} *#{x}",
|
|
113
|
-
" #{g}*#{c} *#{c} *#{w}###{g} *#{c} #{w}/\\###{g} *#{w}###{c} *#{g} #{w}###{c} *#{g} #{w}###{g} *#{c} #{w}/\\###{c} * #{w}#####{g} *#{g} *#{x}",
|
|
114
|
-
" #{c}*#{g} *#{g} *#{c} #{w}#####{c} *#{g} #{w}###{g} *#{c} *#{g} *#{w}###{g} *#{c} *#{w}#####{c} *#{g} *#{w}#####{c} *#{c} *#{x}",
|
|
115
|
-
" #{g}*#{c} *#{c} *#{g} *#{w}###{g} *#{c} #{w}#########{c} *#{g} *#{c} #{w}###{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{x}",
|
|
116
|
-
" #{c}*#{g} *#{g} *#{c} #{w}###{c} *#{g} *#{w}###{g} *#{c} *#{g} *#{w}###{g} *#{c} *#{g} *#{w}###{g} *#{c} * #{w}#####{c} *#{c} *#{x}",
|
|
117
|
-
" #{b}*#{c} *#{c} *#{g} #{w}###{g} *#{c} *#{w}###{c} *#{g} *#{c} *#{w}###{c} *#{g} *#{c} *#{w}###{c} *#{g} * #{w}#####{g} *#{b} *#{x}",
|
|
118
|
-
" #{B}*#{b} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{b} *#{B} *#{b} *#{B} *#{x}",
|
|
119
|
-
],
|
|
120
|
-
# Frame 7 — settling, letters still bright
|
|
121
|
-
[
|
|
122
|
-
" #{d}. #{b}*#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{b} *#{d} . . .#{x}",
|
|
123
|
-
" #{b}*#{c} *#{C} #{w}###{C} *#{c} *#{C} *#{w}###{C} *#{c} *#{C} #{w}#####{C} *#{c} *#{C} #{w}###{c} *#{C} *#{c} *#{w}###{C} * #{w}#####{c} *#{b} *#{x}",
|
|
124
|
-
" #{g}*#{G} *#{g} *#{w}###{g} *#{G} #{w}/\\###{g} *#{w}###{G} *#{g} #{w}###{G} *#{g} #{w}###{g} *#{G} #{w}/\\###{G} * #{w}#####{g} *#{g} *#{x}",
|
|
125
|
-
" #{c}*#{C} *#{g} *#{c} #{w}#####{c} *#{C} #{w}###{C} *#{c} *#{C} *#{w}###{C} *#{c} *#{w}#####{c} *#{C} *#{w}#####{c} *#{c} *#{x}",
|
|
126
|
-
" #{g}*#{G} *#{c} *#{g} *#{w}###{g} *#{G} #{w}#########{G} *#{g} *#{G} #{w}###{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{x}",
|
|
127
|
-
" #{c}*#{C} *#{g} *#{c} #{w}###{C} *#{c} *#{w}###{C} *#{c} *#{C} *#{w}###{C} *#{c} *#{C} *#{w}###{C} *#{c} * #{w}#####{C} *#{c} *#{x}",
|
|
128
|
-
" #{b}*#{c} *#{C} *#{g} #{w}###{C} *#{c} *#{w}###{C} *#{c} *#{C} *#{w}###{C} *#{c} *#{C} *#{w}###{c} *#{C} * #{w}#####{C} *#{b} *#{x}",
|
|
129
|
-
" #{d}. #{b}*#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{g} *#{c} *#{b} *#{d} . . .#{x}",
|
|
130
|
-
],
|
|
131
|
-
# Frame 8 — fading, letters on green field
|
|
132
|
-
[
|
|
133
|
-
" #{d}. . #{g}*#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{d} . . .#{x}",
|
|
134
|
-
" #{d}. #{g}*#{G} . #{w}###{G} . . . . #{w}###{G} . . . #{w}#####{G} . . . #{w}###{G} . . . . #{w}###{G} . #{w}#####{G} .#{g} *#{d} .#{x}",
|
|
135
|
-
" #{d}. #{g}*#{G} . . #{w}###{G} . . #{w}/\\###{G} . #{w}###{G} . . #{w}###{G} . . #{w}###{G} . . #{w}/\\###{G} . #{w}#####{G} .#{g} *#{d} .#{x}",
|
|
136
|
-
" #{d}. . #{g}*#{G} . . #{w}#####{G} . . #{w}###{G} . . . . #{w}###{G} . . . #{w}#####{G} . . . #{w}#####{G} .#{g} *#{d} .#{x}",
|
|
137
|
-
" #{d}. . #{g}*#{G} . . . #{w}###{G} . . #{w}#########{G} . . . . #{w}###{G} . . . . . . . . . .#{g} *#{d} .#{x}",
|
|
138
|
-
" #{d}. #{g}*#{G} . . . #{w}###{G} . . #{w}###{G} . . . . #{w}###{G} . . . . #{w}###{G} . . . #{w}#####{G} .#{g} *#{d} .#{x}",
|
|
139
|
-
" #{d}. #{g}*#{G} . . . #{w}###{G} . . #{w}###{G} . . . . #{w}###{G} . . . . #{w}###{G} . . . #{w}#####{G} .#{g} *#{d} .#{x}",
|
|
140
|
-
" #{d}. . #{g}*#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{d} . . .#{x}",
|
|
141
|
-
],
|
|
142
|
-
# Frame 9 — almost gone, dim letters
|
|
143
|
-
[
|
|
144
|
-
" #{d}. . . . #{G}*#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{G} *#{g} *#{d} . . . . .#{x}",
|
|
145
|
-
" #{d}. . . #{G}. #{D}###{G} . . . . #{D}###{G} . . . #{D}#####{G} . . . #{D}###{G} . . . . #{D}###{G} . #{D}#####{G} . . .#{x}",
|
|
146
|
-
" #{d}. . . . #{D}\\###{d} . . #{D}/\\###{d} . #{D}###{d} . . #{D}###{d} . . #{D}\\###{d} . . #{D}/\\###{d} . #{D}#####{d} . . .#{x}",
|
|
147
|
-
" #{d}. . . . . #{D}#####{d} . . #{D}###{d} . . . . #{D}###{d} . . . #{D}#####{d} . . . #{D}#####{d} . . .#{x}",
|
|
148
|
-
" #{d}. . . . . . #{D}###{d} . . #{D}#########{d} . . . . #{D}###{d} . . . . . . . . . . . .#{x}",
|
|
149
|
-
" #{d}. . . . . #{D}###{d} . . #{D}###{d} . . . . #{D}###{d} . . . . #{D}###{d} . . . #{D}#####{d} . . . .#{x}",
|
|
150
|
-
" #{d}. . . #{G}. #{D}\\###{G} . . #{D}\\###{G} . #{D}###{G} . . #{D}###{G} . #{D}\\###{G} . . #{D}\\###{G} . #{D}#####{G} . . .#{x}",
|
|
151
|
-
" #{d}. . . . #{G}'#{g} '#{G} '#{g} '#{G} '#{g} '#{G} '#{g} '#{G} '#{g} '#{G} '#{g} '#{G} '#{g} '#{G} '#{g} '#{d} . . . . .#{x}",
|
|
152
|
-
],
|
|
153
|
-
]
|
|
154
|
-
|
|
155
|
-
# Pad lines so all rows in each frame have equal stripped length —
|
|
156
|
-
# prevents the player's per-line centering from misaligning the art.
|
|
157
|
-
max = raw_frames.flatten.map { |l| l.gsub(/\e\[[0-9;]*m/, "").length }.max
|
|
158
|
-
raw_frames.each do |frame|
|
|
159
|
-
frame.map! { |l| l + " " * (max - l.gsub(/\e\[[0-9;]*m/, "").length) }
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
DATA = {
|
|
163
|
-
name: "YAY!",
|
|
164
|
-
fps: 8,
|
|
165
|
-
frames: raw_frames
|
|
166
|
-
}.freeze
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
end
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module FunCi
|
|
4
|
-
module Persistence
|
|
5
|
-
class StateMachine
|
|
6
|
-
class InvalidTransition < StandardError; end
|
|
7
|
-
|
|
8
|
-
STATES = %i[scheduled running completed failed timed_out cancelled].freeze
|
|
9
|
-
|
|
10
|
-
TRANSITIONS = {
|
|
11
|
-
scheduled: %i[running cancelled],
|
|
12
|
-
running: %i[completed failed timed_out cancelled],
|
|
13
|
-
completed: [],
|
|
14
|
-
failed: [],
|
|
15
|
-
timed_out: [],
|
|
16
|
-
cancelled: []
|
|
17
|
-
}.freeze
|
|
18
|
-
|
|
19
|
-
TERMINAL_STATES = %i[completed failed timed_out cancelled].freeze
|
|
20
|
-
|
|
21
|
-
attr_reader :current_state
|
|
22
|
-
|
|
23
|
-
def initialize(initial_state)
|
|
24
|
-
validate_state!(initial_state)
|
|
25
|
-
@current_state = initial_state
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def transition_to!(new_state)
|
|
29
|
-
validate_state!(new_state)
|
|
30
|
-
unless TRANSITIONS.fetch(@current_state).include?(new_state)
|
|
31
|
-
raise InvalidTransition,
|
|
32
|
-
"Cannot transition from #{@current_state} to #{new_state}"
|
|
33
|
-
end
|
|
34
|
-
@current_state = new_state
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def terminal?
|
|
38
|
-
TERMINAL_STATES.include?(@current_state)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
private
|
|
42
|
-
|
|
43
|
-
def validate_state!(state)
|
|
44
|
-
return if STATES.include?(state)
|
|
45
|
-
|
|
46
|
-
raise ArgumentError, "Unknown state: #{state}. Valid states: #{STATES.join(", ")}"
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module FunCi
|
|
4
|
-
module Pipeline
|
|
5
|
-
class BackgroundWrapper
|
|
6
|
-
def initialize(recorder:, job_id:, executor:)
|
|
7
|
-
@recorder = recorder
|
|
8
|
-
@job_id = job_id
|
|
9
|
-
@executor = executor
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def run
|
|
13
|
-
_output, status, timed_out = @executor.call
|
|
14
|
-
if timed_out
|
|
15
|
-
@recorder.end_stage(@job_id, "timed_out")
|
|
16
|
-
@recorder.fail_run
|
|
17
|
-
elsif status.success?
|
|
18
|
-
@recorder.end_stage(@job_id, "completed")
|
|
19
|
-
@recorder.complete_run
|
|
20
|
-
else
|
|
21
|
-
@recorder.end_stage(@job_id, "failed")
|
|
22
|
-
@recorder.fail_run
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
data/lib/fun_ci/tui/admin_tui.rb
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "board_data"
|
|
4
|
-
require_relative "board_renderer"
|
|
5
|
-
require_relative "key_handler"
|
|
6
|
-
require_relative "screen"
|
|
7
|
-
require_relative "spinner"
|
|
8
|
-
require_relative "terminal_input"
|
|
9
|
-
require "io/console"
|
|
10
|
-
|
|
11
|
-
module FunCi
|
|
12
|
-
module Tui
|
|
13
|
-
class AdminTui
|
|
14
|
-
FAST_REFRESH = 0.1
|
|
15
|
-
SLOW_REFRESH = 5.0
|
|
16
|
-
|
|
17
|
-
def initialize(db:, output: $stdout, input: $stdin, width: 80,
|
|
18
|
-
width_provider: nil, height_provider: nil,
|
|
19
|
-
page_size: nil, animation_renderer: nil)
|
|
20
|
-
@board_data = BoardData.new(db, page_size: page_size)
|
|
21
|
-
@terminal_input = TerminalInput.new(input: input, width_provider: width_provider)
|
|
22
|
-
@key_handler = KeyHandler.new(board_data: @board_data)
|
|
23
|
-
@renderer = BoardRenderer.new(
|
|
24
|
-
screen: Screen.new(output: output, width: width),
|
|
25
|
-
spinner: Spinner.new,
|
|
26
|
-
animation_renderer: animation_renderer,
|
|
27
|
-
height_provider: height_provider
|
|
28
|
-
)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def render_once
|
|
32
|
-
update_width_from_provider
|
|
33
|
-
@renderer.render(
|
|
34
|
-
runs: @board_data.runs,
|
|
35
|
-
streak: @board_data.streak,
|
|
36
|
-
cursor_index: @key_handler.cursor_index,
|
|
37
|
-
confirming: @key_handler.confirming?
|
|
38
|
-
)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def run
|
|
42
|
-
@renderer.clear
|
|
43
|
-
|
|
44
|
-
begin
|
|
45
|
-
@terminal_input.setup_raw_mode
|
|
46
|
-
@terminal_input.setup_signal_trap
|
|
47
|
-
loop do
|
|
48
|
-
@renderer.begin_frame
|
|
49
|
-
render_once
|
|
50
|
-
key = @terminal_input.read_key_with_timeout(refresh_interval)
|
|
51
|
-
break if key && @key_handler.handle_key(key) == :quit
|
|
52
|
-
end
|
|
53
|
-
ensure
|
|
54
|
-
@terminal_input.restore_terminal
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def resize(new_width)
|
|
59
|
-
@renderer.resize(new_width)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def confirming?
|
|
63
|
-
@key_handler.confirming?
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def confirmation_run
|
|
67
|
-
@key_handler.confirmation_run
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def handle_key(key)
|
|
71
|
-
@key_handler.handle_key(key)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
private
|
|
75
|
-
|
|
76
|
-
def refresh_interval
|
|
77
|
-
return FAST_REFRESH if @renderer.animation_renderer?
|
|
78
|
-
|
|
79
|
-
runs = @board_data.runs
|
|
80
|
-
any_running = runs.any? { |r| r[:status] == "running" }
|
|
81
|
-
any_running ? FAST_REFRESH : SLOW_REFRESH
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def update_width_from_provider
|
|
85
|
-
new_width = @terminal_input.check_width
|
|
86
|
-
@renderer.resize(new_width) if new_width
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
data/lib/fun_ci/tui/animation.rb
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module FunCi
|
|
4
|
-
module Tui
|
|
5
|
-
class Animation
|
|
6
|
-
TYPES = {
|
|
7
|
-
failure: { total_frames: 40, priority: 3 },
|
|
8
|
-
timeout: { total_frames: 4, priority: 2 },
|
|
9
|
-
success: { total_frames: 40, priority: 1 },
|
|
10
|
-
stage_pass: { total_frames: 3, priority: 0 }
|
|
11
|
-
}.freeze
|
|
12
|
-
|
|
13
|
-
attr_reader :type, :run_id, :stage, :frame
|
|
14
|
-
|
|
15
|
-
def initialize(type:, run_id:, stage: nil)
|
|
16
|
-
raise ArgumentError, "Unknown animation type: #{type}" unless TYPES.key?(type)
|
|
17
|
-
|
|
18
|
-
@type = type
|
|
19
|
-
@run_id = run_id
|
|
20
|
-
@stage = stage
|
|
21
|
-
@frame = 0
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def advance!
|
|
25
|
-
@frame += 1
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def finished?
|
|
29
|
-
frame >= total_frames
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def total_frames
|
|
33
|
-
TYPES[@type][:total_frames]
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def priority
|
|
37
|
-
TYPES[@type][:priority]
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def has_header?
|
|
41
|
-
%i[failure timeout success].include?(@type)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def has_footer?
|
|
45
|
-
%i[failure success].include?(@type)
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "ansi"
|
|
4
|
-
require_relative "animation_frames"
|
|
5
|
-
require_relative "row_formatter"
|
|
6
|
-
require_relative "duration_formatter"
|
|
7
|
-
|
|
8
|
-
module FunCi
|
|
9
|
-
module Tui
|
|
10
|
-
module AnimationCompositor
|
|
11
|
-
RESET = Ansi::RESET
|
|
12
|
-
STAGE_STAGGER = { "lint" => 0, "build" => 2, "fast" => 4, "slow" => 6 }.freeze
|
|
13
|
-
|
|
14
|
-
def self.header_overlay(animation, width)
|
|
15
|
-
frames = case animation.type
|
|
16
|
-
when :failure then AnimationFrames.failure_header(width)
|
|
17
|
-
when :success then AnimationFrames.success_header(width)
|
|
18
|
-
when :timeout then AnimationFrames.timeout_header(width)
|
|
19
|
-
else return nil
|
|
20
|
-
end
|
|
21
|
-
frame_at(frames, animation.frame)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def self.footer_overlay(animation, width)
|
|
25
|
-
frames = case animation.type
|
|
26
|
-
when :failure
|
|
27
|
-
AnimationFrames.failure_footer(animation.stage || "stage", width)
|
|
28
|
-
when :success then AnimationFrames.success_footer(width)
|
|
29
|
-
else return nil
|
|
30
|
-
end
|
|
31
|
-
frame_at(frames, animation.frame)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def self.stage_column_overlay(animation, stage_text, col)
|
|
35
|
-
case animation.type
|
|
36
|
-
when :stage_pass then color_flash(animation, stage_text, AnimationFrames.stage_pass_colors)
|
|
37
|
-
when :timeout then color_flash(animation, stage_text, AnimationFrames.timeout_colors)
|
|
38
|
-
when :failure then failure_flanks(animation, stage_text)
|
|
39
|
-
when :success then sparkle_sweep(animation, stage_text)
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def self.stage_text_for(run, stage_name)
|
|
44
|
-
stage = run[:stages]&.find { |s| s[:stage] == stage_name }
|
|
45
|
-
return nil unless stage
|
|
46
|
-
|
|
47
|
-
name = RowFormatter::STAGE_NAMES[stage[:stage]] || stage[:stage]
|
|
48
|
-
dur = stage[:duration] ? DurationFormatter.format(stage[:duration]) : "--"
|
|
49
|
-
case stage[:status]
|
|
50
|
-
when "completed" then "#{name} #{dur}"
|
|
51
|
-
when "failed" then "#{name} FAIL #{dur}"
|
|
52
|
-
when "timed_out" then "#{name} TIMEOUT #{dur}"
|
|
53
|
-
else "#{name} --"
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def self.stage_col_for(run, stage_name)
|
|
58
|
-
project = run[:project_path] ? " #{File.basename(run[:project_path])}" : ""
|
|
59
|
-
prefix_len = 2 + 7 + 2 + run[:branch].to_s.length + project.length + 2
|
|
60
|
-
(run[:stages] || []).each do |s|
|
|
61
|
-
return prefix_len + 1 if s[:stage] == stage_name
|
|
62
|
-
prefix_len += stage_text_for(run, s[:stage]).to_s.length + 2
|
|
63
|
-
end
|
|
64
|
-
nil
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def self.color_flash(animation, stage_text, colors)
|
|
68
|
-
idx = [animation.frame, colors.length - 1].min
|
|
69
|
-
"#{colors[idx]}#{Ansi.strip(stage_text)}#{RESET}"
|
|
70
|
-
end
|
|
71
|
-
private_class_method :color_flash
|
|
72
|
-
|
|
73
|
-
def self.failure_flanks(animation, stage_text)
|
|
74
|
-
particles = AnimationFrames.failure_particles
|
|
75
|
-
return nil if animation.frame >= particles.length
|
|
76
|
-
|
|
77
|
-
p = particles[animation.frame]
|
|
78
|
-
plain = Ansi.strip(stage_text)
|
|
79
|
-
return plain if p[:chars].empty?
|
|
80
|
-
|
|
81
|
-
left = p[:chars].reverse
|
|
82
|
-
right = p[:chars]
|
|
83
|
-
"#{p[:color]}#{left}#{RESET} #{Ansi.bold_red(plain)} #{p[:color]}#{right}#{RESET}"
|
|
84
|
-
end
|
|
85
|
-
private_class_method :failure_flanks
|
|
86
|
-
|
|
87
|
-
def self.sparkle_sweep(animation, stage_text)
|
|
88
|
-
plain = Ansi.strip(stage_text)
|
|
89
|
-
stagger = STAGE_STAGGER[animation.stage] || 0
|
|
90
|
-
pos = animation.frame - stagger
|
|
91
|
-
return nil if pos < 0 || pos > plain.length
|
|
92
|
-
|
|
93
|
-
result = plain.chars.map { |c| "\e[32m#{c}" }
|
|
94
|
-
result[pos] = "\e[1;33m#{plain[pos]}" if pos < plain.length
|
|
95
|
-
"#{result.join}#{RESET}"
|
|
96
|
-
end
|
|
97
|
-
private_class_method :sparkle_sweep
|
|
98
|
-
|
|
99
|
-
def self.frame_at(frames, index)
|
|
100
|
-
return nil if index >= frames.length
|
|
101
|
-
|
|
102
|
-
frames[index]
|
|
103
|
-
end
|
|
104
|
-
private_class_method :frame_at
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
end
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "ansi"
|
|
4
|
-
|
|
5
|
-
module FunCi
|
|
6
|
-
module Tui
|
|
7
|
-
module AnimationFrames
|
|
8
|
-
RESET = Ansi::RESET
|
|
9
|
-
FOOTER_HOLD = 8
|
|
10
|
-
|
|
11
|
-
def self.failure_particles
|
|
12
|
-
[
|
|
13
|
-
{ chars: "*", color: "\e[1;31m" },
|
|
14
|
-
{ chars: ".*", color: "\e[1;31m" },
|
|
15
|
-
{ chars: ".+*.", color: "\e[38;5;208m" },
|
|
16
|
-
{ chars: "*.+'", color: "\e[38;5;208m" },
|
|
17
|
-
{ chars: "' .", color: "\e[38;5;52m" },
|
|
18
|
-
{ chars: ".", color: "\e[38;5;52m" },
|
|
19
|
-
{ chars: "", color: "" }
|
|
20
|
-
]
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def self.failure_header(width)
|
|
24
|
-
boom = "BOOM"
|
|
25
|
-
[
|
|
26
|
-
nil,
|
|
27
|
-
banner(boom, width, "\e[48;5;124m", particles: "* "),
|
|
28
|
-
banner(boom, width, "\e[48;5;166m", particles: "* * "),
|
|
29
|
-
banner(boom, width, "\e[48;5;52m", particles: ". * * "),
|
|
30
|
-
banner(boom, width, "\e[48;5;236m", particles: "' . * "),
|
|
31
|
-
banner(boom, width, "\e[48;5;236m", particles: ". "),
|
|
32
|
-
nil
|
|
33
|
-
]
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def self.failure_footer(stage_name, width)
|
|
37
|
-
up = stage_name.upcase
|
|
38
|
-
down = stage_name.downcase
|
|
39
|
-
hold [
|
|
40
|
-
nil,
|
|
41
|
-
center("\e[1;31m>>> #{up} FAILED <<<#{RESET}", ">>> #{up} FAILED <<<", width),
|
|
42
|
-
center("\e[31m>> #{down} failed <<#{RESET}", ">> #{down} failed <<", width),
|
|
43
|
-
center("\e[2;31m> #{down} failed <#{RESET}", "> #{down} failed <", width),
|
|
44
|
-
nil
|
|
45
|
-
]
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def self.success_header(width)
|
|
49
|
-
text = "ALL PASSED"
|
|
50
|
-
[
|
|
51
|
-
nil,
|
|
52
|
-
banner(text, width, "\e[48;5;22m", particles: ""),
|
|
53
|
-
banner(text, width, "\e[48;5;22m", particles: "* * "),
|
|
54
|
-
banner(text, width, "\e[48;5;22m", particles: "* . . "),
|
|
55
|
-
banner(text, width, "\e[48;5;58m", particles: ". ' ' "),
|
|
56
|
-
banner(text, width, "\e[48;5;22m", particles: "' "),
|
|
57
|
-
banner(text, width, "\e[48;5;22m", particles: ""),
|
|
58
|
-
nil
|
|
59
|
-
]
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def self.success_footer(width)
|
|
63
|
-
hold [
|
|
64
|
-
nil,
|
|
65
|
-
center("\e[1;32m* * * NICE! * * *#{RESET}", "* * * NICE! * * *", width),
|
|
66
|
-
center("\e[32m. + . * NICE! * . + .#{RESET}", ". + . * NICE! * . + .", width),
|
|
67
|
-
center("\e[2;32m' . + . nice . + . '#{RESET}", "' . + . nice . + . '", width),
|
|
68
|
-
nil
|
|
69
|
-
]
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def self.timeout_header(width)
|
|
73
|
-
[
|
|
74
|
-
nil,
|
|
75
|
-
banner("TIMED OUT", width, "\e[48;5;58m", particles: ""),
|
|
76
|
-
banner("timed out", width, "\e[48;5;58m", particles: ""),
|
|
77
|
-
nil
|
|
78
|
-
]
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def self.stage_pass_colors
|
|
82
|
-
["\e[1;33m", "\e[1;32m", "\e[32m"]
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def self.timeout_colors
|
|
86
|
-
["\e[1;33m", "\e[33m", "\e[1;33m", "\e[33m"]
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def self.banner(text, width, bg_code, particles: "")
|
|
90
|
-
padded = if particles.empty?
|
|
91
|
-
text.center(width)
|
|
92
|
-
else
|
|
93
|
-
inner = "#{particles} #{text} #{particles.reverse}"
|
|
94
|
-
inner.center(width)
|
|
95
|
-
end
|
|
96
|
-
"#{bg_code}\e[1;37m#{padded}#{RESET}"
|
|
97
|
-
end
|
|
98
|
-
private_class_method :banner
|
|
99
|
-
|
|
100
|
-
def self.hold(frames)
|
|
101
|
-
frames.flat_map { |f| Array.new(FOOTER_HOLD, f) }
|
|
102
|
-
end
|
|
103
|
-
private_class_method :hold
|
|
104
|
-
|
|
105
|
-
def self.center(colored_text, plain_text, width)
|
|
106
|
-
pad = [(width - plain_text.length) / 2, 0].max
|
|
107
|
-
"#{" " * pad}#{colored_text}"
|
|
108
|
-
end
|
|
109
|
-
private_class_method :center
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
end
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "../animations/explosion"
|
|
4
|
-
require_relative "../animations/success"
|
|
5
|
-
require_relative "../animations/celebrate"
|
|
6
|
-
require_relative "../animations/flash"
|
|
7
|
-
require_relative "../animations/leprechauns"
|
|
8
|
-
require_relative "../animations/yay"
|
|
9
|
-
require_relative "../animations/idle"
|
|
10
|
-
require_relative "../animations/running"
|
|
11
|
-
|
|
12
|
-
module FunCi
|
|
13
|
-
module Tui
|
|
14
|
-
module AnimationLibrary
|
|
15
|
-
FAILURE = [Animations::Explosion::DATA].freeze
|
|
16
|
-
|
|
17
|
-
SUCCESS = [
|
|
18
|
-
Animations::Success::DATA,
|
|
19
|
-
Animations::Celebrate::DATA,
|
|
20
|
-
Animations::Flash::DATA,
|
|
21
|
-
Animations::Leprechauns::DATA,
|
|
22
|
-
Animations::Yay::DATA
|
|
23
|
-
].freeze
|
|
24
|
-
|
|
25
|
-
IDLE = Animations::Idle::DATA
|
|
26
|
-
|
|
27
|
-
RUNNING = Animations::Running::DATA
|
|
28
|
-
|
|
29
|
-
def self.random_failure
|
|
30
|
-
FAILURE.sample
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def self.random_success
|
|
34
|
-
SUCCESS.sample
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def self.idle
|
|
38
|
-
IDLE
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def self.running
|
|
42
|
-
RUNNING
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|