uffizzi_core 0.1.3

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 (240) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/README.md +46 -0
  4. data/Rakefile +31 -0
  5. data/app/assets/config/uffizzi_core_manifest.js +1 -0
  6. data/app/assets/stylesheets/uffizzi_core/application.css +15 -0
  7. data/app/clients/uffizzi_core/amazon_registry_client.rb +18 -0
  8. data/app/clients/uffizzi_core/azure_registry_client/request_result.rb +5 -0
  9. data/app/clients/uffizzi_core/azure_registry_client.rb +42 -0
  10. data/app/clients/uffizzi_core/controller_client/request_result.rb +5 -0
  11. data/app/clients/uffizzi_core/controller_client.rb +106 -0
  12. data/app/clients/uffizzi_core/docker_hub_client/request_result.rb +7 -0
  13. data/app/clients/uffizzi_core/docker_hub_client.rb +139 -0
  14. data/app/clients/uffizzi_core/github/app_client.rb +19 -0
  15. data/app/clients/uffizzi_core/github/installation_client.rb +11 -0
  16. data/app/clients/uffizzi_core/github/user_client.rb +51 -0
  17. data/app/clients/uffizzi_core/google_registry_client/request_result.rb +5 -0
  18. data/app/clients/uffizzi_core/google_registry_client.rb +42 -0
  19. data/app/contexts/uffizzi_core/base_context.rb +12 -0
  20. data/app/contexts/uffizzi_core/project_context.rb +13 -0
  21. data/app/contexts/uffizzi_core/webhooks_context.rb +9 -0
  22. data/app/controllers/concerns/uffizzi_core/auth_management.rb +23 -0
  23. data/app/controllers/concerns/uffizzi_core/authorization_concern.rb +38 -0
  24. data/app/controllers/concerns/uffizzi_core/dependency_injection_concern.rb +19 -0
  25. data/app/controllers/uffizzi_core/api/cli/v1/account/application_controller.rb +7 -0
  26. data/app/controllers/uffizzi_core/api/cli/v1/account/credentials_controller.rb +55 -0
  27. data/app/controllers/uffizzi_core/api/cli/v1/application_controller.rb +5 -0
  28. data/app/controllers/uffizzi_core/api/cli/v1/projects/application_controller.rb +11 -0
  29. data/app/controllers/uffizzi_core/api/cli/v1/projects/compose_files_controller.rb +93 -0
  30. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/activity_items_controller.rb +36 -0
  31. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/application_controller.rb +7 -0
  32. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/containers/application_controller.rb +8 -0
  33. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/containers/logs_controller.rb +27 -0
  34. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/containers_controller.rb +24 -0
  35. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/events_controller.rb +29 -0
  36. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments_controller.rb +148 -0
  37. data/app/controllers/uffizzi_core/api/cli/v1/projects/secrets_controller.rb +69 -0
  38. data/app/controllers/uffizzi_core/api/cli/v1/projects_controller.rb +19 -0
  39. data/app/controllers/uffizzi_core/api/cli/v1/sessions_controller.rb +43 -0
  40. data/app/controllers/uffizzi_core/application_controller.rb +51 -0
  41. data/app/errors/uffizzi_core/compose_file/build_error.rb +4 -0
  42. data/app/errors/uffizzi_core/compose_file/credential_error.rb +4 -0
  43. data/app/errors/uffizzi_core/compose_file/not_found_error.rb +4 -0
  44. data/app/errors/uffizzi_core/compose_file/parse_error.rb +4 -0
  45. data/app/errors/uffizzi_core/compose_file/secrets_error.rb +4 -0
  46. data/app/errors/uffizzi_core/deployment_not_found_error.rb +10 -0
  47. data/app/forms/uffizzi_core/api/cli/v1/account/credential/create_form.rb +26 -0
  48. data/app/forms/uffizzi_core/api/cli/v1/compose_file/check_credentials_form.rb +21 -0
  49. data/app/forms/uffizzi_core/api/cli/v1/compose_file/cli_form.rb +39 -0
  50. data/app/forms/uffizzi_core/api/cli/v1/compose_file/create_form.rb +13 -0
  51. data/app/forms/uffizzi_core/api/cli/v1/compose_file/template_form.rb +44 -0
  52. data/app/forms/uffizzi_core/api/cli/v1/compose_file/update_form.rb +9 -0
  53. data/app/forms/uffizzi_core/api/cli/v1/config_file/create_form.rb +11 -0
  54. data/app/forms/uffizzi_core/api/cli/v1/deployment/create_form.rb +91 -0
  55. data/app/forms/uffizzi_core/api/cli/v1/project/delete_secret_form.rb +27 -0
  56. data/app/forms/uffizzi_core/api/cli/v1/project/update_form.rb +40 -0
  57. data/app/forms/uffizzi_core/api/cli/v1/session_create_form.rb +29 -0
  58. data/app/forms/uffizzi_core/api/cli/v1/template/create_form.rb +65 -0
  59. data/app/forms/uffizzi_core/application_form.rb +11 -0
  60. data/app/forms/uffizzi_core/application_form_without_active_record.rb +17 -0
  61. data/app/forms/uffizzi_core/mass_assignment_control_concern.rb +22 -0
  62. data/app/helpers/uffizzi_core/application_helper.rb +6 -0
  63. data/app/jobs/uffizzi_core/account/create_credential_job.rb +10 -0
  64. data/app/jobs/uffizzi_core/activity_item/docker/update_digest_job.rb +11 -0
  65. data/app/jobs/uffizzi_core/application_job.rb +7 -0
  66. data/app/jobs/uffizzi_core/config_file/apply_job.rb +31 -0
  67. data/app/jobs/uffizzi_core/credential/docker_hub/create_webhook_job.rb +15 -0
  68. data/app/jobs/uffizzi_core/deployment/create_credential_job.rb +32 -0
  69. data/app/jobs/uffizzi_core/deployment/create_credentials_job.rb +17 -0
  70. data/app/jobs/uffizzi_core/deployment/create_job.rb +15 -0
  71. data/app/jobs/uffizzi_core/deployment/create_webhooks_job.rb +13 -0
  72. data/app/jobs/uffizzi_core/deployment/delete_credential_job.rb +13 -0
  73. data/app/jobs/uffizzi_core/deployment/delete_job.rb +11 -0
  74. data/app/jobs/uffizzi_core/deployment/deploy_containers_job.rb +27 -0
  75. data/app/jobs/uffizzi_core/deployment/manage_deploy_activity_item_job.rb +19 -0
  76. data/app/jobs/uffizzi_core/deployment/send_github_preview_message_job.rb +13 -0
  77. data/app/lib/uffizzi_core/rbac/user_access_service.rb +21 -0
  78. data/app/mailers/uffizzi_core/application_mailer.rb +8 -0
  79. data/app/models/concerns/uffizzi_core/hashid_concern.rb +25 -0
  80. data/app/models/concerns/uffizzi_core/state_machine_concern.rb +16 -0
  81. data/app/models/uffizzi_core/account.rb +101 -0
  82. data/app/models/uffizzi_core/activity_item/docker.rb +4 -0
  83. data/app/models/uffizzi_core/activity_item/github.rb +4 -0
  84. data/app/models/uffizzi_core/activity_item/memory_limit.rb +4 -0
  85. data/app/models/uffizzi_core/activity_item.rb +58 -0
  86. data/app/models/uffizzi_core/application_record.rb +7 -0
  87. data/app/models/uffizzi_core/build.rb +39 -0
  88. data/app/models/uffizzi_core/comment.rb +16 -0
  89. data/app/models/uffizzi_core/compose_file.rb +57 -0
  90. data/app/models/uffizzi_core/config_file.rb +24 -0
  91. data/app/models/uffizzi_core/container.rb +100 -0
  92. data/app/models/uffizzi_core/container_config_file.rb +8 -0
  93. data/app/models/uffizzi_core/continuous_preview.rb +4 -0
  94. data/app/models/uffizzi_core/coupon.rb +5 -0
  95. data/app/models/uffizzi_core/credential/amazon.rb +4 -0
  96. data/app/models/uffizzi_core/credential/azure.rb +4 -0
  97. data/app/models/uffizzi_core/credential/docker_hub.rb +4 -0
  98. data/app/models/uffizzi_core/credential/github.rb +4 -0
  99. data/app/models/uffizzi_core/credential/google.rb +4 -0
  100. data/app/models/uffizzi_core/credential.rb +64 -0
  101. data/app/models/uffizzi_core/database.rb +4 -0
  102. data/app/models/uffizzi_core/database_offering.rb +4 -0
  103. data/app/models/uffizzi_core/deployment.rb +77 -0
  104. data/app/models/uffizzi_core/event.rb +13 -0
  105. data/app/models/uffizzi_core/invitation.rb +27 -0
  106. data/app/models/uffizzi_core/membership.rb +16 -0
  107. data/app/models/uffizzi_core/payment.rb +11 -0
  108. data/app/models/uffizzi_core/price.rb +9 -0
  109. data/app/models/uffizzi_core/product.rb +11 -0
  110. data/app/models/uffizzi_core/project.rb +66 -0
  111. data/app/models/uffizzi_core/rating.rb +20 -0
  112. data/app/models/uffizzi_core/repo/amazon.rb +4 -0
  113. data/app/models/uffizzi_core/repo/azure.rb +4 -0
  114. data/app/models/uffizzi_core/repo/docker_hub.rb +4 -0
  115. data/app/models/uffizzi_core/repo/github.rb +4 -0
  116. data/app/models/uffizzi_core/repo/google.rb +4 -0
  117. data/app/models/uffizzi_core/repo.rb +39 -0
  118. data/app/models/uffizzi_core/role.rb +17 -0
  119. data/app/models/uffizzi_core/template.rb +19 -0
  120. data/app/models/uffizzi_core/user.rb +62 -0
  121. data/app/models/uffizzi_core/user_project.rb +14 -0
  122. data/app/policies/uffizzi_core/api/cli/v1/account/credentials_policy.rb +11 -0
  123. data/app/policies/uffizzi_core/api/cli/v1/projects/compose_files_policy.rb +15 -0
  124. data/app/policies/uffizzi_core/api/cli/v1/projects/deployments/activity_items_policy.rb +7 -0
  125. data/app/policies/uffizzi_core/api/cli/v1/projects/deployments/containers_policy.rb +7 -0
  126. data/app/policies/uffizzi_core/api/cli/v1/projects/deployments/events_policy.rb +7 -0
  127. data/app/policies/uffizzi_core/api/cli/v1/projects/deployments_policy.rb +23 -0
  128. data/app/policies/uffizzi_core/api/cli/v1/projects/secrets_policy.rb +15 -0
  129. data/app/policies/uffizzi_core/api/cli/v1/projects_policy.rb +7 -0
  130. data/app/policies/uffizzi_core/application_policy.rb +12 -0
  131. data/app/repositories/uffizzi_core/activity_item_repo.rb +9 -0
  132. data/app/repositories/uffizzi_core/basic_order_repo.rb +11 -0
  133. data/app/repositories/uffizzi_core/build_repo.rb +23 -0
  134. data/app/repositories/uffizzi_core/comment_repo.rb +11 -0
  135. data/app/repositories/uffizzi_core/compose_file_repo.rb +11 -0
  136. data/app/repositories/uffizzi_core/config_file_repo.rb +40 -0
  137. data/app/repositories/uffizzi_core/container_repo.rb +25 -0
  138. data/app/repositories/uffizzi_core/credential_repo.rb +36 -0
  139. data/app/repositories/uffizzi_core/deployment_repo.rb +23 -0
  140. data/app/repositories/uffizzi_core/event_repo.rb +9 -0
  141. data/app/repositories/uffizzi_core/membership_repo.rb +10 -0
  142. data/app/repositories/uffizzi_core/price_repo.rb +11 -0
  143. data/app/repositories/uffizzi_core/product_repo.rb +11 -0
  144. data/app/repositories/uffizzi_core/project_repo.rb +10 -0
  145. data/app/repositories/uffizzi_core/repo_repo.rb +10 -0
  146. data/app/repositories/uffizzi_core/template_repo.rb +87 -0
  147. data/app/repositories/uffizzi_core/usage_repo.rb +9 -0
  148. data/app/repositories/uffizzi_core/user_repo.rb +11 -0
  149. data/app/responders/uffizzi_core/json_responder.rb +13 -0
  150. data/app/serializers/uffizzi_core/api/cli/v1/account/credential_serializer.rb +9 -0
  151. data/app/serializers/uffizzi_core/api/cli/v1/project_serializer.rb +7 -0
  152. data/app/serializers/uffizzi_core/api/cli/v1/projects/compose_file_serializer.rb +7 -0
  153. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/container_serializer.rb +23 -0
  154. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/user_serializer.rb +11 -0
  155. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer.rb +74 -0
  156. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployments/activity_item_serializer.rb +24 -0
  157. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployments/container_serializer/container_config_file_serializer/config_file_serializer.rb +6 -0
  158. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployments/container_serializer/container_config_file_serializer.rb +7 -0
  159. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployments/container_serializer.rb +30 -0
  160. data/app/serializers/uffizzi_core/api/cli/v1/user_serializer/account_serializer.rb +5 -0
  161. data/app/serializers/uffizzi_core/api/cli/v1/user_serializer.rb +7 -0
  162. data/app/serializers/uffizzi_core/base_serializer.rb +7 -0
  163. data/app/serializers/uffizzi_core/controller/create_credential/credential_serializer.rb +17 -0
  164. data/app/serializers/uffizzi_core/controller/create_deployment/deployment_serializer.rb +5 -0
  165. data/app/serializers/uffizzi_core/controller/deploy_containers/container_serializer.rb +53 -0
  166. data/app/serializers/uffizzi_core/controller/deploy_containers/credential_serializer.rb +5 -0
  167. data/app/services/uffizzi_core/account_service.rb +21 -0
  168. data/app/services/uffizzi_core/activity_item_service.rb +98 -0
  169. data/app/services/uffizzi_core/amazon/credential_service.rb +31 -0
  170. data/app/services/uffizzi_core/amazon_service.rb +45 -0
  171. data/app/services/uffizzi_core/azure/credential_service.rb +18 -0
  172. data/app/services/uffizzi_core/cli/compose_file_service.rb +203 -0
  173. data/app/services/uffizzi_core/compose_file/builders/config_files_builder_service.rb +31 -0
  174. data/app/services/uffizzi_core/compose_file/builders/container_builder_service.rb +225 -0
  175. data/app/services/uffizzi_core/compose_file/builders/docker_repo_builder_service.rb +25 -0
  176. data/app/services/uffizzi_core/compose_file/builders/github_repo_builder_service.rb +59 -0
  177. data/app/services/uffizzi_core/compose_file/builders/template_builder_service.rb +45 -0
  178. data/app/services/uffizzi_core/compose_file/builders/variables_builder_service.rb +58 -0
  179. data/app/services/uffizzi_core/compose_file/config_files_service.rb +52 -0
  180. data/app/services/uffizzi_core/compose_file/config_option_service.rb +37 -0
  181. data/app/services/uffizzi_core/compose_file/configs_options_service.rb +26 -0
  182. data/app/services/uffizzi_core/compose_file/container_service.rb +64 -0
  183. data/app/services/uffizzi_core/compose_file/continuous_preview_options_service.rb +57 -0
  184. data/app/services/uffizzi_core/compose_file/dependencies_service.rb +55 -0
  185. data/app/services/uffizzi_core/compose_file/errors_service.rb +46 -0
  186. data/app/services/uffizzi_core/compose_file/github_dependencies_service.rb +38 -0
  187. data/app/services/uffizzi_core/compose_file/ingress_options_service.rb +49 -0
  188. data/app/services/uffizzi_core/compose_file/secrets_options_service.rb +28 -0
  189. data/app/services/uffizzi_core/compose_file/services_options/build_service.rb +93 -0
  190. data/app/services/uffizzi_core/compose_file/services_options/command_service.rb +18 -0
  191. data/app/services/uffizzi_core/compose_file/services_options/configs_service.rb +51 -0
  192. data/app/services/uffizzi_core/compose_file/services_options/deploy_service.rb +44 -0
  193. data/app/services/uffizzi_core/compose_file/services_options/entrypoint_service.rb +18 -0
  194. data/app/services/uffizzi_core/compose_file/services_options/env_file_service.rb +34 -0
  195. data/app/services/uffizzi_core/compose_file/services_options/environment_service.rb +20 -0
  196. data/app/services/uffizzi_core/compose_file/services_options/image_service.rb +89 -0
  197. data/app/services/uffizzi_core/compose_file/services_options/secrets_service.rb +35 -0
  198. data/app/services/uffizzi_core/compose_file/services_options_service.rb +55 -0
  199. data/app/services/uffizzi_core/compose_file/template_service.rb +55 -0
  200. data/app/services/uffizzi_core/compose_file/update_service.rb +29 -0
  201. data/app/services/uffizzi_core/compose_file/variables_service.rb +25 -0
  202. data/app/services/uffizzi_core/compose_file_service.rb +33 -0
  203. data/app/services/uffizzi_core/container_service.rb +57 -0
  204. data/app/services/uffizzi_core/controller_service.rb +80 -0
  205. data/app/services/uffizzi_core/credential_service.rb +44 -0
  206. data/app/services/uffizzi_core/deployment_service.rb +274 -0
  207. data/app/services/uffizzi_core/docker_hub/credential_service.rb +15 -0
  208. data/app/services/uffizzi_core/docker_hub_service.rb +77 -0
  209. data/app/services/uffizzi_core/github/app_service.rb +51 -0
  210. data/app/services/uffizzi_core/github/credential_service.rb +124 -0
  211. data/app/services/uffizzi_core/github/message_service.rb +20 -0
  212. data/app/services/uffizzi_core/github_service.rb +28 -0
  213. data/app/services/uffizzi_core/google/credential_service.rb +18 -0
  214. data/app/services/uffizzi_core/logs_service.rb +33 -0
  215. data/app/services/uffizzi_core/manage_activity_items_service.rb +166 -0
  216. data/app/services/uffizzi_core/project_service.rb +38 -0
  217. data/app/services/uffizzi_core/repo_service.rb +178 -0
  218. data/app/services/uffizzi_core/response_service.rb +13 -0
  219. data/app/services/uffizzi_core/template_service.rb +21 -0
  220. data/app/services/uffizzi_core/token_service.rb +19 -0
  221. data/app/services/uffizzi_core/user_access_service.rb +14 -0
  222. data/app/utils/uffizzi_core/converters.rb +33 -0
  223. data/app/validators/uffizzi_core/email_validator.rb +9 -0
  224. data/app/validators/uffizzi_core/environment_variable_list_validator.rb +15 -0
  225. data/app/validators/uffizzi_core/image_command_args_validator.rb +21 -0
  226. data/config/initializers/rswag_api.rb +15 -0
  227. data/config/initializers/rswag_ui.rb +15 -0
  228. data/config/initializers/swagger_yard.rb +17 -0
  229. data/config/locales/en.activerecord.yml +18 -0
  230. data/config/locales/en.yml +61 -0
  231. data/config/routes.rb +55 -0
  232. data/db/migrate/20220218121438_create_uffizzi_core_tables.rb +375 -0
  233. data/db/migrate/20220325113342_add_name_to_uffizzi_containers.rb +7 -0
  234. data/db/seeds.rb +16 -0
  235. data/lib/tasks/uffizzi_core_tasks.rake +14 -0
  236. data/lib/uffizzi_core/engine.rb +15 -0
  237. data/lib/uffizzi_core/version.rb +5 -0
  238. data/lib/uffizzi_core.rb +60 -0
  239. data/swagger/v1/swagger.json +1278 -0
  240. metadata +935 -0
@@ -0,0 +1,178 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UffizziCore::RepoService
4
+ AVAILABLE_KINDS = [
5
+ {
6
+ name: :buildpacks18,
7
+ detect: proc { |**_args| { available: true, args: [] } },
8
+ },
9
+ {
10
+ name: :dockerfile,
11
+ detect: proc { |**args|
12
+ has_dockerfiles = args[:dockerfiles].is_a?(Array) && !args[:dockerfiles].empty?
13
+ multiple_dockerfiles = has_dockerfiles && args[:dockerfiles].length > 1
14
+
15
+ {
16
+ available: has_dockerfiles,
17
+ args: multiple_dockerfiles ? { name: :dockerfile, type: :select, options: args[:dockerfiles] } : [],
18
+ }
19
+ },
20
+ },
21
+ {
22
+ name: :dotnet,
23
+ detect: proc { |**args|
24
+ has_app_runtimes = args[:dotnetruntimes].is_a?(Array) && !args[:dotnetruntimes].empty?
25
+ multiple_app_runtimes = has_app_runtimes && args[:dotnetruntimes].length > 1
26
+ has_csproj = args[:csproj].present?
27
+
28
+ {
29
+ available: has_app_runtimes || has_csproj,
30
+ args: multiple_app_runtimes ? { name: :dotnetruntimes, type: :select, options: args[:dotnetruntimes] } : [],
31
+ }
32
+ },
33
+ },
34
+ {
35
+ name: :gatsby,
36
+ detect: proc { |**args| { available: args[:gatsbyconfig].present?, args: [] } },
37
+ }, {
38
+ name: :barestatic,
39
+ detect: proc { |**args|
40
+ { available: args[:barestatic].present? && args.filter_map do |k, v|
41
+ ![:barestatic, :dockerfiles].include?(k) && v.present?
42
+ end.blank?, args: [] }
43
+ },
44
+ }
45
+ ].freeze
46
+
47
+ class << self
48
+ def nodejs_static?(repo)
49
+ repo.gatsby? || repo.barestatic?
50
+ end
51
+
52
+ def cnb?(repo)
53
+ repo.buildpacks18? || repo.dotnet? || nodejs_static?(repo)
54
+ end
55
+
56
+ def needs_target_port?(repo)
57
+ return false if repo.nil?
58
+
59
+ !repo.dockerfile?
60
+ end
61
+
62
+ def credential(repo)
63
+ credentials = repo.project.account.credentials
64
+
65
+ case repo.type
66
+ when UffizziCore::Repo::Github.name
67
+ credentials.github.first
68
+ when UffizziCore::Repo::DockerHub.name
69
+ credentials.docker_hub.first
70
+ when UffizziCore::Repo::Azure.name
71
+ credentials.azure.first
72
+ when UffizziCore::Repo::Google.name
73
+ credentials.google.first
74
+ when UffizziCore::Repo::Amazon.name
75
+ credentials.amazon.first
76
+ end
77
+ end
78
+
79
+ def image_name(repo)
80
+ "e#{repo.container.deployment_id}r#{repo.id}-#{Digest::SHA256.hexdigest("#{self.class}:#{repo.branch}:
81
+ #{repo.project_id}:#{repo.id}")[0, 10]}"
82
+ end
83
+
84
+ def tag(repo)
85
+ repo&.builds&.deployed&.last&.commit || 'latest'
86
+ end
87
+
88
+ def image(repo)
89
+ repo_credential = credential(repo)
90
+
91
+ "#{repo_credential.registry_url}/#{image_name(repo)}"
92
+ end
93
+
94
+ def select_default_from(meta)
95
+ return :gatsby if meta[:gatsby][:available]
96
+ return :dotnet if meta[:dotnet][:available]
97
+ return :barestatic if meta[:barestatic][:available]
98
+
99
+ :buildpacks18
100
+ end
101
+
102
+ def available_repo_kinds(repository_id:, branch:, credential:)
103
+ detections = {
104
+ dotnetruntimes: [],
105
+ gatsbyconfig: false,
106
+ csproj: false,
107
+
108
+ go: false,
109
+ ruby: false,
110
+ node: false,
111
+ python: false,
112
+ java: false,
113
+ php: false,
114
+ barestatic: false,
115
+ }
116
+ contents = fetch_contents(credential, repository_id, branch)
117
+ repo_contents = contents[:repo_contents]
118
+ detections[:dotnetruntimes] = repo_contents.filter_map do |f|
119
+ (f.name =~ /^(.+\.)?runtime\.json/ || f.name == 'runtime.template.json') && f.name
120
+ end
121
+ detections[:csproj] = repo_contents.filter_map do |f|
122
+ f.name =~ /^.+\.csproj/ && f.name
123
+ end
124
+ detections[:go] = has_go_files?(contents)
125
+
126
+ [[:ruby, ['Gemfile']],
127
+ [:node, ['package.json']],
128
+ [:python, ['requirements.txt', 'setup.py', 'Pipfile']],
129
+ [:java, ['pom.xml', 'pom.atom', 'pom.clj', 'pom.groovy', 'pom.rb', 'pom.scala', 'pom.yaml', 'pom.yml']],
130
+ [:php, ['composer.json', 'index.php']],
131
+ [:gatsbyconfig, ['gatsby-config.js']],
132
+ [:barestatic, ['index.html', 'index.htm', 'Default.htm']]].each do |lang|
133
+ detections[lang[0]] = repo_contents.filter_map do |f|
134
+ lang[1].include?(f.name)
135
+ end.present?
136
+ end
137
+ end
138
+
139
+ def filter_available_repo_kinds
140
+ kinds = AVAILABLE_KINDS.filter_map do |kind|
141
+ detection = kind[:detect].call(detections)
142
+
143
+ kind.merge(detection).except(:detect)
144
+ end.map { |kind| [kind[:name], kind.except(:name)] }.to_h
145
+
146
+ kinds.merge({ default: select_default_from(kinds) })
147
+ end
148
+
149
+ def fetch_contents(credential, repository_id, branch)
150
+ repo_contents = UffizziCore::Github::CredentialService.contents(credential, repository_id, ref: branch)
151
+ return filter_available_repo_kinds if repo_contents.empty?
152
+
153
+ if repo_contents.filter_map { |f| f.name == 'Godeps' }.present?
154
+ godeps_contents = UffizziCore::Github::CredentialService.contents(credential, repository_id, path: 'Godeps/', ref: branch)
155
+ end
156
+
157
+ if repo_contents.filter_map { |f| f.name == 'vendor' }.present? && godeps_contents.nil?
158
+ govendor_contents = UffizziCore::Github::CredentialService.contents(credential, repository_id, path: 'vendor/', ref: branch)
159
+ end
160
+
161
+ {
162
+ repo_contents: repo_contents,
163
+ godeps_contents: godeps_contents,
164
+ govendor_contents: govendor_contents,
165
+ }
166
+ end
167
+
168
+ def go(contents)
169
+ contents[:repo_contents].filter_map do |f|
170
+ ['go.mod', 'Gopkg.lock', 'glide.yaml'].include?(f.name)
171
+ end.present? || contents[:godeps_contents]&.filter_map do |f|
172
+ f.name == 'Godeps.json'
173
+ end.present? || contents[:govendor_contents]&.filter_map do |f|
174
+ f.name == 'vendor.json'
175
+ end.present?
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UffizziCore::ResponseService
4
+ def meta(collection)
5
+ {
6
+ total_count: collection.total_count,
7
+ current_page: collection.current_page,
8
+ per_page: collection.limit_value,
9
+ count: collection.to_a.count,
10
+ total_pages: collection.total_pages,
11
+ }
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::TemplateService
4
+ class << self
5
+ def valid_containers_memory_limit?(template)
6
+ containers_attributes = template.payload['containers_attributes']
7
+ container_memory_limit = template.project.account.container_memory_limit
8
+ return true if container_memory_limit.nil?
9
+
10
+ containers_attributes.all? { |container| container['memory_limit'].to_i <= container_memory_limit }
11
+ end
12
+
13
+ def valid_containers_memory_request?(template)
14
+ containers_attributes = template.payload['containers_attributes']
15
+ container_memory_limit = template.project.account.container_memory_limit
16
+ return true if container_memory_limit.nil?
17
+
18
+ containers_attributes.all? { |container| container['memory_request'].to_i <= container_memory_limit }
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UffizziCore::TokenService
4
+ class << self
5
+ def encode(payload)
6
+ JWT.encode(payload, Settings.rails.secret_key_base, 'HS256')
7
+ end
8
+
9
+ def decode(token)
10
+ JWT.decode(token, Settings.rails.secret_key_base, true, algorithm: 'HS256')
11
+ rescue JWT::DecodeError
12
+ nil
13
+ end
14
+
15
+ def generate
16
+ SecureRandom.hex
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::UserAccessService
4
+ attr_accessor :user_access_module
5
+
6
+ delegate :admin_access_to_account?, :developer_access_to_account?, :viewer_access_to_account?,
7
+ :admin_or_developer_access_to_account?, :any_access_to_account?, :admin_access_to_project?,
8
+ :developer_access_to_project?, :viewer_access_to_project?, :admin_or_developer_access_to_project?,
9
+ :any_access_to_project?, :global_admin?, to: :@user_access_module
10
+
11
+ def initialize(user_access_module)
12
+ @user_access_module = user_access_module
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UffizziCore::Converters
4
+ class << self
5
+ include ActionView::Helpers::NumberHelper
6
+
7
+ def deep_lower_camelize_keys(object)
8
+ case object
9
+ when Array
10
+ object.map do |element|
11
+ element.deep_transform_keys { |key| key.to_s.camelize(:lower) }
12
+ end
13
+ when Hash
14
+ object.deep_transform_keys { |key| key.to_s.camelize(:lower) }
15
+ else
16
+ object
17
+ end
18
+ end
19
+
20
+ def deep_underscore_keys(object)
21
+ case object
22
+ when Array
23
+ object.map do |element|
24
+ element.deep_transform_keys { |key| key.to_s.underscore }
25
+ end
26
+ when Hash
27
+ object.deep_transform_keys { |key| key.to_s.underscore }
28
+ else
29
+ object
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::EmailValidator < ActiveModel::EachValidator
4
+ EMAIL_REGEXP = /\A([^@\s<>]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i.freeze
5
+
6
+ def validate_each(record, attribute, value)
7
+ record.errors.add(attribute, (options[:message] || :invalid)) unless value&.match?(EMAIL_REGEXP)
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::EnvironmentVariableListValidator < ActiveModel::EachValidator
4
+ def validate_each(record, attribute, variables)
5
+ record.errors.add(attribute, :invalid) if variables.class != Array || !valid_variables?(variables)
6
+ end
7
+
8
+ def valid_variables?(variables)
9
+ variables.each do |variable|
10
+ return false if variable.class != Hash || !variable.key?('name') || variable['name'].nil? || !variable.key?('value')
11
+ end
12
+
13
+ true
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::ImageCommandArgsValidator < ActiveModel::EachValidator
4
+ def validate_each(record, attribute, command_args)
5
+ record.errors.add(attribute, :invalid) if !command_args.nil? && !valid_command_args?(command_args)
6
+ end
7
+
8
+ def valid_command_args?(raw_command_args)
9
+ return true if raw_command_args.empty?
10
+
11
+ begin
12
+ command_args = JSON.parse(raw_command_args)
13
+ rescue JSON::ParserError
14
+ return false
15
+ end
16
+
17
+ return false if command_args.class != Array || command_args.empty?
18
+
19
+ command_args.all? { |item| item.instance_of?(String) }
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rswag::Api.configure do |c|
4
+ # Specify a root folder where Swagger JSON files are located
5
+ # This is used by the Swagger middleware to serve requests for API descriptions
6
+ # NOTE: If you're using rswag-specs to generate Swagger, you'll need to ensure
7
+ # that it's configured to generate files in the same folder
8
+ c.swagger_root = "#{UffizziCore::Engine.root}/swagger"
9
+
10
+ # Inject a lamda function to alter the returned Swagger prior to serialization
11
+ # The function will have access to the rack env for the current request
12
+ # For example, you could leverage this to dynamically assign the "host" property
13
+ #
14
+ # c.swagger_filter = lambda { |swagger, env| swagger['host'] = env['HTTP_HOST'] }
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rswag::Ui.configure do |c|
4
+ # List the Swagger endpoints that you want to be documented through the swagger-ui
5
+ # The first parameter is the path (absolute or relative to the UI host) to the corresponding
6
+ # endpoint and the second is a title that will be displayed in the document selector
7
+ # NOTE: If you're using rspec-api to expose Swagger files (under swagger_root) as JSON or YAML endpoints,
8
+ # then the list below should correspond to the relative paths for those endpoints
9
+
10
+ c.swagger_endpoint('/api-docs/v1/swagger.json', 'API V1 Docs')
11
+
12
+ # Add Basic Auth in case your API is private
13
+ # c.basic_auth_enabled = true
14
+ # c.basic_auth_credentials 'username', 'password'
15
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'swagger_yard'
4
+
5
+ SwaggerYard.configure do |config|
6
+ config.api_version = '1.0'
7
+
8
+ config.title = 'Uffizzi docs'
9
+ config.description = 'Your API does this'
10
+
11
+ config.api_base_path = 'http://lvh.me:7000'
12
+
13
+ config.controller_path = File.expand_path('app/controllers/uffizzi_core/api/**/*', UffizziCore::Engine.root)
14
+ config.model_path = File.expand_path('app/models/uffizzi_core/**/*', UffizziCore::Engine.root)
15
+
16
+ config.include_private = false
17
+ end
@@ -0,0 +1,18 @@
1
+ en:
2
+ activerecord:
3
+ errors:
4
+ models:
5
+ uffizzi_core/project:
6
+ attributes:
7
+ secret:
8
+ not_found: There is no secret with name %{name}
9
+ uffizzi_core/credential:
10
+ attributes:
11
+ registry_url:
12
+ invalid_scheme: The protocol for the registry url is not specified
13
+ password:
14
+ password_blank: Password/Access Token can't be blank
15
+ username:
16
+ incorrect: We were unable to log you in to docker registry. Please verify that your username and password are correct.
17
+ type:
18
+ exist: Credential of that type already exist.
@@ -0,0 +1,61 @@
1
+ en:
2
+ github:
3
+ preview_url_message: |
4
+ **This branch has been deployed using Uffizzi.**
5
+ Preview URL:
6
+ https://%{preview_url}
7
+ View deployment details here:
8
+ https://%{deployment_url}
9
+ This is an automated comment. To turn off commenting, visit uffizzi.com.
10
+ invalid_compose_message: |
11
+ :exclamation: **Preview failed: invalid compose**
12
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Uffizzi was unable to deploy a preview of this pull request because the compose file in this branch is invalid.
13
+ compose:
14
+ unsupported_file: Unsupported compose file
15
+ invalid_file: Invalid compose file
16
+ invalid_config_option: Invalid config option '%{value}' - only [a-zA-Z0-9\._\-] characters are allowed
17
+ no_services: Service services has neither an image nor a build context specified. At least one must be provided.
18
+ no_ingress: Service ingress has not been defined.
19
+ invalid_image_value: Invalid image value '%{value}'
20
+ invalid_credential: Invalid credential '%{value}'
21
+ invalid_repo_type: Unsupported repo type
22
+ repo_not_found: The specified repository doesn't exist '%{name}'
23
+ ingress_port_not_specified: Ingress port not specified
24
+ ingress_service_not_found: Ingress service not found
25
+ invalid_ingress_service: Invalid ingress service '%{value}'
26
+ no_variable_name: Invalid environment variable 'name=%{name}' 'value=%{value}'
27
+ invalid_config: Invalid config value 'source=%{source}' 'target=%{target}'
28
+ invalid_port: Invalid port specification '%{value}'
29
+ invalid_memory_postfix: The specified value for memory '%{value}' should specify the units. The postfix should be one of the `b` `k` `m` `g` characters
30
+ invalid_memory_type: Memory '%{value}' contains an invalid type, it should be a string
31
+ invalid_memory_value: Invalid memory value '%{value}'
32
+ invalid_memory: The memory should be one of the `125m` `250m` `500m` `1000m` `2000m` `4000m` values
33
+ image_build_no_specified: Service %{value} has neither an image nor a build context specified. At least one must be provided.
34
+ build_context_no_specified: The context option should be specified
35
+ config_file_not_found: Config file not found '%{name}'
36
+ invalid_context: Invalid context value '%{value}'
37
+ invalid_bool_value: Invalid %{field} value '%{value}'. The value should be `true` or `false`
38
+ invalid_delete_after_postfix: The postfix of the delete_preview_after value should be `h`
39
+ invalid_integer: The specified value for %{option} should be an Integer type
40
+ invalid_string: The specified value for %{option} should be a String type
41
+ invalid_delete_after_min: Minimum delete_preview_after allowed is %{value}h
42
+ invalid_delete_after_max: Maximum delete_preview_after allowed is %{value}h
43
+ invalid_type: Unsupported type of '%{option}' option
44
+ empty_env_file: env_file contains an empty value
45
+ file_not_found: Couldn't find '%{path}' file
46
+ env_file_duplicates: env_file contains non-unique items '%{values}'
47
+ boolean_option: The service name %{value} must be a quoted string, i.e. '%{value}'.
48
+ config_file_option_empty: "'%{config_name}' has an empty file"
49
+ global_config_not_found: undefined config '%{config}'
50
+ invalid_branch: Branch '%{branch}' doesn't exist for repository '%{repository_url}'
51
+ repository_not_found: The specified repository doesn't exist '%{repository_url}'
52
+ build_context_unknown_repository: Compose repository is undefined
53
+ secret_name_blank: The specified name for '%{option}' secret can not be blank
54
+ secret_external: The specified secret '%{secret}' should be external
55
+ global_secret_not_found: undefined secret '%{secret}'
56
+ project_secret_not_found: Project secret '%{secret}' not found
57
+ continuous_preview_in_service_level: The option '%{option}' is not supported for service-level. Use 'x-uffizzi-continuous-preview' instead
58
+ file_already_exists: A compose file already exists for this project. Run 'uffizzi compose update' to update this file or 'uffizzi compose rm' to remove it. For more options, see 'uffizzi compose --help'"
59
+ secrets:
60
+ duplicates_exists: Secret with key %{secrets} already exist.
61
+ invalid_key_length: A secret key must be no longer than 256 characters.
data/config/routes.rb ADDED
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ UffizziCore::Engine.routes.draw do
4
+ mount Rswag::Api::Engine => '/api-docs'
5
+ mount Rswag::Ui::Engine => '/api-docs'
6
+
7
+ namespace :api, defaults: { format: :json } do
8
+ namespace :cli do
9
+ namespace :v1 do
10
+ resource :webhooks, only: [] do
11
+ post :docker_hub
12
+ post :github
13
+ post :azure
14
+ post :amazon
15
+ post :google
16
+ end
17
+
18
+ resources :projects, only: ['index'], param: :slug do
19
+ scope module: :projects do
20
+ resource :compose_file, only: ['show', 'create', 'destroy']
21
+ resources :deployments, only: ['index', 'show', 'create', 'destroy'] do
22
+ post :deploy_containers, on: :member
23
+ scope module: :deployments do
24
+ resources :activity_items, only: ['index']
25
+ resources :events, only: ['index']
26
+ resources :containers, only: ['index'], param: :name do
27
+ scope module: :containers do
28
+ resources :logs, only: ['index']
29
+ resources :builds, only: [] do
30
+ collection do
31
+ get :logs
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ resources :secrets, only: ['index', 'destroy'] do
39
+ collection do
40
+ post :bulk_create
41
+ end
42
+ end
43
+ end
44
+ end
45
+ resource :session, only: ['create', 'destroy']
46
+
47
+ resource :account, only: [] do
48
+ scope module: :account do
49
+ resources :credentials, only: ['create', 'destroy'], param: :type
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end