fun_ci 1.0.0 → 1.2.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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -0
  3. data/README.md +3 -1
  4. data/exe/fun-ci-trigger +6 -6
  5. data/exe/fun-ci-tui +9 -4
  6. data/lib/fun_ci/animations/celebrate.rb +210 -0
  7. data/lib/fun_ci/animations/explosion.rb +138 -0
  8. data/lib/fun_ci/animations/flash.rb +205 -0
  9. data/lib/fun_ci/animations/idle.rb +127 -0
  10. data/lib/fun_ci/animations/leprechauns.rb +240 -0
  11. data/lib/fun_ci/animations/running.rb +129 -0
  12. data/lib/fun_ci/animations/success.rb +281 -0
  13. data/lib/fun_ci/animations/yay.rb +169 -0
  14. data/lib/fun_ci/cli.rb +20 -14
  15. data/lib/fun_ci/persistence/database.rb +52 -0
  16. data/lib/fun_ci/persistence/pipeline_recorder.rb +74 -0
  17. data/lib/fun_ci/persistence/pipeline_run.rb +59 -0
  18. data/lib/fun_ci/persistence/stage_job.rb +46 -0
  19. data/lib/fun_ci/{state_machine.rb → persistence/state_machine.rb} +3 -12
  20. data/lib/fun_ci/pipeline/background_wrapper.rb +27 -0
  21. data/lib/fun_ci/pipeline/pipeline_forker.rb +38 -0
  22. data/lib/fun_ci/pipeline/process_runner.rb +28 -0
  23. data/lib/fun_ci/pipeline/progress_reporter.rb +31 -0
  24. data/lib/fun_ci/pipeline/stage_runner.rb +85 -0
  25. data/lib/fun_ci/pipeline/stale_pipeline_canceller.rb +53 -0
  26. data/lib/fun_ci/pipeline/trigger.rb +153 -0
  27. data/lib/fun_ci/setup/hook_writer.rb +75 -0
  28. data/lib/fun_ci/setup/installer.rb +55 -0
  29. data/lib/fun_ci/setup/maven_linter_detector.rb +26 -0
  30. data/lib/fun_ci/setup/project_config.rb +42 -0
  31. data/lib/fun_ci/setup/project_detector.rb +22 -0
  32. data/lib/fun_ci/setup/setup_checker.rb +30 -0
  33. data/lib/fun_ci/setup/template_writer.rb +53 -0
  34. data/lib/fun_ci/tui/admin_tui.rb +90 -0
  35. data/lib/fun_ci/tui/animation.rb +49 -0
  36. data/lib/fun_ci/tui/animation_compositor.rb +107 -0
  37. data/lib/fun_ci/tui/animation_frames.rb +112 -0
  38. data/lib/fun_ci/tui/animation_library.rb +46 -0
  39. data/lib/fun_ci/tui/animation_renderer.rb +144 -0
  40. data/lib/fun_ci/tui/ansi.rb +34 -0
  41. data/lib/fun_ci/tui/board_data.rb +53 -0
  42. data/lib/fun_ci/tui/board_renderer.rb +105 -0
  43. data/lib/fun_ci/tui/duration_formatter.rb +24 -0
  44. data/lib/fun_ci/tui/header_animation_manager.rb +71 -0
  45. data/lib/fun_ci/tui/header_animation_player.rb +45 -0
  46. data/lib/fun_ci/tui/key_handler.rb +86 -0
  47. data/lib/fun_ci/tui/looping_animation_player.rb +45 -0
  48. data/lib/fun_ci/tui/relative_time.rb +22 -0
  49. data/lib/fun_ci/tui/row_formatter.rb +108 -0
  50. data/lib/fun_ci/tui/screen.rb +103 -0
  51. data/lib/fun_ci/tui/spinner.rb +24 -0
  52. data/lib/fun_ci/tui/stage_change_detector.rb +58 -0
  53. data/lib/fun_ci/tui/streak_counter.rb +29 -0
  54. data/lib/fun_ci/tui/terminal_input.rb +69 -0
  55. data/lib/fun_ci.rb +6 -6
  56. metadata +49 -28
  57. data/lib/fun_ci/admin_tui.rb +0 -226
  58. data/lib/fun_ci/ansi.rb +0 -21
  59. data/lib/fun_ci/background_wrapper.rb +0 -27
  60. data/lib/fun_ci/board_data.rb +0 -51
  61. data/lib/fun_ci/database.rb +0 -50
  62. data/lib/fun_ci/duration_formatter.rb +0 -23
  63. data/lib/fun_ci/hook_writer.rb +0 -73
  64. data/lib/fun_ci/installer.rb +0 -53
  65. data/lib/fun_ci/maven_linter_detector.rb +0 -24
  66. data/lib/fun_ci/pipeline_forker.rb +0 -36
  67. data/lib/fun_ci/pipeline_recorder.rb +0 -72
  68. data/lib/fun_ci/pipeline_run.rb +0 -57
  69. data/lib/fun_ci/progress_reporter.rb +0 -29
  70. data/lib/fun_ci/project_config.rb +0 -40
  71. data/lib/fun_ci/project_detector.rb +0 -18
  72. data/lib/fun_ci/relative_time.rb +0 -20
  73. data/lib/fun_ci/row_formatter.rb +0 -106
  74. data/lib/fun_ci/screen.rb +0 -81
  75. data/lib/fun_ci/setup_checker.rb +0 -28
  76. data/lib/fun_ci/spinner.rb +0 -22
  77. data/lib/fun_ci/stage_job.rb +0 -44
  78. data/lib/fun_ci/stage_runner.rb +0 -108
  79. data/lib/fun_ci/stale_pipeline_canceller.rb +0 -51
  80. data/lib/fun_ci/streak_counter.rb +0 -30
  81. data/lib/fun_ci/template_writer.rb +0 -51
  82. data/lib/fun_ci/trigger.rb +0 -150
@@ -1,150 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "open3"
4
- require "timeout"
5
- require_relative "project_config"
6
- require_relative "pipeline_recorder"
7
- require_relative "background_wrapper"
8
- require_relative "stage_runner"
9
- require_relative "stale_pipeline_canceller"
10
- require_relative "progress_reporter"
11
- require_relative "pipeline_forker"
12
-
13
- module FunCi
14
- class Trigger
15
- DEFAULT_BUDGETS = {
16
- "lint" => 30,
17
- "build" => 30,
18
- "fast" => 10,
19
- "slow" => 300
20
- }.freeze
21
-
22
- def self.run_from_args(args, stdout: $stdout, stderr: $stderr, recorder: NullRecorder.new, pipeline_forker: nil)
23
- positional = args.reject { |a| a.start_with?("--") }
24
- if positional.length < 2
25
- stderr.puts "fun-ci: commit hash and branch name are required."
26
- stderr.puts "Usage: fun-ci trigger <commit-hash> <branch>"
27
- return 1
28
- end
29
- commit_hash, branch = positional
30
- if args.include?("--no-validate")
31
- db_path = recorder.db_path
32
- recorder.close
33
- (pipeline_forker || PipelineForker.method(:fork_pipeline)).call(
34
- commit_hash: commit_hash, branch: branch, db_path: db_path
35
- )
36
- return 0
37
- end
38
- new(project_root: Dir.pwd, commit_hash: commit_hash, branch: branch,
39
- stdout: stdout, stderr: stderr, recorder: recorder).run
40
- end
41
-
42
- attr_writer :command_runner
43
-
44
- def initialize(project_root:, commit_hash:, branch:, stdout: $stdout, stderr: $stderr, command_runner: nil, time_budgets: {}, commit_validator: nil, recorder: NullRecorder.new, background_launcher: nil)
45
- @project_root = project_root
46
- @commit_hash = commit_hash
47
- @branch = branch
48
- @stdout = stdout
49
- @stderr = stderr
50
- @command_runner = command_runner
51
- @time_budgets = DEFAULT_BUDGETS.merge(time_budgets)
52
- @commit_validator = commit_validator || method(:default_commit_validator)
53
- @recorder = recorder
54
- @background_launcher = background_launcher || method(:default_background_launcher)
55
- end
56
-
57
- def run
58
- config = ProjectConfig.new(@project_root)
59
- return handle_config_errors(config) if config.validate.any?
60
- unless @commit_validator.call(@commit_hash)
61
- @stderr.puts "fun-ci: commit #{@commit_hash} not found in this repository."
62
- return 1
63
- end
64
- cancel_stale_pipelines
65
- @recorder.create_run(commit_hash: @commit_hash, branch: @branch, project_path: @project_root)
66
- stage_runner = make_stage_runner
67
- progress = ProgressReporter.new(stdout: @stdout)
68
- results = run_phase_one(stage_runner, config)
69
- progress.phase_one_result(results)
70
- unless results.values.all?
71
- @recorder.fail_run
72
- return 1
73
- end
74
- spawn_slow_suite(config)
75
- progress.slow_launched
76
- fast_runner = make_stage_runner
77
- fast_passed = fast_runner.run_stage(config, "fast")
78
- progress.fast_result(fast_passed)
79
- unless fast_passed
80
- @recorder.fail_run
81
- return 1
82
- end
83
- 0
84
- end
85
-
86
- private
87
-
88
- def handle_config_errors(config)
89
- config.validate.each { |e| @stdout.puts "fun-ci: #{e}" }
90
- unless config.folder_exists?
91
- @stdout.puts "Create .fun-ci/lint.sh, build.sh, fast.sh, and slow.sh to set up this project."
92
- @stdout.puts "Commit will proceed without CI."
93
- end
94
- 0
95
- end
96
-
97
- def run_phase_one(stage_runner, config)
98
- results = {}
99
- threads = %w[lint build].map do |stage|
100
- Thread.new { results[stage] = stage_runner.run_stage(config, stage) }
101
- end
102
- threads.each(&:join)
103
- results
104
- end
105
-
106
- def spawn_slow_suite(config)
107
- cmd = "#{config.script_path("slow")} #{@commit_hash}"
108
- job_id = @recorder.start_stage("slow")
109
- runner = @command_runner || ->(c) { Open3.capture2e(c) }
110
- budget = @time_budgets["slow"]
111
- executor = -> { Timeout.timeout(budget) { runner.call(cmd) } }
112
- @background_launcher.call(
113
- db_path: @recorder.db_path, pipeline_run_id: @recorder.pipeline_run_id,
114
- job_id: job_id, executor: executor
115
- )
116
- end
117
-
118
- def make_stage_runner
119
- StageRunner.new(
120
- commit_hash: @commit_hash, stdout: @stdout,
121
- command_runner: @command_runner,
122
- time_budgets: @time_budgets, recorder: @recorder
123
- )
124
- end
125
-
126
- def cancel_stale_pipelines
127
- return unless @recorder.db
128
- StalePipelineCanceller.new(
129
- db: @recorder.db, branch: @branch, stdout: @stdout
130
- ).cancel(new_commit_hash: @commit_hash)
131
- end
132
-
133
- def default_background_launcher(db_path:, pipeline_run_id:, job_id:, executor:)
134
- @recorder.close
135
- pid = fork do
136
- recorder = DbRecorder.for_background(db_path, pipeline_run_id)
137
- BackgroundWrapper.new(recorder: recorder, job_id: job_id, executor: executor).run
138
- recorder.close
139
- end
140
- @recorder = DbRecorder.for_background(db_path, pipeline_run_id)
141
- Process.detach(pid)
142
- PipelineRun.store_pid(@recorder.db, pipeline_run_id, pid)
143
- end
144
-
145
- def default_commit_validator(commit_hash)
146
- _, status = Open3.capture2e("git", "cat-file", "-t", commit_hash)
147
- status.success?
148
- end
149
- end
150
- end