makit 0.0.168 → 0.0.169

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 (179) 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 +187 -187
  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/github_actions.rb +202 -202
  84. data/lib/makit/gitlab/pipeline.rb +857 -857
  85. data/lib/makit/gitlab/pipeline_service_impl.rb +1535 -1535
  86. data/lib/makit/gitlab_runner.rb +59 -59
  87. data/lib/makit/humanize.rb +218 -218
  88. data/lib/makit/indexer.rb +47 -47
  89. data/lib/makit/io/filesystem.rb +111 -111
  90. data/lib/makit/io/filesystem_service_impl.rb +337 -337
  91. data/lib/makit/lint.rb +212 -212
  92. data/lib/makit/logging/configuration.rb +309 -309
  93. data/lib/makit/logging/format_registry.rb +84 -84
  94. data/lib/makit/logging/formatters/base.rb +39 -39
  95. data/lib/makit/logging/formatters/console_formatter.rb +140 -140
  96. data/lib/makit/logging/formatters/json_formatter.rb +65 -65
  97. data/lib/makit/logging/formatters/plain_text_formatter.rb +71 -71
  98. data/lib/makit/logging/formatters/text_formatter.rb +64 -64
  99. data/lib/makit/logging/log_request.rb +119 -119
  100. data/lib/makit/logging/logger.rb +199 -199
  101. data/lib/makit/logging/sinks/base.rb +91 -91
  102. data/lib/makit/logging/sinks/console.rb +72 -72
  103. data/lib/makit/logging/sinks/file_sink.rb +92 -92
  104. data/lib/makit/logging/sinks/structured.rb +123 -123
  105. data/lib/makit/logging/sinks/unified_file_sink.rb +296 -296
  106. data/lib/makit/logging.rb +578 -578
  107. data/lib/makit/markdown.rb +75 -75
  108. data/lib/makit/mp/basic_object_mp.rb +17 -17
  109. data/lib/makit/mp/command_mp.rb +13 -13
  110. data/lib/makit/mp/command_request.mp.rb +17 -17
  111. data/lib/makit/mp/project_mp.rb +199 -199
  112. data/lib/makit/mp/string_mp.rb +205 -205
  113. data/lib/makit/nuget.rb +460 -458
  114. data/lib/makit/podman/podman.rb +458 -458
  115. data/lib/makit/podman/podman_service_impl.rb +1081 -1081
  116. data/lib/makit/port.rb +32 -32
  117. data/lib/makit/process.rb +377 -377
  118. data/lib/makit/protoc.rb +112 -112
  119. data/lib/makit/rake/cli.rb +196 -196
  120. data/lib/makit/rake/trace_controller.rb +174 -174
  121. data/lib/makit/rake.rb +81 -81
  122. data/lib/makit/ruby/cli.rb +185 -185
  123. data/lib/makit/ruby.rb +25 -25
  124. data/lib/makit/rubygems.rb +137 -137
  125. data/lib/makit/secrets/azure_key_vault.rb +322 -322
  126. data/lib/makit/secrets/azure_secrets.rb +221 -221
  127. data/lib/makit/secrets/local_secrets.rb +72 -72
  128. data/lib/makit/secrets/secrets_manager.rb +105 -105
  129. data/lib/makit/secrets.rb +96 -96
  130. data/lib/makit/serializer.rb +130 -130
  131. data/lib/makit/services/builder.rb +186 -186
  132. data/lib/makit/services/error_handler.rb +226 -226
  133. data/lib/makit/services/repository_manager.rb +367 -367
  134. data/lib/makit/services/validator.rb +112 -112
  135. data/lib/makit/setup/classlib.rb +101 -101
  136. data/lib/makit/setup/gem.rb +268 -268
  137. data/lib/makit/setup/pages.rb +11 -11
  138. data/lib/makit/setup/razorclasslib.rb +101 -101
  139. data/lib/makit/setup/runner.rb +54 -54
  140. data/lib/makit/setup.rb +5 -5
  141. data/lib/makit/show.rb +110 -110
  142. data/lib/makit/storage.rb +126 -126
  143. data/lib/makit/symbols.rb +175 -175
  144. data/lib/makit/task_info.rb +130 -130
  145. data/lib/makit/tasks/at_exit.rb +15 -15
  146. data/lib/makit/tasks/build.rb +22 -22
  147. data/lib/makit/tasks/bump.rb +7 -7
  148. data/lib/makit/tasks/clean.rb +13 -13
  149. data/lib/makit/tasks/configure.rb +10 -10
  150. data/lib/makit/tasks/format.rb +10 -10
  151. data/lib/makit/tasks/hook_manager.rb +443 -443
  152. data/lib/makit/tasks/info.rb +368 -368
  153. data/lib/makit/tasks/init.rb +49 -49
  154. data/lib/makit/tasks/integrate.rb +60 -60
  155. data/lib/makit/tasks/pull_incoming.rb +13 -13
  156. data/lib/makit/tasks/secrets.rb +7 -7
  157. data/lib/makit/tasks/setup.rb +16 -16
  158. data/lib/makit/tasks/sync.rb +14 -14
  159. data/lib/makit/tasks/tag.rb +27 -27
  160. data/lib/makit/tasks/task_monkey_patch.rb +81 -81
  161. data/lib/makit/tasks/test.rb +22 -22
  162. data/lib/makit/tasks/update.rb +21 -21
  163. data/lib/makit/tasks/version.rb +6 -6
  164. data/lib/makit/tasks.rb +24 -24
  165. data/lib/makit/test_cache.rb +239 -239
  166. data/lib/makit/tree.rb +37 -37
  167. data/lib/makit/v1/configuration/project_service_impl.rb +370 -370
  168. data/lib/makit/v1/git/git_repository_service_impl.rb +295 -295
  169. data/lib/makit/v1/makit.v1_pb.rb +35 -35
  170. data/lib/makit/v1/makit.v1_services_pb.rb +27 -27
  171. data/lib/makit/v1/services/repository_manager_service_impl.rb +572 -572
  172. data/lib/makit/version.rb +661 -661
  173. data/lib/makit/version_util.rb +21 -21
  174. data/lib/makit/wix.rb +95 -95
  175. data/lib/makit/yaml.rb +29 -29
  176. data/lib/makit/zip.rb +17 -17
  177. data/lib/makit copy.rb +44 -44
  178. data/lib/makit.rb +121 -121
  179. metadata +2 -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