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.
- checksums.yaml +7 -0
- data/LICENSE +201 -0
- data/README.md +46 -0
- data/Rakefile +31 -0
- data/app/assets/config/uffizzi_core_manifest.js +1 -0
- data/app/assets/stylesheets/uffizzi_core/application.css +15 -0
- data/app/clients/uffizzi_core/amazon_registry_client.rb +18 -0
- data/app/clients/uffizzi_core/azure_registry_client/request_result.rb +5 -0
- data/app/clients/uffizzi_core/azure_registry_client.rb +42 -0
- data/app/clients/uffizzi_core/controller_client/request_result.rb +5 -0
- data/app/clients/uffizzi_core/controller_client.rb +106 -0
- data/app/clients/uffizzi_core/docker_hub_client/request_result.rb +7 -0
- data/app/clients/uffizzi_core/docker_hub_client.rb +139 -0
- data/app/clients/uffizzi_core/github/app_client.rb +19 -0
- data/app/clients/uffizzi_core/github/installation_client.rb +11 -0
- data/app/clients/uffizzi_core/github/user_client.rb +51 -0
- data/app/clients/uffizzi_core/google_registry_client/request_result.rb +5 -0
- data/app/clients/uffizzi_core/google_registry_client.rb +42 -0
- data/app/contexts/uffizzi_core/base_context.rb +12 -0
- data/app/contexts/uffizzi_core/project_context.rb +13 -0
- data/app/contexts/uffizzi_core/webhooks_context.rb +9 -0
- data/app/controllers/concerns/uffizzi_core/auth_management.rb +23 -0
- data/app/controllers/concerns/uffizzi_core/authorization_concern.rb +38 -0
- data/app/controllers/concerns/uffizzi_core/dependency_injection_concern.rb +19 -0
- data/app/controllers/uffizzi_core/api/cli/v1/account/application_controller.rb +7 -0
- data/app/controllers/uffizzi_core/api/cli/v1/account/credentials_controller.rb +55 -0
- data/app/controllers/uffizzi_core/api/cli/v1/application_controller.rb +5 -0
- data/app/controllers/uffizzi_core/api/cli/v1/projects/application_controller.rb +11 -0
- data/app/controllers/uffizzi_core/api/cli/v1/projects/compose_files_controller.rb +93 -0
- data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/activity_items_controller.rb +36 -0
- data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/application_controller.rb +7 -0
- data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/containers/application_controller.rb +8 -0
- data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/containers/logs_controller.rb +27 -0
- data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/containers_controller.rb +24 -0
- data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/events_controller.rb +29 -0
- data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments_controller.rb +148 -0
- data/app/controllers/uffizzi_core/api/cli/v1/projects/secrets_controller.rb +69 -0
- data/app/controllers/uffizzi_core/api/cli/v1/projects_controller.rb +19 -0
- data/app/controllers/uffizzi_core/api/cli/v1/sessions_controller.rb +43 -0
- data/app/controllers/uffizzi_core/application_controller.rb +51 -0
- data/app/errors/uffizzi_core/compose_file/build_error.rb +4 -0
- data/app/errors/uffizzi_core/compose_file/credential_error.rb +4 -0
- data/app/errors/uffizzi_core/compose_file/not_found_error.rb +4 -0
- data/app/errors/uffizzi_core/compose_file/parse_error.rb +4 -0
- data/app/errors/uffizzi_core/compose_file/secrets_error.rb +4 -0
- data/app/errors/uffizzi_core/deployment_not_found_error.rb +10 -0
- data/app/forms/uffizzi_core/api/cli/v1/account/credential/create_form.rb +26 -0
- data/app/forms/uffizzi_core/api/cli/v1/compose_file/check_credentials_form.rb +21 -0
- data/app/forms/uffizzi_core/api/cli/v1/compose_file/cli_form.rb +39 -0
- data/app/forms/uffizzi_core/api/cli/v1/compose_file/create_form.rb +13 -0
- data/app/forms/uffizzi_core/api/cli/v1/compose_file/template_form.rb +44 -0
- data/app/forms/uffizzi_core/api/cli/v1/compose_file/update_form.rb +9 -0
- data/app/forms/uffizzi_core/api/cli/v1/config_file/create_form.rb +11 -0
- data/app/forms/uffizzi_core/api/cli/v1/deployment/create_form.rb +91 -0
- data/app/forms/uffizzi_core/api/cli/v1/project/delete_secret_form.rb +27 -0
- data/app/forms/uffizzi_core/api/cli/v1/project/update_form.rb +40 -0
- data/app/forms/uffizzi_core/api/cli/v1/session_create_form.rb +29 -0
- data/app/forms/uffizzi_core/api/cli/v1/template/create_form.rb +65 -0
- data/app/forms/uffizzi_core/application_form.rb +11 -0
- data/app/forms/uffizzi_core/application_form_without_active_record.rb +17 -0
- data/app/forms/uffizzi_core/mass_assignment_control_concern.rb +22 -0
- data/app/helpers/uffizzi_core/application_helper.rb +6 -0
- data/app/jobs/uffizzi_core/account/create_credential_job.rb +10 -0
- data/app/jobs/uffizzi_core/activity_item/docker/update_digest_job.rb +11 -0
- data/app/jobs/uffizzi_core/application_job.rb +7 -0
- data/app/jobs/uffizzi_core/config_file/apply_job.rb +31 -0
- data/app/jobs/uffizzi_core/credential/docker_hub/create_webhook_job.rb +15 -0
- data/app/jobs/uffizzi_core/deployment/create_credential_job.rb +32 -0
- data/app/jobs/uffizzi_core/deployment/create_credentials_job.rb +17 -0
- data/app/jobs/uffizzi_core/deployment/create_job.rb +15 -0
- data/app/jobs/uffizzi_core/deployment/create_webhooks_job.rb +13 -0
- data/app/jobs/uffizzi_core/deployment/delete_credential_job.rb +13 -0
- data/app/jobs/uffizzi_core/deployment/delete_job.rb +11 -0
- data/app/jobs/uffizzi_core/deployment/deploy_containers_job.rb +27 -0
- data/app/jobs/uffizzi_core/deployment/manage_deploy_activity_item_job.rb +19 -0
- data/app/jobs/uffizzi_core/deployment/send_github_preview_message_job.rb +13 -0
- data/app/lib/uffizzi_core/rbac/user_access_service.rb +21 -0
- data/app/mailers/uffizzi_core/application_mailer.rb +8 -0
- data/app/models/concerns/uffizzi_core/hashid_concern.rb +25 -0
- data/app/models/concerns/uffizzi_core/state_machine_concern.rb +16 -0
- data/app/models/uffizzi_core/account.rb +101 -0
- data/app/models/uffizzi_core/activity_item/docker.rb +4 -0
- data/app/models/uffizzi_core/activity_item/github.rb +4 -0
- data/app/models/uffizzi_core/activity_item/memory_limit.rb +4 -0
- data/app/models/uffizzi_core/activity_item.rb +58 -0
- data/app/models/uffizzi_core/application_record.rb +7 -0
- data/app/models/uffizzi_core/build.rb +39 -0
- data/app/models/uffizzi_core/comment.rb +16 -0
- data/app/models/uffizzi_core/compose_file.rb +57 -0
- data/app/models/uffizzi_core/config_file.rb +24 -0
- data/app/models/uffizzi_core/container.rb +100 -0
- data/app/models/uffizzi_core/container_config_file.rb +8 -0
- data/app/models/uffizzi_core/continuous_preview.rb +4 -0
- data/app/models/uffizzi_core/coupon.rb +5 -0
- data/app/models/uffizzi_core/credential/amazon.rb +4 -0
- data/app/models/uffizzi_core/credential/azure.rb +4 -0
- data/app/models/uffizzi_core/credential/docker_hub.rb +4 -0
- data/app/models/uffizzi_core/credential/github.rb +4 -0
- data/app/models/uffizzi_core/credential/google.rb +4 -0
- data/app/models/uffizzi_core/credential.rb +64 -0
- data/app/models/uffizzi_core/database.rb +4 -0
- data/app/models/uffizzi_core/database_offering.rb +4 -0
- data/app/models/uffizzi_core/deployment.rb +77 -0
- data/app/models/uffizzi_core/event.rb +13 -0
- data/app/models/uffizzi_core/invitation.rb +27 -0
- data/app/models/uffizzi_core/membership.rb +16 -0
- data/app/models/uffizzi_core/payment.rb +11 -0
- data/app/models/uffizzi_core/price.rb +9 -0
- data/app/models/uffizzi_core/product.rb +11 -0
- data/app/models/uffizzi_core/project.rb +66 -0
- data/app/models/uffizzi_core/rating.rb +20 -0
- data/app/models/uffizzi_core/repo/amazon.rb +4 -0
- data/app/models/uffizzi_core/repo/azure.rb +4 -0
- data/app/models/uffizzi_core/repo/docker_hub.rb +4 -0
- data/app/models/uffizzi_core/repo/github.rb +4 -0
- data/app/models/uffizzi_core/repo/google.rb +4 -0
- data/app/models/uffizzi_core/repo.rb +39 -0
- data/app/models/uffizzi_core/role.rb +17 -0
- data/app/models/uffizzi_core/template.rb +19 -0
- data/app/models/uffizzi_core/user.rb +62 -0
- data/app/models/uffizzi_core/user_project.rb +14 -0
- data/app/policies/uffizzi_core/api/cli/v1/account/credentials_policy.rb +11 -0
- data/app/policies/uffizzi_core/api/cli/v1/projects/compose_files_policy.rb +15 -0
- data/app/policies/uffizzi_core/api/cli/v1/projects/deployments/activity_items_policy.rb +7 -0
- data/app/policies/uffizzi_core/api/cli/v1/projects/deployments/containers_policy.rb +7 -0
- data/app/policies/uffizzi_core/api/cli/v1/projects/deployments/events_policy.rb +7 -0
- data/app/policies/uffizzi_core/api/cli/v1/projects/deployments_policy.rb +23 -0
- data/app/policies/uffizzi_core/api/cli/v1/projects/secrets_policy.rb +15 -0
- data/app/policies/uffizzi_core/api/cli/v1/projects_policy.rb +7 -0
- data/app/policies/uffizzi_core/application_policy.rb +12 -0
- data/app/repositories/uffizzi_core/activity_item_repo.rb +9 -0
- data/app/repositories/uffizzi_core/basic_order_repo.rb +11 -0
- data/app/repositories/uffizzi_core/build_repo.rb +23 -0
- data/app/repositories/uffizzi_core/comment_repo.rb +11 -0
- data/app/repositories/uffizzi_core/compose_file_repo.rb +11 -0
- data/app/repositories/uffizzi_core/config_file_repo.rb +40 -0
- data/app/repositories/uffizzi_core/container_repo.rb +25 -0
- data/app/repositories/uffizzi_core/credential_repo.rb +36 -0
- data/app/repositories/uffizzi_core/deployment_repo.rb +23 -0
- data/app/repositories/uffizzi_core/event_repo.rb +9 -0
- data/app/repositories/uffizzi_core/membership_repo.rb +10 -0
- data/app/repositories/uffizzi_core/price_repo.rb +11 -0
- data/app/repositories/uffizzi_core/product_repo.rb +11 -0
- data/app/repositories/uffizzi_core/project_repo.rb +10 -0
- data/app/repositories/uffizzi_core/repo_repo.rb +10 -0
- data/app/repositories/uffizzi_core/template_repo.rb +87 -0
- data/app/repositories/uffizzi_core/usage_repo.rb +9 -0
- data/app/repositories/uffizzi_core/user_repo.rb +11 -0
- data/app/responders/uffizzi_core/json_responder.rb +13 -0
- data/app/serializers/uffizzi_core/api/cli/v1/account/credential_serializer.rb +9 -0
- data/app/serializers/uffizzi_core/api/cli/v1/project_serializer.rb +7 -0
- data/app/serializers/uffizzi_core/api/cli/v1/projects/compose_file_serializer.rb +7 -0
- data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/container_serializer.rb +23 -0
- data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/user_serializer.rb +11 -0
- data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer.rb +74 -0
- data/app/serializers/uffizzi_core/api/cli/v1/projects/deployments/activity_item_serializer.rb +24 -0
- data/app/serializers/uffizzi_core/api/cli/v1/projects/deployments/container_serializer/container_config_file_serializer/config_file_serializer.rb +6 -0
- data/app/serializers/uffizzi_core/api/cli/v1/projects/deployments/container_serializer/container_config_file_serializer.rb +7 -0
- data/app/serializers/uffizzi_core/api/cli/v1/projects/deployments/container_serializer.rb +30 -0
- data/app/serializers/uffizzi_core/api/cli/v1/user_serializer/account_serializer.rb +5 -0
- data/app/serializers/uffizzi_core/api/cli/v1/user_serializer.rb +7 -0
- data/app/serializers/uffizzi_core/base_serializer.rb +7 -0
- data/app/serializers/uffizzi_core/controller/create_credential/credential_serializer.rb +17 -0
- data/app/serializers/uffizzi_core/controller/create_deployment/deployment_serializer.rb +5 -0
- data/app/serializers/uffizzi_core/controller/deploy_containers/container_serializer.rb +53 -0
- data/app/serializers/uffizzi_core/controller/deploy_containers/credential_serializer.rb +5 -0
- data/app/services/uffizzi_core/account_service.rb +21 -0
- data/app/services/uffizzi_core/activity_item_service.rb +98 -0
- data/app/services/uffizzi_core/amazon/credential_service.rb +31 -0
- data/app/services/uffizzi_core/amazon_service.rb +45 -0
- data/app/services/uffizzi_core/azure/credential_service.rb +18 -0
- data/app/services/uffizzi_core/cli/compose_file_service.rb +203 -0
- data/app/services/uffizzi_core/compose_file/builders/config_files_builder_service.rb +31 -0
- data/app/services/uffizzi_core/compose_file/builders/container_builder_service.rb +225 -0
- data/app/services/uffizzi_core/compose_file/builders/docker_repo_builder_service.rb +25 -0
- data/app/services/uffizzi_core/compose_file/builders/github_repo_builder_service.rb +59 -0
- data/app/services/uffizzi_core/compose_file/builders/template_builder_service.rb +45 -0
- data/app/services/uffizzi_core/compose_file/builders/variables_builder_service.rb +58 -0
- data/app/services/uffizzi_core/compose_file/config_files_service.rb +52 -0
- data/app/services/uffizzi_core/compose_file/config_option_service.rb +37 -0
- data/app/services/uffizzi_core/compose_file/configs_options_service.rb +26 -0
- data/app/services/uffizzi_core/compose_file/container_service.rb +64 -0
- data/app/services/uffizzi_core/compose_file/continuous_preview_options_service.rb +57 -0
- data/app/services/uffizzi_core/compose_file/dependencies_service.rb +55 -0
- data/app/services/uffizzi_core/compose_file/errors_service.rb +46 -0
- data/app/services/uffizzi_core/compose_file/github_dependencies_service.rb +38 -0
- data/app/services/uffizzi_core/compose_file/ingress_options_service.rb +49 -0
- data/app/services/uffizzi_core/compose_file/secrets_options_service.rb +28 -0
- data/app/services/uffizzi_core/compose_file/services_options/build_service.rb +93 -0
- data/app/services/uffizzi_core/compose_file/services_options/command_service.rb +18 -0
- data/app/services/uffizzi_core/compose_file/services_options/configs_service.rb +51 -0
- data/app/services/uffizzi_core/compose_file/services_options/deploy_service.rb +44 -0
- data/app/services/uffizzi_core/compose_file/services_options/entrypoint_service.rb +18 -0
- data/app/services/uffizzi_core/compose_file/services_options/env_file_service.rb +34 -0
- data/app/services/uffizzi_core/compose_file/services_options/environment_service.rb +20 -0
- data/app/services/uffizzi_core/compose_file/services_options/image_service.rb +89 -0
- data/app/services/uffizzi_core/compose_file/services_options/secrets_service.rb +35 -0
- data/app/services/uffizzi_core/compose_file/services_options_service.rb +55 -0
- data/app/services/uffizzi_core/compose_file/template_service.rb +55 -0
- data/app/services/uffizzi_core/compose_file/update_service.rb +29 -0
- data/app/services/uffizzi_core/compose_file/variables_service.rb +25 -0
- data/app/services/uffizzi_core/compose_file_service.rb +33 -0
- data/app/services/uffizzi_core/container_service.rb +57 -0
- data/app/services/uffizzi_core/controller_service.rb +80 -0
- data/app/services/uffizzi_core/credential_service.rb +44 -0
- data/app/services/uffizzi_core/deployment_service.rb +274 -0
- data/app/services/uffizzi_core/docker_hub/credential_service.rb +15 -0
- data/app/services/uffizzi_core/docker_hub_service.rb +77 -0
- data/app/services/uffizzi_core/github/app_service.rb +51 -0
- data/app/services/uffizzi_core/github/credential_service.rb +124 -0
- data/app/services/uffizzi_core/github/message_service.rb +20 -0
- data/app/services/uffizzi_core/github_service.rb +28 -0
- data/app/services/uffizzi_core/google/credential_service.rb +18 -0
- data/app/services/uffizzi_core/logs_service.rb +33 -0
- data/app/services/uffizzi_core/manage_activity_items_service.rb +166 -0
- data/app/services/uffizzi_core/project_service.rb +38 -0
- data/app/services/uffizzi_core/repo_service.rb +178 -0
- data/app/services/uffizzi_core/response_service.rb +13 -0
- data/app/services/uffizzi_core/template_service.rb +21 -0
- data/app/services/uffizzi_core/token_service.rb +19 -0
- data/app/services/uffizzi_core/user_access_service.rb +14 -0
- data/app/utils/uffizzi_core/converters.rb +33 -0
- data/app/validators/uffizzi_core/email_validator.rb +9 -0
- data/app/validators/uffizzi_core/environment_variable_list_validator.rb +15 -0
- data/app/validators/uffizzi_core/image_command_args_validator.rb +21 -0
- data/config/initializers/rswag_api.rb +15 -0
- data/config/initializers/rswag_ui.rb +15 -0
- data/config/initializers/swagger_yard.rb +17 -0
- data/config/locales/en.activerecord.yml +18 -0
- data/config/locales/en.yml +61 -0
- data/config/routes.rb +55 -0
- data/db/migrate/20220218121438_create_uffizzi_core_tables.rb +375 -0
- data/db/migrate/20220325113342_add_name_to_uffizzi_containers.rb +7 -0
- data/db/seeds.rb +16 -0
- data/lib/tasks/uffizzi_core_tasks.rake +14 -0
- data/lib/uffizzi_core/engine.rb +15 -0
- data/lib/uffizzi_core/version.rb +5 -0
- data/lib/uffizzi_core.rb +60 -0
- data/swagger/v1/swagger.json +1278 -0
- 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
|
+
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
|