makit 0.0.164 → 0.0.166

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 (178) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +41 -41
  3. data/exe/makit +5 -5
  4. data/lib/makit/apache.rb +28 -28
  5. data/lib/makit/auto.rb +48 -48
  6. data/lib/makit/azure/blob_storage.rb +257 -257
  7. data/lib/makit/azure/cli.rb +284 -284
  8. data/lib/makit/azure-pipelines.rb +139 -0
  9. data/lib/makit/cli/base.rb +17 -17
  10. data/lib/makit/cli/build_commands.rb +500 -500
  11. data/lib/makit/cli/generators/base_generator.rb +74 -74
  12. data/lib/makit/cli/generators/dotnet_generator.rb +50 -50
  13. data/lib/makit/cli/generators/generator_factory.rb +49 -49
  14. data/lib/makit/cli/generators/node_generator.rb +50 -50
  15. data/lib/makit/cli/generators/ruby_generator.rb +77 -77
  16. data/lib/makit/cli/generators/rust_generator.rb +50 -50
  17. data/lib/makit/cli/generators/templates/dotnet_templates.rb +167 -167
  18. data/lib/makit/cli/generators/templates/node_templates.rb +161 -161
  19. data/lib/makit/cli/generators/templates/ruby/gemfile.rb +26 -26
  20. data/lib/makit/cli/generators/templates/ruby/gemspec.rb +41 -41
  21. data/lib/makit/cli/generators/templates/ruby/main_lib.rb +33 -33
  22. data/lib/makit/cli/generators/templates/ruby/rakefile.rb +35 -35
  23. data/lib/makit/cli/generators/templates/ruby/readme.rb +63 -63
  24. data/lib/makit/cli/generators/templates/ruby/test.rb +39 -39
  25. data/lib/makit/cli/generators/templates/ruby/test_helper.rb +29 -29
  26. data/lib/makit/cli/generators/templates/ruby/version.rb +29 -29
  27. data/lib/makit/cli/generators/templates/rust_templates.rb +128 -128
  28. data/lib/makit/cli/main.rb +78 -78
  29. data/lib/makit/cli/pipeline_commands.rb +311 -311
  30. data/lib/makit/cli/project_commands.rb +868 -868
  31. data/lib/makit/cli/repository_commands.rb +661 -661
  32. data/lib/makit/cli/strategy_commands.rb +207 -207
  33. data/lib/makit/cli/utility_commands.rb +521 -521
  34. data/lib/makit/commands/factory.rb +359 -359
  35. data/lib/makit/commands/middleware/base.rb +73 -73
  36. data/lib/makit/commands/middleware/cache.rb +248 -248
  37. data/lib/makit/commands/middleware/command_logger.rb +312 -312
  38. data/lib/makit/commands/middleware/validator.rb +269 -269
  39. data/lib/makit/commands/request.rb +316 -316
  40. data/lib/makit/commands/result.rb +323 -323
  41. data/lib/makit/commands/runner.rb +386 -386
  42. data/lib/makit/commands/strategies/base.rb +171 -171
  43. data/lib/makit/commands/strategies/child_process.rb +162 -162
  44. data/lib/makit/commands/strategies/factory.rb +136 -136
  45. data/lib/makit/commands/strategies/synchronous.rb +139 -139
  46. data/lib/makit/commands.rb +50 -50
  47. data/lib/makit/configuration/dotnet_project.rb +48 -48
  48. data/lib/makit/configuration/gitlab_helper.rb +61 -61
  49. data/lib/makit/configuration/project.rb +292 -292
  50. data/lib/makit/configuration/rakefile_helper.rb +43 -43
  51. data/lib/makit/configuration/step.rb +34 -34
  52. data/lib/makit/configuration/timeout.rb +74 -74
  53. data/lib/makit/configuration.rb +21 -21
  54. data/lib/makit/content/default_gitignore.rb +7 -7
  55. data/lib/makit/content/default_gitignore.txt +225 -225
  56. data/lib/makit/content/default_rakefile.rb +13 -13
  57. data/lib/makit/content/gem_rakefile.rb +16 -16
  58. data/lib/makit/context.rb +1 -1
  59. data/lib/makit/data.rb +49 -49
  60. data/lib/makit/directories.rb +170 -170
  61. data/lib/makit/directory.rb +262 -262
  62. data/lib/makit/docs/files.rb +89 -89
  63. data/lib/makit/docs/rake.rb +102 -102
  64. data/lib/makit/dotnet/cli.rb +224 -224
  65. data/lib/makit/dotnet/project.rb +217 -217
  66. data/lib/makit/dotnet/solution.rb +38 -38
  67. data/lib/makit/dotnet/solution_classlib.rb +239 -239
  68. data/lib/makit/dotnet/solution_console.rb +264 -264
  69. data/lib/makit/dotnet/solution_maui.rb +354 -354
  70. data/lib/makit/dotnet/solution_wasm.rb +275 -275
  71. data/lib/makit/dotnet/solution_wpf.rb +304 -304
  72. data/lib/makit/dotnet.rb +110 -110
  73. data/lib/makit/email.rb +90 -90
  74. data/lib/makit/environment.rb +142 -142
  75. data/lib/makit/examples/runner.rb +370 -370
  76. data/lib/makit/exceptions.rb +45 -45
  77. data/lib/makit/fileinfo.rb +32 -32
  78. data/lib/makit/files.rb +43 -43
  79. data/lib/makit/gems.rb +49 -49
  80. data/lib/makit/git/cli.rb +103 -103
  81. data/lib/makit/git/repository.rb +100 -100
  82. data/lib/makit/git.rb +104 -104
  83. data/lib/makit/gitlab/pipeline.rb +857 -857
  84. data/lib/makit/gitlab/pipeline_service_impl.rb +1535 -1535
  85. data/lib/makit/gitlab_runner.rb +59 -59
  86. data/lib/makit/humanize.rb +218 -218
  87. data/lib/makit/indexer.rb +47 -47
  88. data/lib/makit/io/filesystem.rb +111 -111
  89. data/lib/makit/io/filesystem_service_impl.rb +337 -337
  90. data/lib/makit/lint.rb +212 -212
  91. data/lib/makit/logging/configuration.rb +309 -309
  92. data/lib/makit/logging/format_registry.rb +84 -84
  93. data/lib/makit/logging/formatters/base.rb +39 -39
  94. data/lib/makit/logging/formatters/console_formatter.rb +140 -140
  95. data/lib/makit/logging/formatters/json_formatter.rb +65 -65
  96. data/lib/makit/logging/formatters/plain_text_formatter.rb +71 -71
  97. data/lib/makit/logging/formatters/text_formatter.rb +64 -64
  98. data/lib/makit/logging/log_request.rb +119 -119
  99. data/lib/makit/logging/logger.rb +199 -199
  100. data/lib/makit/logging/sinks/base.rb +91 -91
  101. data/lib/makit/logging/sinks/console.rb +72 -72
  102. data/lib/makit/logging/sinks/file_sink.rb +92 -92
  103. data/lib/makit/logging/sinks/structured.rb +123 -123
  104. data/lib/makit/logging/sinks/unified_file_sink.rb +296 -296
  105. data/lib/makit/logging.rb +578 -578
  106. data/lib/makit/markdown.rb +75 -75
  107. data/lib/makit/mp/basic_object_mp.rb +17 -17
  108. data/lib/makit/mp/command_mp.rb +13 -13
  109. data/lib/makit/mp/command_request.mp.rb +17 -17
  110. data/lib/makit/mp/project_mp.rb +199 -199
  111. data/lib/makit/mp/string_mp.rb +205 -205
  112. data/lib/makit/nuget.rb +454 -454
  113. data/lib/makit/podman/podman.rb +458 -458
  114. data/lib/makit/podman/podman_service_impl.rb +1081 -1081
  115. data/lib/makit/port.rb +32 -32
  116. data/lib/makit/process.rb +377 -377
  117. data/lib/makit/protoc.rb +112 -112
  118. data/lib/makit/rake/cli.rb +196 -196
  119. data/lib/makit/rake/trace_controller.rb +174 -174
  120. data/lib/makit/rake.rb +81 -81
  121. data/lib/makit/ruby/cli.rb +185 -185
  122. data/lib/makit/ruby.rb +25 -25
  123. data/lib/makit/rubygems.rb +137 -137
  124. data/lib/makit/secrets/azure_key_vault.rb +322 -322
  125. data/lib/makit/secrets/azure_secrets.rb +221 -183
  126. data/lib/makit/secrets/local_secrets.rb +72 -72
  127. data/lib/makit/secrets/secrets_manager.rb +105 -105
  128. data/lib/makit/secrets.rb +96 -16
  129. data/lib/makit/serializer.rb +130 -130
  130. data/lib/makit/services/builder.rb +186 -186
  131. data/lib/makit/services/error_handler.rb +226 -226
  132. data/lib/makit/services/repository_manager.rb +367 -367
  133. data/lib/makit/services/validator.rb +112 -112
  134. data/lib/makit/setup/classlib.rb +101 -101
  135. data/lib/makit/setup/gem.rb +268 -268
  136. data/lib/makit/setup/pages.rb +11 -11
  137. data/lib/makit/setup/razorclasslib.rb +101 -101
  138. data/lib/makit/setup/runner.rb +54 -54
  139. data/lib/makit/setup.rb +5 -5
  140. data/lib/makit/show.rb +110 -110
  141. data/lib/makit/storage.rb +126 -126
  142. data/lib/makit/symbols.rb +175 -175
  143. data/lib/makit/task_info.rb +130 -130
  144. data/lib/makit/tasks/at_exit.rb +15 -15
  145. data/lib/makit/tasks/build.rb +22 -22
  146. data/lib/makit/tasks/bump.rb +7 -7
  147. data/lib/makit/tasks/clean.rb +13 -13
  148. data/lib/makit/tasks/configure.rb +10 -10
  149. data/lib/makit/tasks/format.rb +10 -10
  150. data/lib/makit/tasks/hook_manager.rb +443 -443
  151. data/lib/makit/tasks/info.rb +368 -368
  152. data/lib/makit/tasks/init.rb +49 -49
  153. data/lib/makit/tasks/integrate.rb +60 -60
  154. data/lib/makit/tasks/pull_incoming.rb +13 -13
  155. data/lib/makit/tasks/secrets.rb +7 -7
  156. data/lib/makit/tasks/setup.rb +16 -16
  157. data/lib/makit/tasks/sync.rb +14 -14
  158. data/lib/makit/tasks/tag.rb +27 -27
  159. data/lib/makit/tasks/task_monkey_patch.rb +81 -81
  160. data/lib/makit/tasks/test.rb +22 -22
  161. data/lib/makit/tasks/update.rb +21 -21
  162. data/lib/makit/tasks/version.rb +6 -6
  163. data/lib/makit/tasks.rb +24 -24
  164. data/lib/makit/test_cache.rb +239 -239
  165. data/lib/makit/tree.rb +37 -37
  166. data/lib/makit/v1/configuration/project_service_impl.rb +370 -370
  167. data/lib/makit/v1/git/git_repository_service_impl.rb +295 -295
  168. data/lib/makit/v1/makit.v1_pb.rb +35 -35
  169. data/lib/makit/v1/makit.v1_services_pb.rb +27 -27
  170. data/lib/makit/v1/services/repository_manager_service_impl.rb +572 -572
  171. data/lib/makit/version.rb +661 -661
  172. data/lib/makit/version_util.rb +21 -21
  173. data/lib/makit/wix.rb +95 -95
  174. data/lib/makit/yaml.rb +29 -29
  175. data/lib/makit/zip.rb +17 -17
  176. data/lib/makit copy.rb +44 -44
  177. data/lib/makit.rb +120 -119
  178. metadata +3 -2
@@ -1,371 +1,371 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../../../generated/makit/v1/configuration/project_service_services_pb"
4
- require_relative "../../configuration/gitlab_helper"
5
- require_relative "../../configuration/rakefile_helper"
6
- require_relative "../../configuration/step"
7
-
8
- module Makit
9
- module V1
10
- module Configuration
11
- # gRPC service implementation for ProjectService
12
- # Implements all the RPC methods defined in the protobuf service definition
13
- class ProjectServiceImpl < ProjectService::Service
14
- # Load a project from a JSON file
15
- def load_from_file(request, _unused_call)
16
- raise ArgumentError, "File does not exist: #{request.path}" unless File.exist?(request.path)
17
-
18
- content = File.read(request.path)
19
- data = JSON.parse(content, symbolize_names: true)
20
-
21
- project = convert_from_json_data(data)
22
- project
23
- rescue ArgumentError => e
24
- raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
25
- rescue StandardError => e
26
- raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
27
- end
28
-
29
- # Load a project from JSON string
30
- def load_from_json(request, _unused_call)
31
- raise ArgumentError, "JSON string cannot be empty" if request.json_string.nil? || request.json_string.strip.empty?
32
-
33
- data = JSON.parse(request.json_string, symbolize_names: true)
34
- project = convert_from_json_data(data)
35
- project
36
- rescue ArgumentError => e
37
- raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
38
- rescue StandardError => e
39
- raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
40
- end
41
-
42
- # Save a project to a specific path as pretty JSON
43
- def save_to_file(request, _unused_call)
44
- validate_project_model(request.project)
45
- raise ArgumentError, "Path cannot be empty" if request.path.nil? || request.path.strip.empty?
46
-
47
- File.write(request.path, convert_to_json_pretty(request.project))
48
- Google::Protobuf::Empty.new
49
- rescue ArgumentError => e
50
- raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
51
- rescue StandardError => e
52
- raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
53
- end
54
-
55
- # Save a project to the default .makit.json file
56
- def save_to_default(request, _unused_call)
57
- validate_project_model(request.project)
58
- File.write(".makit.json", convert_to_json_pretty(request.project))
59
- Google::Protobuf::Empty.new
60
- rescue ArgumentError => e
61
- raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
62
- rescue StandardError => e
63
- raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
64
- end
65
-
66
- # Load the default project from .makit.json or create a new one
67
- def load_default(request, _unused_call)
68
- if File.exist?(".makit.json")
69
- load_from_file(LoadFromFileRequest.new(path: ".makit.json"), nil)
70
- else
71
- project = Project.new(
72
- name: "",
73
- version: "0.0.0",
74
- project_type: "",
75
- authors: "authors",
76
- description: "description",
77
- license_expression: "MIT",
78
- steps: []
79
- )
80
- #Makit::Logging.default_logger.warn("Project not configured")
81
- project
82
- end
83
- rescue StandardError => e
84
- raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
85
- end
86
-
87
- # Generate GitLab CI YAML from project
88
- def generate_gitlab_ci(request, _unused_call)
89
- validate_project_model(request.project)
90
- raise ArgumentError, "Path cannot be empty" if request.path.nil? || request.path.strip.empty?
91
-
92
- # Convert protobuf model to Ruby model for GitLab helper
93
- ruby_model = convert_to_ruby_model(request.project)
94
- Makit::Configuration::GitLabHelper.to_yaml(ruby_model, request.path)
95
- Google::Protobuf::Empty.new
96
- rescue ArgumentError => e
97
- raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
98
- rescue StandardError => e
99
- raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
100
- end
101
-
102
- # Generate Rakefile from project
103
- def generate_rakefile(request, _unused_call)
104
- validate_project_model(request.project)
105
-
106
- # Convert protobuf model to Ruby model for Rakefile helper
107
- ruby_model = convert_to_ruby_model(request.project)
108
- content = Makit::Configuration::RakefileHelper.generate(ruby_model)
109
- GenerateRakefileResponse.new(content: content)
110
- rescue ArgumentError => e
111
- raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
112
- rescue StandardError => e
113
- raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
114
- end
115
-
116
- # Write Rakefile to file
117
- def write_rakefile(request, _unused_call)
118
- validate_project_model(request.project)
119
- raise ArgumentError, "Path cannot be empty" if request.path.nil? || request.path.strip.empty?
120
-
121
- # Convert protobuf model to Ruby model for Rakefile helper
122
- ruby_model = convert_to_ruby_model(request.project)
123
- Makit::Configuration::RakefileHelper.write(ruby_model, request.path)
124
- Google::Protobuf::Empty.new
125
- rescue ArgumentError => e
126
- raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
127
- rescue StandardError => e
128
- raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
129
- end
130
-
131
- # Validate project configuration
132
- def validate_project(request, _unused_call)
133
- errors = validate_project_model_errors(request.project)
134
- ValidateProjectResponse.new(errors: errors)
135
- rescue StandardError => e
136
- raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
137
- end
138
-
139
- # Merge two project configurations
140
- def merge_projects(request, _unused_call)
141
- merged = Project.new(
142
- git_remote_url: request.override_project.git_remote_url || request.base_project.git_remote_url,
143
- name: request.override_project.name || request.base_project.name,
144
- version: request.override_project.version || request.base_project.version,
145
- project_type: request.override_project.project_type || request.base_project.project_type,
146
- authors: request.override_project.authors || request.base_project.authors,
147
- description: request.override_project.description || request.base_project.description,
148
- license_expression: request.override_project.license_expression || request.base_project.license_expression,
149
- dotnet_projects: request.override_project.dotnet_projects.any? ? request.override_project.dotnet_projects.to_a : request.base_project.dotnet_projects.to_a,
150
- steps: request.override_project.steps.any? ? request.override_project.steps.to_a : request.base_project.steps.to_a
151
- )
152
- merged
153
- rescue StandardError => e
154
- raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
155
- end
156
-
157
- # Create a new project with default values
158
- def create_project(request, _unused_call)
159
- raise ArgumentError, "Project name cannot be empty" if request.name.nil? || request.name.strip.empty?
160
-
161
- project = Project.new(
162
- name: request.name,
163
- version: request.version || "0.0.0",
164
- project_type: request.project_type || "gem",
165
- authors: "authors",
166
- description: "description",
167
- license_expression: "MIT",
168
- steps: []
169
- )
170
- project
171
- rescue ArgumentError => e
172
- raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
173
- rescue StandardError => e
174
- raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
175
- end
176
-
177
- # Update project with new values
178
- def update_project(request, _unused_call)
179
- updated_project = Project.new(
180
- git_remote_url: request.project.git_remote_url,
181
- name: request.project.name,
182
- version: request.project.version,
183
- project_type: request.project.project_type,
184
- authors: request.project.authors,
185
- description: request.project.description,
186
- license_expression: request.project.license_expression,
187
- dotnet_projects: request.project.dotnet_projects.to_a,
188
- steps: request.project.steps.to_a
189
- )
190
-
191
- # Apply updates
192
- request.updates.each do |key, value|
193
- case key.to_sym
194
- when :name
195
- updated_project.name = value
196
- when :version
197
- updated_project.version = value
198
- when :project_type
199
- updated_project.project_type = value
200
- when :authors
201
- updated_project.authors = value
202
- when :description
203
- updated_project.description = value
204
- when :license_expression
205
- updated_project.license_expression = value
206
- when :git_remote_url
207
- updated_project.git_remote_url = value
208
- end
209
- end
210
-
211
- updated_project
212
- rescue StandardError => e
213
- raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
214
- end
215
-
216
- private
217
-
218
- # Validate project model
219
- def validate_project_model(project)
220
- errors = validate_project_model_errors(project)
221
- raise ArgumentError, errors.join(", ") if errors.any?
222
- errors
223
- end
224
-
225
- # Validate project model and return errors without raising
226
- def validate_project_model_errors(project)
227
- errors = []
228
-
229
- errors << "Project name cannot be empty" if project.name.nil? || project.name.strip.empty?
230
- errors << "Project version cannot be empty" if project.version.nil? || project.version.strip.empty?
231
- errors << "Project type cannot be empty" if project.project_type.nil? || project.project_type.strip.empty?
232
-
233
- # Validate steps
234
- project.steps.each_with_index do |step, index|
235
- errors << "Step #{index} name cannot be empty" if step.name.nil? || step.name.strip.empty?
236
- errors << "Step #{index} description cannot be empty" if step.description.nil? || step.description.strip.empty?
237
- errors << "Step #{index} commands cannot be empty" if step.commands.nil? || step.commands.empty?
238
- end
239
-
240
- errors
241
- end
242
-
243
- # Convert JSON data to Project
244
- def convert_from_json_data(data)
245
- project = Project.new(
246
- git_remote_url: data[:git_remote_url] || "",
247
- name: data[:name] || "",
248
- version: data[:version] || "",
249
- project_type: data[:project_type] || "",
250
- authors: data[:authors] || "authors",
251
- description: data[:description] || "description",
252
- license_expression: data[:license_expression] || "MIT",
253
- dotnet_projects: data[:dotnet_projects] || []
254
- )
255
-
256
- # Convert steps
257
- (data[:steps] || []).each do |step_data|
258
- step = Step.new(
259
- name: step_data[:name] || "",
260
- description: step_data[:description] || "",
261
- commands: step_data[:commands] || []
262
- )
263
- project.steps << step
264
- end
265
-
266
- project
267
- end
268
-
269
- # Convert Project to pretty JSON
270
- def convert_to_json_pretty(project)
271
- project_data = {
272
- name: project.name,
273
- version: project.version,
274
- project_type: project.project_type,
275
- authors: project.authors,
276
- description: project.description,
277
- license_expression: project.license_expression,
278
- steps: project.steps.map do |step|
279
- {
280
- name: step.name,
281
- description: step.description,
282
- commands: step.commands.to_a
283
- }
284
- end
285
- }
286
-
287
- JSON.pretty_generate(project_data)
288
- end
289
-
290
- # Convert Protobuf Project to Ruby model for helper classes
291
- def convert_to_ruby_model(proto_model)
292
- # Create a simple Ruby object that mimics the Project interface
293
- ruby_model = Object.new
294
-
295
- def ruby_model.name
296
- @name
297
- end
298
-
299
- def ruby_model.name=(value)
300
- @name = value
301
- end
302
-
303
- def ruby_model.version
304
- @version
305
- end
306
-
307
- def ruby_model.version=(value)
308
- @version = value
309
- end
310
-
311
- def ruby_model.project_type
312
- @project_type
313
- end
314
-
315
- def ruby_model.project_type=(value)
316
- @project_type = value
317
- end
318
-
319
- def ruby_model.steps
320
- @steps ||= []
321
- end
322
-
323
- def ruby_model.steps=(value)
324
- @steps = value
325
- end
326
-
327
- ruby_model.name = proto_model.name
328
- ruby_model.version = proto_model.version
329
- ruby_model.project_type = proto_model.project_type
330
-
331
- # Convert steps
332
- ruby_steps = proto_model.steps.map do |proto_step|
333
- ruby_step = Object.new
334
-
335
- def ruby_step.name
336
- @name
337
- end
338
-
339
- def ruby_step.name=(value)
340
- @name = value
341
- end
342
-
343
- def ruby_step.description
344
- @description
345
- end
346
-
347
- def ruby_step.description=(value)
348
- @description = value
349
- end
350
-
351
- def ruby_step.commands
352
- @commands ||= []
353
- end
354
-
355
- def ruby_step.commands=(value)
356
- @commands = value
357
- end
358
-
359
- ruby_step.name = proto_step.name
360
- ruby_step.description = proto_step.description
361
- ruby_step.commands = proto_step.commands.to_a
362
- ruby_step
363
- end
364
-
365
- ruby_model.steps = ruby_steps
366
- ruby_model
367
- end
368
- end
369
- end
370
- end
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../generated/makit/v1/configuration/project_service_services_pb"
4
+ require_relative "../../configuration/gitlab_helper"
5
+ require_relative "../../configuration/rakefile_helper"
6
+ require_relative "../../configuration/step"
7
+
8
+ module Makit
9
+ module V1
10
+ module Configuration
11
+ # gRPC service implementation for ProjectService
12
+ # Implements all the RPC methods defined in the protobuf service definition
13
+ class ProjectServiceImpl < ProjectService::Service
14
+ # Load a project from a JSON file
15
+ def load_from_file(request, _unused_call)
16
+ raise ArgumentError, "File does not exist: #{request.path}" unless File.exist?(request.path)
17
+
18
+ content = File.read(request.path)
19
+ data = JSON.parse(content, symbolize_names: true)
20
+
21
+ project = convert_from_json_data(data)
22
+ project
23
+ rescue ArgumentError => e
24
+ raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
25
+ rescue StandardError => e
26
+ raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
27
+ end
28
+
29
+ # Load a project from JSON string
30
+ def load_from_json(request, _unused_call)
31
+ raise ArgumentError, "JSON string cannot be empty" if request.json_string.nil? || request.json_string.strip.empty?
32
+
33
+ data = JSON.parse(request.json_string, symbolize_names: true)
34
+ project = convert_from_json_data(data)
35
+ project
36
+ rescue ArgumentError => e
37
+ raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
38
+ rescue StandardError => e
39
+ raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
40
+ end
41
+
42
+ # Save a project to a specific path as pretty JSON
43
+ def save_to_file(request, _unused_call)
44
+ validate_project_model(request.project)
45
+ raise ArgumentError, "Path cannot be empty" if request.path.nil? || request.path.strip.empty?
46
+
47
+ File.write(request.path, convert_to_json_pretty(request.project))
48
+ Google::Protobuf::Empty.new
49
+ rescue ArgumentError => e
50
+ raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
51
+ rescue StandardError => e
52
+ raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
53
+ end
54
+
55
+ # Save a project to the default .makit.json file
56
+ def save_to_default(request, _unused_call)
57
+ validate_project_model(request.project)
58
+ File.write(".makit.json", convert_to_json_pretty(request.project))
59
+ Google::Protobuf::Empty.new
60
+ rescue ArgumentError => e
61
+ raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
62
+ rescue StandardError => e
63
+ raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
64
+ end
65
+
66
+ # Load the default project from .makit.json or create a new one
67
+ def load_default(request, _unused_call)
68
+ if File.exist?(".makit.json")
69
+ load_from_file(LoadFromFileRequest.new(path: ".makit.json"), nil)
70
+ else
71
+ project = Project.new(
72
+ name: "",
73
+ version: "0.0.0",
74
+ project_type: "",
75
+ authors: "authors",
76
+ description: "description",
77
+ license_expression: "MIT",
78
+ steps: []
79
+ )
80
+ #Makit::Logging.default_logger.warn("Project not configured")
81
+ project
82
+ end
83
+ rescue StandardError => e
84
+ raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
85
+ end
86
+
87
+ # Generate GitLab CI YAML from project
88
+ def generate_gitlab_ci(request, _unused_call)
89
+ validate_project_model(request.project)
90
+ raise ArgumentError, "Path cannot be empty" if request.path.nil? || request.path.strip.empty?
91
+
92
+ # Convert protobuf model to Ruby model for GitLab helper
93
+ ruby_model = convert_to_ruby_model(request.project)
94
+ Makit::Configuration::GitLabHelper.to_yaml(ruby_model, request.path)
95
+ Google::Protobuf::Empty.new
96
+ rescue ArgumentError => e
97
+ raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
98
+ rescue StandardError => e
99
+ raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
100
+ end
101
+
102
+ # Generate Rakefile from project
103
+ def generate_rakefile(request, _unused_call)
104
+ validate_project_model(request.project)
105
+
106
+ # Convert protobuf model to Ruby model for Rakefile helper
107
+ ruby_model = convert_to_ruby_model(request.project)
108
+ content = Makit::Configuration::RakefileHelper.generate(ruby_model)
109
+ GenerateRakefileResponse.new(content: content)
110
+ rescue ArgumentError => e
111
+ raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
112
+ rescue StandardError => e
113
+ raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
114
+ end
115
+
116
+ # Write Rakefile to file
117
+ def write_rakefile(request, _unused_call)
118
+ validate_project_model(request.project)
119
+ raise ArgumentError, "Path cannot be empty" if request.path.nil? || request.path.strip.empty?
120
+
121
+ # Convert protobuf model to Ruby model for Rakefile helper
122
+ ruby_model = convert_to_ruby_model(request.project)
123
+ Makit::Configuration::RakefileHelper.write(ruby_model, request.path)
124
+ Google::Protobuf::Empty.new
125
+ rescue ArgumentError => e
126
+ raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
127
+ rescue StandardError => e
128
+ raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
129
+ end
130
+
131
+ # Validate project configuration
132
+ def validate_project(request, _unused_call)
133
+ errors = validate_project_model_errors(request.project)
134
+ ValidateProjectResponse.new(errors: errors)
135
+ rescue StandardError => e
136
+ raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
137
+ end
138
+
139
+ # Merge two project configurations
140
+ def merge_projects(request, _unused_call)
141
+ merged = Project.new(
142
+ git_remote_url: request.override_project.git_remote_url || request.base_project.git_remote_url,
143
+ name: request.override_project.name || request.base_project.name,
144
+ version: request.override_project.version || request.base_project.version,
145
+ project_type: request.override_project.project_type || request.base_project.project_type,
146
+ authors: request.override_project.authors || request.base_project.authors,
147
+ description: request.override_project.description || request.base_project.description,
148
+ license_expression: request.override_project.license_expression || request.base_project.license_expression,
149
+ dotnet_projects: request.override_project.dotnet_projects.any? ? request.override_project.dotnet_projects.to_a : request.base_project.dotnet_projects.to_a,
150
+ steps: request.override_project.steps.any? ? request.override_project.steps.to_a : request.base_project.steps.to_a
151
+ )
152
+ merged
153
+ rescue StandardError => e
154
+ raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
155
+ end
156
+
157
+ # Create a new project with default values
158
+ def create_project(request, _unused_call)
159
+ raise ArgumentError, "Project name cannot be empty" if request.name.nil? || request.name.strip.empty?
160
+
161
+ project = Project.new(
162
+ name: request.name,
163
+ version: request.version || "0.0.0",
164
+ project_type: request.project_type || "gem",
165
+ authors: "authors",
166
+ description: "description",
167
+ license_expression: "MIT",
168
+ steps: []
169
+ )
170
+ project
171
+ rescue ArgumentError => e
172
+ raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
173
+ rescue StandardError => e
174
+ raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
175
+ end
176
+
177
+ # Update project with new values
178
+ def update_project(request, _unused_call)
179
+ updated_project = Project.new(
180
+ git_remote_url: request.project.git_remote_url,
181
+ name: request.project.name,
182
+ version: request.project.version,
183
+ project_type: request.project.project_type,
184
+ authors: request.project.authors,
185
+ description: request.project.description,
186
+ license_expression: request.project.license_expression,
187
+ dotnet_projects: request.project.dotnet_projects.to_a,
188
+ steps: request.project.steps.to_a
189
+ )
190
+
191
+ # Apply updates
192
+ request.updates.each do |key, value|
193
+ case key.to_sym
194
+ when :name
195
+ updated_project.name = value
196
+ when :version
197
+ updated_project.version = value
198
+ when :project_type
199
+ updated_project.project_type = value
200
+ when :authors
201
+ updated_project.authors = value
202
+ when :description
203
+ updated_project.description = value
204
+ when :license_expression
205
+ updated_project.license_expression = value
206
+ when :git_remote_url
207
+ updated_project.git_remote_url = value
208
+ end
209
+ end
210
+
211
+ updated_project
212
+ rescue StandardError => e
213
+ raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
214
+ end
215
+
216
+ private
217
+
218
+ # Validate project model
219
+ def validate_project_model(project)
220
+ errors = validate_project_model_errors(project)
221
+ raise ArgumentError, errors.join(", ") if errors.any?
222
+ errors
223
+ end
224
+
225
+ # Validate project model and return errors without raising
226
+ def validate_project_model_errors(project)
227
+ errors = []
228
+
229
+ errors << "Project name cannot be empty" if project.name.nil? || project.name.strip.empty?
230
+ errors << "Project version cannot be empty" if project.version.nil? || project.version.strip.empty?
231
+ errors << "Project type cannot be empty" if project.project_type.nil? || project.project_type.strip.empty?
232
+
233
+ # Validate steps
234
+ project.steps.each_with_index do |step, index|
235
+ errors << "Step #{index} name cannot be empty" if step.name.nil? || step.name.strip.empty?
236
+ errors << "Step #{index} description cannot be empty" if step.description.nil? || step.description.strip.empty?
237
+ errors << "Step #{index} commands cannot be empty" if step.commands.nil? || step.commands.empty?
238
+ end
239
+
240
+ errors
241
+ end
242
+
243
+ # Convert JSON data to Project
244
+ def convert_from_json_data(data)
245
+ project = Project.new(
246
+ git_remote_url: data[:git_remote_url] || "",
247
+ name: data[:name] || "",
248
+ version: data[:version] || "",
249
+ project_type: data[:project_type] || "",
250
+ authors: data[:authors] || "authors",
251
+ description: data[:description] || "description",
252
+ license_expression: data[:license_expression] || "MIT",
253
+ dotnet_projects: data[:dotnet_projects] || []
254
+ )
255
+
256
+ # Convert steps
257
+ (data[:steps] || []).each do |step_data|
258
+ step = Step.new(
259
+ name: step_data[:name] || "",
260
+ description: step_data[:description] || "",
261
+ commands: step_data[:commands] || []
262
+ )
263
+ project.steps << step
264
+ end
265
+
266
+ project
267
+ end
268
+
269
+ # Convert Project to pretty JSON
270
+ def convert_to_json_pretty(project)
271
+ project_data = {
272
+ name: project.name,
273
+ version: project.version,
274
+ project_type: project.project_type,
275
+ authors: project.authors,
276
+ description: project.description,
277
+ license_expression: project.license_expression,
278
+ steps: project.steps.map do |step|
279
+ {
280
+ name: step.name,
281
+ description: step.description,
282
+ commands: step.commands.to_a
283
+ }
284
+ end
285
+ }
286
+
287
+ JSON.pretty_generate(project_data)
288
+ end
289
+
290
+ # Convert Protobuf Project to Ruby model for helper classes
291
+ def convert_to_ruby_model(proto_model)
292
+ # Create a simple Ruby object that mimics the Project interface
293
+ ruby_model = Object.new
294
+
295
+ def ruby_model.name
296
+ @name
297
+ end
298
+
299
+ def ruby_model.name=(value)
300
+ @name = value
301
+ end
302
+
303
+ def ruby_model.version
304
+ @version
305
+ end
306
+
307
+ def ruby_model.version=(value)
308
+ @version = value
309
+ end
310
+
311
+ def ruby_model.project_type
312
+ @project_type
313
+ end
314
+
315
+ def ruby_model.project_type=(value)
316
+ @project_type = value
317
+ end
318
+
319
+ def ruby_model.steps
320
+ @steps ||= []
321
+ end
322
+
323
+ def ruby_model.steps=(value)
324
+ @steps = value
325
+ end
326
+
327
+ ruby_model.name = proto_model.name
328
+ ruby_model.version = proto_model.version
329
+ ruby_model.project_type = proto_model.project_type
330
+
331
+ # Convert steps
332
+ ruby_steps = proto_model.steps.map do |proto_step|
333
+ ruby_step = Object.new
334
+
335
+ def ruby_step.name
336
+ @name
337
+ end
338
+
339
+ def ruby_step.name=(value)
340
+ @name = value
341
+ end
342
+
343
+ def ruby_step.description
344
+ @description
345
+ end
346
+
347
+ def ruby_step.description=(value)
348
+ @description = value
349
+ end
350
+
351
+ def ruby_step.commands
352
+ @commands ||= []
353
+ end
354
+
355
+ def ruby_step.commands=(value)
356
+ @commands = value
357
+ end
358
+
359
+ ruby_step.name = proto_step.name
360
+ ruby_step.description = proto_step.description
361
+ ruby_step.commands = proto_step.commands.to_a
362
+ ruby_step
363
+ end
364
+
365
+ ruby_model.steps = ruby_steps
366
+ ruby_model
367
+ end
368
+ end
369
+ end
370
+ end
371
371
  end