makit 0.0.143 → 0.0.145
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/lib/makit/cli/base.rb +17 -0
- data/lib/makit/cli/generators/templates/ruby/gemspec.rb +1 -0
- data/lib/makit/cli/main.rb +9 -0
- data/lib/makit/cli/pipeline_commands.rb +311 -0
- data/lib/makit/cli/strategy_commands.rb +2 -7
- data/lib/makit/commands/result.rb +1 -1
- data/lib/makit/configuration/dotnet_project.rb +9 -0
- data/lib/makit/configuration/gitlab_helper.rb +4 -1
- data/lib/makit/configuration/project.rb +362 -84
- data/lib/makit/configuration/timeout.rb +1 -1
- data/lib/makit/configuration.rb +5 -0
- data/lib/makit/fileinfo.rb +8 -0
- data/lib/makit/git/repository.rb +207 -31
- data/lib/makit/git.rb +6 -0
- data/lib/makit/gitlab/pipeline.rb +857 -0
- data/lib/makit/gitlab/pipeline_service_impl.rb +1536 -0
- data/lib/makit/humanize.rb +81 -0
- data/lib/makit/io/filesystem.rb +111 -0
- data/lib/makit/io/filesystem_service_impl.rb +337 -0
- data/lib/makit/mp/string_mp.rb +15 -9
- data/lib/makit/podman/podman.rb +458 -0
- data/lib/makit/podman/podman_service_impl.rb +1081 -0
- data/lib/makit/process.rb +214 -0
- data/lib/makit/protoc.rb +6 -1
- data/lib/makit/services/repository_manager.rb +268 -132
- data/lib/makit/symbols.rb +5 -0
- data/lib/makit/v1/configuration/project_service_impl.rb +371 -0
- data/lib/makit/v1/git/git_repository_service_impl.rb +295 -0
- data/lib/makit/v1/makit.v1_pb.rb +1 -1
- data/lib/makit/v1/makit.v1_services_pb.rb +1 -1
- data/lib/makit/v1/services/repository_manager_service_impl.rb +572 -0
- data/lib/makit/version.rb +1 -1
- data/lib/makit.rb +68 -0
- metadata +61 -36
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 17d44fa44cc50748851e438335d85ae0f836a21366c46b57e7341a95e8acafc6
|
|
4
|
+
data.tar.gz: 1e9f25ea683dbfaa061a05679dfe99ae8f074e2a33f17f1d5d2ce17655eaafa0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aa24a58a06074747e3fe8ecff4afbd53549c05586da155bdb36aea35c3adc2ec881aa6b5bb8ae7fea7df073a06f64c0430e508d01becf7f43e38c573dd58e668
|
|
7
|
+
data.tar.gz: 9b0d0d5d1120f9817054d48626c228c0de1ad9ca0bba56ee231cd1cd0972f3f9facee1fbf7f16e3013529bb2e2a77f3b9d902f248de9866c1ad052a4cd2602fe
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "clamp"
|
|
4
|
+
|
|
5
|
+
module Makit
|
|
6
|
+
module Cli
|
|
7
|
+
# Base class for CLI commands
|
|
8
|
+
class Base < Clamp::Command
|
|
9
|
+
# Common functionality for CLI commands can be added here
|
|
10
|
+
|
|
11
|
+
# Helper method to define command descriptions
|
|
12
|
+
def self.desc(command_name, description)
|
|
13
|
+
self.description = "#{command_name} - #{description}"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/makit/cli/main.rb
CHANGED
|
@@ -6,6 +6,7 @@ require_relative "project_commands"
|
|
|
6
6
|
require_relative "build_commands"
|
|
7
7
|
require_relative "utility_commands"
|
|
8
8
|
require_relative "strategy_commands"
|
|
9
|
+
require_relative "pipeline_commands"
|
|
9
10
|
require_relative "../rake/cli"
|
|
10
11
|
|
|
11
12
|
module Makit
|
|
@@ -20,6 +21,7 @@ module Makit
|
|
|
20
21
|
repository - Manage git repositories (add, clone, pull, list, remove, import)
|
|
21
22
|
project - Manage project creation and setup (new, init, setup, work)
|
|
22
23
|
build - Build operations and cleanup (make, clean)
|
|
24
|
+
pipeline - GitLab CI pipeline operations (run)
|
|
23
25
|
utility - System utilities and maintenance (nuget-cache, system-info)
|
|
24
26
|
strategy - Manage execution strategies (show, test)
|
|
25
27
|
trace - Manage trace functionality (show, enable, disable, test)
|
|
@@ -45,6 +47,12 @@ module Makit
|
|
|
45
47
|
makit build make https://github.com/user/repo # Build specific repository
|
|
46
48
|
makit build make --target release # Build current project
|
|
47
49
|
makit build clean --deep
|
|
50
|
+
#{" "}
|
|
51
|
+
# Pipeline operations
|
|
52
|
+
makit pipeline run # Run .gitlab-ci.yml in current directory
|
|
53
|
+
makit pipeline run --file custom-ci.yml # Run custom pipeline file
|
|
54
|
+
makit pipeline run --dry-run # Simulate execution
|
|
55
|
+
makit pipeline run --variables KEY=value # Pass variables to pipeline
|
|
48
56
|
#{" "}
|
|
49
57
|
# Utilities
|
|
50
58
|
makit utility nuget-cache --clear
|
|
@@ -59,6 +67,7 @@ module Makit
|
|
|
59
67
|
subcommand "repository", "Manage git repositories", RepositoryCommand
|
|
60
68
|
subcommand "project", "Manage project creation and setup", ProjectCommand
|
|
61
69
|
subcommand "build", "Build operations and cleanup", BuildCommand
|
|
70
|
+
subcommand "pipeline", "GitLab CI pipeline operations", PipelineCommand
|
|
62
71
|
subcommand "utility", "System utilities and maintenance", UtilityCommand
|
|
63
72
|
subcommand "strategy", "Manage execution strategies", StrategyCommands
|
|
64
73
|
subcommand "trace", "Manage trace functionality", TraceCommands
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "clamp"
|
|
4
|
+
require "colorize"
|
|
5
|
+
require_relative "../gitlab/pipeline"
|
|
6
|
+
require_relative "../humanize"
|
|
7
|
+
|
|
8
|
+
module Makit
|
|
9
|
+
module Cli
|
|
10
|
+
# Command to run GitLab CI pipelines
|
|
11
|
+
class PipelineRunCommand < Clamp::Command
|
|
12
|
+
self.description = <<~DESC
|
|
13
|
+
Execute a GitLab CI pipeline using Podman containers.
|
|
14
|
+
|
|
15
|
+
By default, looks for .gitlab-ci.yml in the current directory.
|
|
16
|
+
Each job in the pipeline will be executed in a separate Podman container.
|
|
17
|
+
DESC
|
|
18
|
+
|
|
19
|
+
option ["-f", "--file"], "FILE", "Pipeline file to execute", default: ".gitlab-ci.yml"
|
|
20
|
+
option ["-v", "--variables"], "VARS", "Variables to pass to the pipeline (format: KEY=value,KEY2=value2)"
|
|
21
|
+
option ["-w", "--working-directory"], "DIR", "Working directory for execution", default: Dir.pwd
|
|
22
|
+
option ["-p", "--podman-executable"], "EXECUTABLE", "Podman executable path", default: "podman"
|
|
23
|
+
option ["-d", "--dry-run"], :flag, "Simulate execution without actually running"
|
|
24
|
+
option ["--verbose"], :flag, "Show detailed output"
|
|
25
|
+
option ["--no-color"], :flag, "Disable colored output"
|
|
26
|
+
|
|
27
|
+
def execute
|
|
28
|
+
# Disable color if requested
|
|
29
|
+
String.disable_colorization = true if no_color?
|
|
30
|
+
|
|
31
|
+
# Check if pipeline file exists
|
|
32
|
+
unless File.exist?(file)
|
|
33
|
+
error "Pipeline file '#{file}' not found"
|
|
34
|
+
exit(1)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Parse variables
|
|
38
|
+
variables = parse_variables
|
|
39
|
+
|
|
40
|
+
# Load and parse pipeline
|
|
41
|
+
puts "Loading pipeline from #{file}..." if verbose?
|
|
42
|
+
begin
|
|
43
|
+
pipeline_content = File.read(file)
|
|
44
|
+
pipeline = Makit::Gitlab::Pipeline.parse_yaml(pipeline_content)
|
|
45
|
+
rescue StandardError => e
|
|
46
|
+
error "Failed to parse pipeline file: #{e.message}"
|
|
47
|
+
exit(1)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Validate pipeline
|
|
51
|
+
validation_result = pipeline.validate
|
|
52
|
+
unless validation_result[:is_valid]
|
|
53
|
+
error "Pipeline validation failed:"
|
|
54
|
+
validation_result[:errors].each { |err| error " - #{err}" }
|
|
55
|
+
exit(1)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Show warnings if any
|
|
59
|
+
if validation_result[:warnings].any?
|
|
60
|
+
warning "Pipeline warnings:"
|
|
61
|
+
validation_result[:warnings].each { |warn| warning " - #{warn}" }
|
|
62
|
+
puts
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Show pipeline info
|
|
66
|
+
show_pipeline_info(pipeline)
|
|
67
|
+
|
|
68
|
+
# Execute pipeline
|
|
69
|
+
puts "\nExecuting pipeline..." unless dry_run?
|
|
70
|
+
puts "Dry run mode - no actual execution will occur" if dry_run?
|
|
71
|
+
|
|
72
|
+
start_time = Time.now
|
|
73
|
+
result = pipeline.execute_pipeline(
|
|
74
|
+
variables: variables,
|
|
75
|
+
working_directory: working_directory,
|
|
76
|
+
podman_executable: podman_executable,
|
|
77
|
+
dry_run: dry_run?
|
|
78
|
+
)
|
|
79
|
+
end_time = Time.now
|
|
80
|
+
|
|
81
|
+
# Display results
|
|
82
|
+
display_execution_result(result, start_time, end_time)
|
|
83
|
+
|
|
84
|
+
# Exit with appropriate code
|
|
85
|
+
success = if result.is_a?(Hash)
|
|
86
|
+
result[:success]
|
|
87
|
+
else
|
|
88
|
+
result.success
|
|
89
|
+
end
|
|
90
|
+
exit(success ? 0 : 1)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
private
|
|
94
|
+
|
|
95
|
+
def parse_variables
|
|
96
|
+
return {} unless variables
|
|
97
|
+
|
|
98
|
+
vars = {}
|
|
99
|
+
variables.split(",").each do |var|
|
|
100
|
+
key, value = var.split("=", 2)
|
|
101
|
+
if key && value
|
|
102
|
+
vars[key.strip] = value.strip
|
|
103
|
+
else
|
|
104
|
+
error "Invalid variable format: #{var}. Use KEY=value format."
|
|
105
|
+
exit(1)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
vars
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def show_pipeline_info(pipeline)
|
|
112
|
+
puts "Pipeline Information:"
|
|
113
|
+
puts " Image: #{pipeline.pipeline_data.image}" unless pipeline.pipeline_data.image.empty?
|
|
114
|
+
puts " Stages: #{pipeline.pipeline_data.stages.map(&:name).join(', ')}"
|
|
115
|
+
puts " Jobs: #{pipeline.pipeline_data.jobs.keys.join(', ')}"
|
|
116
|
+
puts " Variables: #{pipeline.pipeline_data.variables.keys.join(', ')}" unless pipeline.pipeline_data.variables.empty?
|
|
117
|
+
puts
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def display_execution_result(result, start_time, end_time)
|
|
121
|
+
puts "\n" + "="*60
|
|
122
|
+
puts "PIPELINE EXECUTION RESULT".center(60)
|
|
123
|
+
puts "="*60
|
|
124
|
+
|
|
125
|
+
# Extract result data based on mode
|
|
126
|
+
if result.is_a?(Hash)
|
|
127
|
+
# Fallback mode
|
|
128
|
+
execution_result = result[:result]
|
|
129
|
+
success = result[:success]
|
|
130
|
+
errors = result[:errors] || []
|
|
131
|
+
warnings = result[:warnings] || []
|
|
132
|
+
else
|
|
133
|
+
# gRPC mode
|
|
134
|
+
execution_result = result.result
|
|
135
|
+
success = result.success
|
|
136
|
+
errors = result.errors || []
|
|
137
|
+
warnings = result.warnings || []
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Overall status
|
|
141
|
+
status_color = success ? :green : :red
|
|
142
|
+
status_icon = success ? "✓" : "✗"
|
|
143
|
+
puts "#{status_icon} Status: #{success ? 'SUCCESS' : 'FAILED'}".colorize(status_color)
|
|
144
|
+
|
|
145
|
+
# Access execution result fields safely
|
|
146
|
+
execution_id = if execution_result.respond_to?(:execution_id)
|
|
147
|
+
execution_result.execution_id
|
|
148
|
+
else
|
|
149
|
+
execution_result[:execution_id]
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
started_at = if execution_result.respond_to?(:started_at)
|
|
153
|
+
execution_result.started_at
|
|
154
|
+
else
|
|
155
|
+
execution_result[:started_at]
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
finished_at = if execution_result.respond_to?(:finished_at)
|
|
159
|
+
execution_result.finished_at
|
|
160
|
+
else
|
|
161
|
+
execution_result[:finished_at]
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
puts " Execution ID: #{execution_id}"
|
|
165
|
+
puts " Started: #{started_at}"
|
|
166
|
+
puts " Finished: #{finished_at}" if finished_at
|
|
167
|
+
puts " Duration: #{Makit::Humanize.get_humanized_duration(end_time - start_time)}"
|
|
168
|
+
|
|
169
|
+
# Podman info
|
|
170
|
+
podman_version = if execution_result.respond_to?(:podman_version)
|
|
171
|
+
execution_result.podman_version
|
|
172
|
+
else
|
|
173
|
+
execution_result[:podman_version]
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
execution_host = if execution_result.respond_to?(:execution_host)
|
|
177
|
+
execution_result.execution_host
|
|
178
|
+
else
|
|
179
|
+
execution_result[:execution_host]
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
puts " Podman Version: #{podman_version}" if podman_version
|
|
183
|
+
puts " Host: #{execution_host}" if execution_host
|
|
184
|
+
|
|
185
|
+
# Job results
|
|
186
|
+
job_results = if execution_result.respond_to?(:job_results)
|
|
187
|
+
execution_result.job_results
|
|
188
|
+
else
|
|
189
|
+
execution_result[:job_results]
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
if job_results && job_results.any?
|
|
193
|
+
puts "\nJob Results:"
|
|
194
|
+
job_results.each do |job_result|
|
|
195
|
+
display_job_result(job_result)
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Errors
|
|
200
|
+
if errors.any?
|
|
201
|
+
puts "\nErrors:".colorize(:red)
|
|
202
|
+
errors.each { |err| puts " ✗ #{err}".colorize(:red) }
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Warnings
|
|
206
|
+
if warnings.any?
|
|
207
|
+
puts "\nWarnings:".colorize(:yellow)
|
|
208
|
+
warnings.each { |warn| puts " ⚠ #{warn}".colorize(:yellow) }
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
# Logs
|
|
212
|
+
logs = if execution_result.respond_to?(:logs)
|
|
213
|
+
execution_result.logs
|
|
214
|
+
else
|
|
215
|
+
execution_result[:logs]
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
if logs && logs.any? && verbose?
|
|
219
|
+
puts "\nExecution Logs:"
|
|
220
|
+
logs.each { |log| puts " #{log}" }
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
puts "="*60
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def display_job_result(job_result)
|
|
227
|
+
# Extract job data based on mode
|
|
228
|
+
if job_result.is_a?(Hash)
|
|
229
|
+
job_name = job_result[:job_name]
|
|
230
|
+
status = job_result[:status]
|
|
231
|
+
exit_code = job_result[:exit_code]
|
|
232
|
+
started_at = job_result[:started_at]
|
|
233
|
+
finished_at = job_result[:finished_at]
|
|
234
|
+
logs = job_result[:logs] || []
|
|
235
|
+
errors = job_result[:errors] || []
|
|
236
|
+
stdout = job_result[:stdout] || ""
|
|
237
|
+
stderr = job_result[:stderr] || ""
|
|
238
|
+
else
|
|
239
|
+
job_name = job_result.job_name
|
|
240
|
+
status = job_result.status
|
|
241
|
+
exit_code = job_result.exit_code
|
|
242
|
+
started_at = job_result.started_at
|
|
243
|
+
finished_at = job_result.finished_at
|
|
244
|
+
logs = job_result.logs || []
|
|
245
|
+
errors = job_result.errors || []
|
|
246
|
+
stdout = job_result.respond_to?(:stdout) ? job_result.stdout : ""
|
|
247
|
+
stderr = job_result.respond_to?(:stderr) ? job_result.stderr : ""
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Job status
|
|
251
|
+
status_color = (status == :success || status.to_s.include?('SUCCESS')) ? :green : :red
|
|
252
|
+
status_icon = (status == :success || status.to_s.include?('SUCCESS')) ? "✓" : "✗"
|
|
253
|
+
|
|
254
|
+
puts " #{status_icon} #{job_name}: #{status.to_s.upcase}".colorize(status_color)
|
|
255
|
+
puts " Exit Code: #{exit_code}" if exit_code
|
|
256
|
+
puts " Started: #{started_at}"
|
|
257
|
+
puts " Finished: #{finished_at}" if finished_at
|
|
258
|
+
|
|
259
|
+
# Job errors
|
|
260
|
+
if errors.any?
|
|
261
|
+
puts " Errors:".colorize(:red)
|
|
262
|
+
errors.each { |err| puts " ✗ #{err}".colorize(:red) }
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# Job logs (if verbose)
|
|
266
|
+
if logs.any? && verbose?
|
|
267
|
+
puts " Logs:"
|
|
268
|
+
logs.each { |log| puts " #{log}" }
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
# Job stdout (if verbose and not empty)
|
|
272
|
+
if stdout && !stdout.empty? && verbose?
|
|
273
|
+
puts " Stdout:".colorize(:green)
|
|
274
|
+
stdout.split("\n").each { |line| puts " #{line}".colorize(:green) }
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
# Job stderr (if verbose and not empty)
|
|
278
|
+
if stderr && !stderr.empty? && verbose?
|
|
279
|
+
puts " Stderr:".colorize(:red)
|
|
280
|
+
stderr.split("\n").each { |line| puts " #{line}".colorize(:red) }
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def error(message)
|
|
285
|
+
puts "Error: #{message}".colorize(:red)
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def warning(message)
|
|
289
|
+
puts "Warning: #{message}".colorize(:yellow)
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
# Pipeline command group for GitLab CI pipeline operations
|
|
294
|
+
class PipelineCommand < Clamp::Command
|
|
295
|
+
self.description = <<~DESC
|
|
296
|
+
GitLab CI Pipeline operations.
|
|
297
|
+
|
|
298
|
+
Available commands:
|
|
299
|
+
run - Execute a GitLab CI pipeline using Podman
|
|
300
|
+
|
|
301
|
+
Examples:
|
|
302
|
+
makit pipeline run # Run .gitlab-ci.yml in current directory
|
|
303
|
+
makit pipeline run --file custom-ci.yml # Run custom pipeline file
|
|
304
|
+
makit pipeline run --dry-run # Simulate execution without running
|
|
305
|
+
makit pipeline run --variables KEY=value # Pass variables to pipeline
|
|
306
|
+
DESC
|
|
307
|
+
|
|
308
|
+
subcommand "run", "Execute a GitLab CI pipeline", PipelineRunCommand
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
end
|
|
@@ -102,10 +102,7 @@ module Makit
|
|
|
102
102
|
end
|
|
103
103
|
|
|
104
104
|
# Add trace commands to the main CLI
|
|
105
|
-
|
|
106
|
-
module Cli
|
|
107
|
-
# Commands for managing trace functionality
|
|
108
|
-
class TraceCommands < Base
|
|
105
|
+
class TraceCommands < Cli::Base
|
|
109
106
|
desc "trace", "Show current trace status and configuration"
|
|
110
107
|
option ["--verbose", "-v"], :flag, "Show detailed trace information"
|
|
111
108
|
|
|
@@ -154,7 +151,7 @@ module Makit
|
|
|
154
151
|
end
|
|
155
152
|
|
|
156
153
|
# Commands for managing timeout configuration
|
|
157
|
-
class TimeoutCommands < Base
|
|
154
|
+
class TimeoutCommands < Cli::Base
|
|
158
155
|
desc "timeout", "Show current timeout configuration"
|
|
159
156
|
option ["--verbose", "-v"], :flag, "Show detailed timeout information"
|
|
160
157
|
|
|
@@ -207,6 +204,4 @@ module Makit
|
|
|
207
204
|
end
|
|
208
205
|
end
|
|
209
206
|
end
|
|
210
|
-
end
|
|
211
|
-
end
|
|
212
207
|
end
|
|
@@ -33,6 +33,15 @@ module Makit
|
|
|
33
33
|
commands << "dotnet publish #{get_csproj_path} --configuration Debug --output artifacts/Publish"
|
|
34
34
|
commands
|
|
35
35
|
end
|
|
36
|
+
|
|
37
|
+
def to_json
|
|
38
|
+
{
|
|
39
|
+
name: @name,
|
|
40
|
+
output_dir: @output_dir,
|
|
41
|
+
frameworks: @frameworks,
|
|
42
|
+
template: @template
|
|
43
|
+
}.to_json
|
|
44
|
+
end
|
|
36
45
|
|
|
37
46
|
end
|
|
38
47
|
end
|
|
@@ -15,7 +15,10 @@ module Makit
|
|
|
15
15
|
content = File.read(path)
|
|
16
16
|
data = YAML.safe_load(content, symbolize_names: true, permitted_classes: [Symbol])
|
|
17
17
|
|
|
18
|
-
project = Project.new(
|
|
18
|
+
project = Project.new(
|
|
19
|
+
name: data[:variables]&.dig(:project_name) || data[:name] || "Unknown",
|
|
20
|
+
version: data[:variables]&.dig(:project_version) || data[:version] || "1.0.0"
|
|
21
|
+
)
|
|
19
22
|
|
|
20
23
|
# Extract steps from GitLab CI jobs
|
|
21
24
|
data.each do |key, value|
|