uffizzi_core 0.1.11 → 0.1.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -0
  3. data/app/controllers/uffizzi_core/api/cli/v1/account/credentials_controller.rb +3 -3
  4. data/app/controllers/uffizzi_core/api/cli/v1/projects_controller.rb +68 -2
  5. data/app/forms/uffizzi_core/api/cli/v1/deployment/create_form.rb +1 -0
  6. data/app/forms/uffizzi_core/api/cli/v1/project/create_form.rb +7 -0
  7. data/app/lib/uffizzi_core/concerns/models/activity_item.rb +39 -0
  8. data/app/lib/uffizzi_core/concerns/models/credential.rb +65 -0
  9. data/app/lib/uffizzi_core/concerns/models/repo.rb +33 -0
  10. data/app/lib/uffizzi_core/rbac/user_access_service.rb +24 -0
  11. data/app/models/uffizzi_core/project.rb +9 -2
  12. data/app/policies/uffizzi_core/api/cli/v1/projects_policy.rb +12 -0
  13. data/app/serializers/uffizzi_core/api/cli/v1/project_serializer/compose_file_serializer.rb +7 -0
  14. data/app/serializers/uffizzi_core/api/cli/v1/project_serializer/deployment_serializer.rb +13 -0
  15. data/app/serializers/uffizzi_core/api/cli/v1/project_serializer.rb +24 -1
  16. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployment_serializer/container_serializer.rb +2 -1
  17. data/app/serializers/uffizzi_core/api/cli/v1/projects/deployments/container_serializer.rb +1 -1
  18. data/app/serializers/uffizzi_core/api/cli/v1/short_project_serializer.rb +7 -0
  19. data/app/serializers/uffizzi_core/controller/deploy_containers/container_serializer.rb +16 -1
  20. data/app/services/uffizzi_core/compose_file/builders/container_builder_service.rb +11 -7
  21. data/app/services/uffizzi_core/compose_file/config_option_service.rb +4 -0
  22. data/app/services/uffizzi_core/compose_file/parsers/services/healthcheck_parser_service.rb +73 -0
  23. data/app/services/uffizzi_core/compose_file/services_options_service.rb +2 -0
  24. data/app/services/uffizzi_core/compose_file/template_service.rb +4 -4
  25. data/app/services/uffizzi_core/compose_file_service.rb +1 -1
  26. data/app/services/uffizzi_core/deployment_service.rb +17 -5
  27. data/app/services/uffizzi_core/manage_activity_items_service.rb +1 -1
  28. data/app/services/uffizzi_core/project_service.rb +10 -0
  29. data/app/services/uffizzi_core/starter_template_service.rb +200 -0
  30. data/app/services/uffizzi_core/user_generator_service.rb +11 -5
  31. data/config/locales/en.yml +2 -0
  32. data/config/routes.rb +11 -1
  33. data/db/migrate/20220419074956_add_health_check_to_containers.rb +7 -0
  34. data/lib/tasks/uffizzi_core_tasks.rake +1 -1
  35. data/lib/uffizzi_core/version.rb +1 -1
  36. data/swagger/v1/swagger.json +174 -2
  37. metadata +12 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 48e413ec49645c1e18d15251bcfa9ceaf94309be078fd46befbfd97894d9318e
4
- data.tar.gz: 213cd12f3c9216b851ccd16c44562da68c954a03f126fd35ec683119ee7b8755
3
+ metadata.gz: 43f66c059196fdf90a87f740f396bf781294f4dab94c221f38abc58caef7f141
4
+ data.tar.gz: 3f8aec775f29147cdc79b115401a28414ac19ee9146b9226ea62f5deb0de9083
5
5
  SHA512:
6
- metadata.gz: 339656968a5609d9674536a6bd36518f2efb33afe30bf77ef2c56d158fe3b1b7a9f27da8dd76dcc8c1f35ad5624121a2914482d296b0b2e5afe9025735dda974
7
- data.tar.gz: b5369f15696f2e011b1be386c1ee1b4660a0e5733e09030d0af8095612337cf544e2be0adfce7b3410f0338bd64e7e0d479a0f0f779360d9c99eb6990261670f
6
+ metadata.gz: 4d90a4d0a13b2d7e899573c8484d6355d751a81bd9648443211b4fa4155f439ae40993a4f3dd18c2ec5079bb183093f0f78b7800d24f96d693a98b3ef9c81a48
7
+ data.tar.gz: a7dcc2e613d8d5293c070d66f4c1366534c0077c8d5d588906be93b389a51bb88c2951c9db2b68c5236e90933da51af775ae00516afbc34cd6f8c7148ce5bb51
data/README.md CHANGED
@@ -44,3 +44,9 @@ Or install it yourself as:
44
44
  ```bash
45
45
  $ gem install uffizzi_core
46
46
  ```
47
+
48
+ ## Migrations
49
+ After adding a new migration, ru the following command:
50
+ ```
51
+ rake uffizzi_core:install
52
+ ```
@@ -15,7 +15,6 @@ class UffizziCore::Api::Cli::V1::Account::CredentialsController < UffizziCore::A
15
15
  render json: { credentials: credentials }, status: :ok
16
16
  end
17
17
 
18
- # rubocop:disable Layout/LineLength
19
18
  # Create account credential
20
19
  #
21
20
  # @path [POST] /api/cli/v1/account/credentials
@@ -25,8 +24,9 @@ class UffizziCore::Api::Cli::V1::Account::CredentialsController < UffizziCore::A
25
24
  # @response [object<errors>] 422 Unprocessable entity
26
25
  #
27
26
  # @example
28
- # type can be one of UffizziCore::Credential::Amazon, UffizziCore::Credential::Azure, UffizziCore::Credential::DockerHub, UffizziCore::Credential::Google, UffizziCore::Credential::GithubContainerRegistry
29
- # rubocop:enable Layout/LineLength
27
+ # type can be one of UffizziCore::Credential::Amazon, UffizziCore::Credential::Azure,
28
+ # UffizziCore::Credential::DockerHub, UffizziCore::Credential::Google, UffizziCore::Credential::GithubContainerRegistry
29
+
30
30
  def create
31
31
  credential_form = UffizziCore::Api::Cli::V1::Account::Credential::CreateForm.new
32
32
  credential_form.assign_attributes(credential_params)
@@ -9,11 +9,77 @@ class UffizziCore::Api::Cli::V1::ProjectsController < UffizziCore::Api::Cli::V1:
9
9
  #
10
10
  # @path [GET] /api/cli/v1/projects
11
11
  #
12
- # @response [object<projects: Array<object<slug: string>> >] 200 OK
12
+ # @response [object<projects: Array<object<slug: string, name: string>> >] 200 OK
13
13
  # @response 401 Not authorized
14
14
  def index
15
15
  projects = current_user.projects.active.order(updated_at: :desc)
16
16
 
17
- respond_with projects
17
+ respond_with projects, each_serializer: UffizziCore::Api::Cli::V1::ShortProjectSerializer
18
+ end
19
+
20
+ # Get a project by slug
21
+ #
22
+ # @path [GET] /api/cli/v1/projects/{slug}
23
+ #
24
+ # @response <object< project: Project>> 200 OK
25
+ # @response 404 Not Found
26
+ # @response 401 Not authorized
27
+ def show
28
+ project = current_user.projects.find_by!(slug: params[:slug])
29
+
30
+ respond_with project
31
+ end
32
+
33
+ # Create a project
34
+ #
35
+ # @path [POST] /api/cli/v1/projects
36
+ # @parameter params(required,body) [object<name: string, slug: string, description: string>]
37
+ #
38
+ # @response <object< project: Project>> 200 OK
39
+ # @response 404 Not Found
40
+ # @response 401 Not authorized
41
+ # @response [object<errors: object<password: string >>] 422 Unprocessable entity
42
+
43
+ def create
44
+ project_form = UffizziCore::Api::Cli::V1::Project::CreateForm.new(project_params)
45
+ project_form.account = current_user.organizational_account
46
+
47
+ if project_form.save
48
+ current_membership = current_user.memberships.find_by(account: current_user.organizational_account)
49
+ user_projects = []
50
+
51
+ if current_membership.developer?
52
+ user_projects << { project: project_form, user: current_user, role: UffizziCore::UserProject.role.developer }
53
+ end
54
+
55
+ current_user.organizational_account.memberships.where(role: UffizziCore::Membership.role.admin).map do |membership|
56
+ user_projects << { project: project_form, user: membership.user, role: UffizziCore::UserProject.role.admin }
57
+ end
58
+
59
+ UffizziCore::UserProject.create!(user_projects)
60
+ end
61
+
62
+ respond_with project_form
63
+ end
64
+
65
+ # Delete a project
66
+ #
67
+ # @path [DELETE] /api/cli/v1/projects/{slug}
68
+ #
69
+ # @response 204 No content
70
+ # @response 404 Not Found
71
+ # @response 401 Not authorized
72
+
73
+ def destroy
74
+ project = current_user.organizational_account.active_projects.find_by!(slug: params[:slug])
75
+ project.disable!
76
+
77
+ head :no_content
78
+ end
79
+
80
+ private
81
+
82
+ def project_params
83
+ params.require(:project)
18
84
  end
19
85
  end
@@ -16,6 +16,7 @@ class UffizziCore::Api::Cli::V1::Deployment::CreateForm < UffizziCore::Deploymen
16
16
  :command,
17
17
  :receive_incoming_requests,
18
18
  :continuously_deploy,
19
+ { healthcheck: {} },
19
20
  { variables: [:name, :value],
20
21
  secret_variables: [:name, :value],
21
22
  repo_attributes: [
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::Project::CreateForm < UffizziCore::Project
4
+ include UffizziCore::ApplicationForm
5
+
6
+ permit :name, :slug, :description
7
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UffizziCore::Concerns::Models::ActivityItem
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ include UffizziCore::ActivityItemRepo
8
+
9
+ self.table_name = UffizziCore.table_names[:activity_items]
10
+
11
+ belongs_to :deployment
12
+ belongs_to :container
13
+ belongs_to :build, optional: true
14
+
15
+ has_many :events, dependent: :destroy
16
+
17
+ scope :docker, -> {
18
+ where(type: UffizziCore::ActivityItem::Docker.name)
19
+ }
20
+
21
+ scope :github, -> {
22
+ where(type: UffizziCore::ActivityItem::Github.name)
23
+ }
24
+
25
+ def docker?
26
+ type == UffizziCore::ActivityItem::Docker.name
27
+ end
28
+
29
+ def image
30
+ [namespace, name].compact.join('/')
31
+ end
32
+
33
+ def full_image
34
+ return "#{image}:#{tag}" if docker?
35
+
36
+ ''
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UffizziCore::Concerns::Models::Credential
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ include AASM
8
+ include UffizziCore::CredentialRepo
9
+
10
+ self.table_name = UffizziCore.table_names[:credentials]
11
+
12
+ belongs_to :account
13
+
14
+ before_destroy :remove_token
15
+
16
+ validates :registry_url, presence: true
17
+
18
+ aasm :state, column: :state do
19
+ state :not_connected, initial: true
20
+ state :active
21
+ state :unauthorized
22
+
23
+ event :activate do
24
+ transitions from: [:not_connected, :unauthorized], to: :active
25
+ end
26
+
27
+ event :unauthorize do
28
+ transitions from: [:not_connected, :active], to: :unauthorized
29
+ end
30
+ end
31
+
32
+ def github_container_registry?
33
+ type == UffizziCore::Credential::GithubContainerRegistry.name
34
+ end
35
+
36
+ def docker_hub?
37
+ type == UffizziCore::Credential::DockerHub.name
38
+ end
39
+
40
+ def azure?
41
+ type == UffizziCore::Credential::Azure.name
42
+ end
43
+
44
+ def google?
45
+ type == UffizziCore::Credential::Google.name
46
+ end
47
+
48
+ def amazon?
49
+ type == UffizziCore::Credential::Amazon.name
50
+ end
51
+
52
+ private
53
+
54
+ def remove_token
55
+ account.projects.find_each do |project|
56
+ project.deployments.find_each do |deployment|
57
+ containers = deployment.containers
58
+ attributes = { continuously_deploy: UffizziCore::Container::STATE_DISABLED }
59
+
60
+ containers.with_docker_hub_repo.update_all(attributes) if docker_hub?
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UffizziCore::Concerns::Models::Repo
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ extend Enumerize
8
+ include UffizziCore::RepoRepo
9
+
10
+ self.table_name = UffizziCore.table_names[:repos]
11
+
12
+ enumerize :kind, in: [:buildpacks18, :dockerfile, :dotnet, :gatsby, :barestatic], predicates: true
13
+
14
+ belongs_to :project
15
+ has_one :container, inverse_of: :repo, dependent: :destroy
16
+ has_many :builds, dependent: :destroy
17
+
18
+ validates :dockerfile_path, presence: true, if: :dockerfile?
19
+ validates :delete_preview_after, numericality: { greater_than: 0, only_integer: true }, allow_nil: true
20
+
21
+ def docker_hub?
22
+ type == UffizziCore::Repo::DockerHub.name
23
+ end
24
+
25
+ def azure?
26
+ type == UffizziCore::Repo::Azure.name
27
+ end
28
+
29
+ def google?
30
+ type == UffizziCore::Repo::Google.name
31
+ end
32
+ end
33
+ end
@@ -6,10 +6,34 @@ module UffizziCore::Rbac::UserAccessService
6
6
  true
7
7
  end
8
8
 
9
+ def developer_access_to_account?(_user, _account)
10
+ true
11
+ end
12
+
13
+ def viewer_access_to_account?(_user, _account)
14
+ true
15
+ end
16
+
17
+ def admin_or_developer_access_to_account?(_user, _account)
18
+ true
19
+ end
20
+
9
21
  def any_access_to_account?(_user, _account)
10
22
  true
11
23
  end
12
24
 
25
+ def admin_access_to_project?(_user, _project)
26
+ true
27
+ end
28
+
29
+ def developer_access_to_project?(_user, _project)
30
+ true
31
+ end
32
+
33
+ def viewer_access_to_project?(_user, _project)
34
+ true
35
+ end
36
+
13
37
  def admin_or_developer_access_to_project?(_user, _project)
14
38
  true
15
39
  end
@@ -1,7 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # @model
3
+ # @model Project
4
4
  # @property slug [string]
5
+ # @property name [string]
6
+ # @property description [string]
7
+ # @property created_at [date-time]
8
+ # @property secrets [string]
9
+ # @property default_compose [object<source: string>]
10
+ # @property deployments [object<id: integer, domain: string>]
5
11
 
6
12
  class UffizziCore::Project < UffizziCore::ApplicationRecord
7
13
  include AASM
@@ -23,7 +29,8 @@ class UffizziCore::Project < UffizziCore::ApplicationRecord
23
29
  has_many :compose_files, dependent: :destroy
24
30
  has_many :secrets, dependent: :destroy, as: :resource
25
31
 
26
- validates :name, presence: true, uniqueness: { scope: :account }
32
+ validates :name, presence: true, uniqueness: { scope: :account, message: 'Name already exists' }
33
+ validates :slug, presence: true, uniqueness: { message: 'Project slug already taken' }
27
34
 
28
35
  aasm(:state) do
29
36
  state :active, initial: true
@@ -4,4 +4,16 @@ class UffizziCore::Api::Cli::V1::ProjectsPolicy < UffizziCore::ApplicationPolicy
4
4
  def index?
5
5
  context.user_access_module.any_access_to_account?(context.user, context.account)
6
6
  end
7
+
8
+ def show?
9
+ context.user_access_module.any_access_to_account?(context.user, context.account)
10
+ end
11
+
12
+ def create?
13
+ context.user_access_module.admin_or_developer_access_to_account?(context.user, context.account)
14
+ end
15
+
16
+ def destroy?
17
+ context.user_access_module.admin_or_developer_access_to_account?(context.user, context.account)
18
+ end
7
19
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::ProjectSerializer::ComposeFileSerializer < UffizziCore::BaseSerializer
4
+ type :compose_file
5
+
6
+ attributes :source
7
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::ProjectSerializer::DeploymentSerializer < UffizziCore::BaseSerializer
4
+ type :deployment
5
+
6
+ attributes :id,
7
+ :preview_url,
8
+ :state
9
+
10
+ def preview_url
11
+ UffizziCore::DeploymentService.build_preview_url(object)
12
+ end
13
+ end
@@ -2,6 +2,29 @@
2
2
 
3
3
  class UffizziCore::Api::Cli::V1::ProjectSerializer < UffizziCore::BaseSerializer
4
4
  type :project
5
+ has_many :deployments
6
+ has_many :secrets
7
+ has_one :default_compose
5
8
 
6
- attributes :slug
9
+ attributes :name,
10
+ :slug,
11
+ :description,
12
+ :created_at
13
+
14
+ def default_compose
15
+ object.compose_files.main.first
16
+ end
17
+
18
+ def deployments
19
+ object.deployments.active.map do |deployment|
20
+ deployment.state = UffizziCore::DeploymentService.failed?(deployment) ? 'failed' : 'active'
21
+ deployment
22
+ end
23
+ end
24
+
25
+ def secrets
26
+ return [] unless object.secrets
27
+
28
+ object.secrets.map(&:name)
29
+ end
7
30
  end
@@ -19,7 +19,8 @@ class UffizziCore::Api::Cli::V1::Projects::DeploymentSerializer::ContainerSerial
19
19
  :public,
20
20
  :repo_id,
21
21
  :continuously_deploy,
22
- :receive_incoming_requests
22
+ :receive_incoming_requests,
23
+ :healthcheck
23
24
 
24
25
  def secret_variables
25
26
  return unless object.secret_variables.present?
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UffizziCore::Api::Cli::V1::Projects::Deployments::ContainerSerializer < UffizziCore::BaseSerializer
4
- attributes :id, :name, :memory_limit, :memory_request, :continuously_deploy, :variables, :secret_variables
4
+ attributes :id, :name, :memory_limit, :memory_request, :continuously_deploy, :variables, :secret_variables, :healthcheck
5
5
 
6
6
  has_many :container_config_files
7
7
 
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::ShortProjectSerializer < UffizziCore::BaseSerializer
4
+ type :project
5
+
6
+ attributes :name, :slug
7
+ end
@@ -15,7 +15,8 @@ class UffizziCore::Controller::DeployContainers::ContainerSerializer < UffizziCo
15
15
  :target_port,
16
16
  :public,
17
17
  :controller_name,
18
- :receive_incoming_requests
18
+ :receive_incoming_requests,
19
+ :healthcheck
19
20
 
20
21
  has_many :container_config_files
21
22
 
@@ -52,4 +53,18 @@ class UffizziCore::Controller::DeployContainers::ContainerSerializer < UffizziCo
52
53
  def command
53
54
  object.command.blank? ? nil : JSON.parse(object.command)
54
55
  end
56
+
57
+ def healthcheck
58
+ return {} if object.healthcheck.nil?
59
+
60
+ command = object.healthcheck['test']
61
+ new_command = if command.is_a?(Array)
62
+ items_to_remove = ['CMD', 'CMD-SHELL']
63
+ command.select { |item| items_to_remove.exclude?(item) }
64
+ elsif object.healthcheck['test'].is_a?(String)
65
+ command.split
66
+ end
67
+
68
+ object.healthcheck.merge(test: new_command)
69
+ end
55
70
  end
@@ -17,18 +17,14 @@ class UffizziCore::ComposeFile::Builders::ContainerBuilderService
17
17
  configs_data = container_data[:configs] || []
18
18
  secrets = container_data[:secrets] || []
19
19
  container_name = container_data[:container_name]
20
- continuous_preview_container_data = container_data[:'x-uffizzi-continuous-preview'] || container_data[:'x-uffizzi-continuous-previews']
20
+ healthcheck_data = container_data[:healthcheck] || {}
21
21
 
22
22
  env_file_dependencies = UffizziCore::ComposeFile::GithubDependenciesService.env_file_dependencies_for_container(compose_dependencies,
23
23
  container_name)
24
24
  configs_dependencies = UffizziCore::ComposeFile::GithubDependenciesService.configs_dependencies_for_container(compose_dependencies,
25
25
  container_name)
26
-
27
26
  is_ingress = ingress_container?(container_name, ingress_data)
28
- repo_attributes = build_repo_attributes(container_data, image_data, build_data, credentials)
29
-
30
- repo_attributes = set_continuous_preview_attributes_to_repo(repo_attributes, continuous_preview_global_data.to_h,
31
- continuous_preview_container_data.to_h)
27
+ repo_attributes = repo_attributes(container_data, continuous_preview_global_data)
32
28
 
33
29
  {
34
30
  tag: tag(image_data, repo_attributes),
@@ -51,6 +47,13 @@ class UffizziCore::ComposeFile::Builders::ContainerBuilderService
51
47
 
52
48
  private
53
49
 
50
+ def repo_attributes(container_data, continuous_preview_global_data)
51
+ repo_attributes = build_repo_attributes(container_data)
52
+ continuous_preview_container_data = container_data[:'x-uffizzi-continuous-preview'] || container_data[:'x-uffizzi-continuous-previews']
53
+
54
+ set_continuous_preview_attributes_to_repo(repo_attributes, continuous_preview_global_data.to_h, continuous_preview_container_data.to_h)
55
+ end
56
+
54
57
  def set_continuous_preview_attributes_to_repo(repo_attributes, global_data, container_data)
55
58
  condition_attributes = [
56
59
  :deploy_preview_when_pull_request_is_opened,
@@ -148,8 +151,9 @@ class UffizziCore::ComposeFile::Builders::ContainerBuilderService
148
151
  memory_value
149
152
  end
150
153
 
151
- def build_repo_attributes(container_data, image_data, _build_data, credentials)
154
+ def build_repo_attributes(container_data)
152
155
  repo_type = repo_type(container_data)
156
+ image_data = container_data[:image]
153
157
 
154
158
  case repo_type
155
159
  when UffizziCore::Repo::DockerHub.name
@@ -12,6 +12,10 @@ class UffizziCore::ComposeFile::ConfigOptionService
12
12
 
13
13
  def config_options(compose_data)
14
14
  compose_data.each_with_object([]) do |(key, value), keys|
15
+ if compose_data.equal?(value)
16
+ raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.infinite_recursion', key: key)
17
+ end
18
+
15
19
  keys << key
16
20
  keys.concat(config_options(value)) if value.is_a?(Hash)
17
21
  end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::ComposeFile::Parsers::Services::HealthcheckParserService
4
+ REQUIRED_START_COMMANDS = ['NONE', 'CMD', 'CMD-SHELL'].freeze
5
+
6
+ class << self
7
+ def parse(healthcheck_data)
8
+ return {} if healthcheck_data.blank?
9
+
10
+ command = parse_command(healthcheck_data)
11
+
12
+ {
13
+ test: command,
14
+ interval: parse_time(healthcheck_data['interval']),
15
+ timeout: parse_time(healthcheck_data['timeout']),
16
+ retries: parse_retries(healthcheck_data['retries']),
17
+ start_period: parse_time(healthcheck_data['start_period']),
18
+ disable: parse_disable_option(healthcheck_data['disable'], command),
19
+ }
20
+ end
21
+
22
+ private
23
+
24
+ def parse_command(healthcheck_data)
25
+ command = healthcheck_data['test']
26
+ raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.string_or_array_error', option: :test) if command.nil?
27
+
28
+ case command
29
+ when Array
30
+ start_command = command.first
31
+ raise UffizziCore::ComposeFile::ParseError unless REQUIRED_START_COMMANDS.include?(start_command)
32
+
33
+ command
34
+ when String
35
+ command
36
+ else
37
+ raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.invalid_type', option: :test)
38
+ end
39
+ end
40
+
41
+ def parse_retries(value)
42
+ raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.invalid_integer', option: :retries) unless value.is_a?(Integer)
43
+ end
44
+
45
+ def parse_time(value)
46
+ tokens = {
47
+ 's' => 1,
48
+ 'm' => 60,
49
+ 'h' => (60 * 60),
50
+ 'd' => (60 * 60 * 24),
51
+ }
52
+
53
+ time_parts = value.scan(/(\d+)(\w)/).compact
54
+
55
+ time_parts.reduce(0) do |acc, part|
56
+ amount, measure = part
57
+ acc += amount.to_i * tokens[measure]
58
+
59
+ acc
60
+ rescue StandardError
61
+ raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.invalid_time_interval')
62
+ end
63
+ end
64
+
65
+ def parse_disable_option(value, command)
66
+ return true if command.is_a?(Array) && command.first == 'NONE'
67
+ return false if value.nil?
68
+ return value if value.in?([true, false])
69
+
70
+ raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.invalid_bool_value', field: 'disable', value: value)
71
+ end
72
+ end
73
+ end
@@ -42,6 +42,8 @@ class UffizziCore::ComposeFile::ServicesOptionsService
42
42
  UffizziCore::ComposeFile::ServicesOptions::EntrypointService.parse(value)
43
43
  when :command
44
44
  UffizziCore::ComposeFile::ServicesOptions::CommandService.parse(value)
45
+ when :healthcheck
46
+ UffizziCore::ComposeFile::Parsers::Services::HealthcheckParserService.parse(value)
45
47
  when :'x-uffizzi-continuous-preview', :'x-uffizzi-continuous-previews'
46
48
  UffizziCore::ComposeFile::ContinuousPreviewOptionsService.parse(value)
47
49
  end
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UffizziCore::ComposeFile::TemplateService
4
- def initialize(github_form, project, user)
4
+ def initialize(cli_form, project, user)
5
5
  @project = project
6
6
  @user = user
7
- @compose_dependencies = github_form.compose_dependencies
8
- @compose_data = github_form.compose_data
9
- @compose_repositories = github_form.compose_repositories
7
+ @compose_dependencies = cli_form.compose_dependencies
8
+ @compose_data = cli_form.compose_data
9
+ @compose_repositories = cli_form.compose_repositories
10
10
  end
11
11
 
12
12
  def create_template(compose_file_form)
@@ -158,7 +158,7 @@ module UffizziCore::ComposeFileService
158
158
 
159
159
  def load_compose_data(compose_content)
160
160
  begin
161
- compose_data = YAML.safe_load(compose_content)
161
+ compose_data = YAML.safe_load(compose_content, aliases: true)
162
162
  rescue Psych::SyntaxError
163
163
  raise UffizziCore::ComposeFile::ParseError, 'Invalid compose file'
164
164
  end