uffizzi_core 0.7.1 → 1.0.1

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/app/contexts/uffizzi_core/account_context.rb +12 -0
  3. data/app/contexts/uffizzi_core/base_context.rb +1 -2
  4. data/app/contexts/uffizzi_core/project_context.rb +2 -2
  5. data/app/controllers/concerns/uffizzi_core/dependency_injection_concern.rb +6 -0
  6. data/app/controllers/uffizzi_core/api/cli/v1/accounts/application_controller.rb +11 -0
  7. data/app/controllers/uffizzi_core/api/cli/v1/{account → accounts}/credentials_controller.rb +2 -2
  8. data/app/controllers/uffizzi_core/api/cli/v1/accounts/projects_controller.rb +34 -0
  9. data/app/controllers/uffizzi_core/api/cli/v1/ci/application_controller.rb +5 -0
  10. data/app/controllers/uffizzi_core/api/cli/v1/ci/sessions_controller.rb +36 -0
  11. data/app/controllers/uffizzi_core/api/cli/v1/projects/application_controller.rb +5 -1
  12. data/app/controllers/uffizzi_core/api/cli/v1/projects/deployments/activity_items_controller.rb +8 -1
  13. data/app/controllers/uffizzi_core/api/cli/v1/projects_controller.rb +12 -26
  14. data/app/controllers/uffizzi_core/application_controller.rb +6 -0
  15. data/app/forms/uffizzi_core/api/cli/v1/deployment/create_form.rb +15 -1
  16. data/app/forms/uffizzi_core/api/cli/v1/deployment/update_form.rb +1 -0
  17. data/app/forms/uffizzi_core/api/cli/v1/template/create_form.rb +1 -1
  18. data/app/lib/uffizzi_core/concerns/models/account.rb +0 -1
  19. data/app/lib/uffizzi_core/concerns/models/project.rb +0 -1
  20. data/app/lib/uffizzi_core/concerns/models/user_project.rb +1 -1
  21. data/app/models/uffizzi_core/project.rb +1 -0
  22. data/app/policies/uffizzi_core/api/cli/v1/{account → accounts}/credentials_policy.rb +1 -1
  23. data/app/policies/uffizzi_core/api/cli/v1/accounts/projects_policy.rb +7 -0
  24. data/app/policies/uffizzi_core/api/cli/v1/projects_policy.rb +0 -4
  25. data/app/serializers/uffizzi_core/api/cli/v1/{account → accounts}/credential_serializer.rb +1 -1
  26. data/app/serializers/uffizzi_core/api/cli/v1/accounts/project_serializer.rb +11 -0
  27. data/app/serializers/uffizzi_core/api/cli/v1/project_serializer/account_serializer.rb +5 -0
  28. data/app/serializers/uffizzi_core/api/cli/v1/project_serializer.rb +1 -0
  29. data/app/serializers/uffizzi_core/api/cli/v1/short_project_serializer.rb +1 -1
  30. data/app/serializers/uffizzi_core/api/cli/v1/user_serializer/account_serializer.rb +1 -1
  31. data/app/serializers/uffizzi_core/controller/deploy_containers/container_serializer.rb +3 -8
  32. data/app/services/uffizzi_core/compose_file/parsers/services/healthcheck_parser_service.rb +23 -7
  33. data/app/services/uffizzi_core/deployment_service.rb +20 -23
  34. data/config/locales/en.yml +8 -2
  35. data/config/routes.rb +8 -3
  36. data/lib/uffizzi_core/version.rb +1 -1
  37. data/lib/uffizzi_core.rb +1 -0
  38. metadata +13 -9
  39. data/app/controllers/uffizzi_core/api/cli/v1/account/application_controller.rb +0 -7
  40. data/app/lib/uffizzi_core/concerns/models/invitation.rb +0 -31
  41. data/app/models/uffizzi_core/invitation.rb +0 -5
  42. data/app/models/uffizzi_core/repo/github.rb +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 25654d45dce9f26feb5a3cca55a5891bb389216e749512b2900898bec4a8da0b
4
- data.tar.gz: cb7784c03bcffb216adc343ae30e0ef0c51e3038791da4fe0229b86179cdc8e9
3
+ metadata.gz: 169a9ec674c81b791babc5049b74c807a9150da4534980f6b6eb2188b3b12771
4
+ data.tar.gz: c3365c36312f14cf56a3d8c71b293939d667369b8a6df9da67925620127b514e
5
5
  SHA512:
6
- metadata.gz: c3b6ae9974961ae5d39e723264e6c72fa0f4dfa9f99085a6550a98af67afd6ddcbd92f98e7f815ff602bb7f6a3144d2f87ac9d61a58f228099b9dedd537ce6be
7
- data.tar.gz: 572bcfcc9d1e3396d721a83a60c703db10c0b3848031e35b63aa26065b67ceb6fc11bb5278fd6b383e4686a5885758d45d69b0a3c3314cda4f6d93fc3a81d93b
6
+ metadata.gz: f8af4f54965d0557094566deb6d3bea447ede3071891aa4bd7d00139b3795a9644fd6b8d71a346b8b6aeff113cc578bdde3f4f64e45d21bb31f5d59b531e15e9
7
+ data.tar.gz: aa2b7c6fce6745775164119324cd7298cd2382246764026c4aa4bf6ebba3f1c8c390eba3cd3a9bde9b512fb1ec3607da5fee8c376bcac79e953d9efaccd7d811
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::AccountContext
4
+ attr_reader :user, :user_access_module, :account, :params
5
+
6
+ def initialize(user, user_access_module, account, params)
7
+ @user = user
8
+ @user_access_module = user_access_module
9
+ @account = account
10
+ @params = params
11
+ end
12
+ end
@@ -1,12 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UffizziCore::BaseContext
4
- attr_reader :user, :user_access_module, :params, :account
4
+ attr_reader :user, :user_access_module, :params
5
5
 
6
6
  def initialize(user, user_access_module, params)
7
7
  @user = user
8
8
  @user_access_module = user_access_module
9
- @account = user.organizational_account
10
9
  @params = params
11
10
  end
12
11
  end
@@ -3,10 +3,10 @@
3
3
  class UffizziCore::ProjectContext
4
4
  attr_reader :user, :user_access_module, :project, :account, :params
5
5
 
6
- def initialize(user, user_access_module, project, params)
6
+ def initialize(user, user_access_module, project, account, params)
7
7
  @user = user
8
8
  @user_access_module = user_access_module
9
- @account = user.organizational_account
9
+ @account = account
10
10
  @project = project
11
11
  @params = params
12
12
  end
@@ -15,6 +15,12 @@ module UffizziCore::DependencyInjectionConcern
15
15
  module_class(:volume_parser)
16
16
  end
17
17
 
18
+ def ci_session
19
+ return unless module_exists?(:ci_session)
20
+
21
+ module_class(:ci_session)
22
+ end
23
+
18
24
  def password_protection_module
19
25
  return unless module_exists?(:password_protection)
20
26
 
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::Accounts::ApplicationController < UffizziCore::Api::Cli::V1::ApplicationController
4
+ def resource_account
5
+ @resource_account ||= current_user.accounts.find(params[:account_id])
6
+ end
7
+
8
+ def policy_context
9
+ UffizziCore::AccountContext.new(current_user, user_access_module, resource_account, params)
10
+ end
11
+ end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # @resource Account/Credential
4
- class UffizziCore::Api::Cli::V1::Account::CredentialsController < UffizziCore::Api::Cli::V1::Account::ApplicationController
5
- before_action :authorize_uffizzi_core_api_cli_v1_account_credentials
4
+ class UffizziCore::Api::Cli::V1::Accounts::CredentialsController < UffizziCore::Api::Cli::V1::Accounts::ApplicationController
5
+ before_action :authorize_uffizzi_core_api_cli_v1_accounts_credentials
6
6
 
7
7
  # Get a list of accounts credential
8
8
  #
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @resource Project
4
+
5
+ class UffizziCore::Api::Cli::V1::Accounts::ProjectsController < UffizziCore::Api::Cli::V1::Accounts::ApplicationController
6
+ before_action :authorize_uffizzi_core_api_cli_v1_accounts_projects
7
+
8
+ # Create a project
9
+ #
10
+ # @path [POST] /api/cli/v1/accounts/{account_id}/projects
11
+ # @parameter params(required,body) [object<name: string, slug: string, description: string>]
12
+ #
13
+ # @response <object< project: Project>> 200 OK
14
+ # @response 404 Not Found
15
+ # @response 401 Not authorized
16
+ # @response [object<errors: object<password: string >>] 422 Unprocessable entity
17
+
18
+ def create
19
+ project_form = UffizziCore::Api::Cli::V1::Project::CreateForm.new(project_params)
20
+ project_form.account = current_user.organizational_account
21
+
22
+ if project_form.save
23
+ UffizziCore::ProjectService.add_users_to_project!(project_form, current_user)
24
+ end
25
+
26
+ respond_with project_form
27
+ end
28
+
29
+ private
30
+
31
+ def project_params
32
+ params.require(:project)
33
+ end
34
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::Ci::ApplicationController < UffizziCore::Api::Cli::V1::ApplicationController
4
+ before_action :authenticate_request!
5
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @resource Uffizzi
4
+
5
+ class UffizziCore::Api::Cli::V1::Ci::SessionsController < UffizziCore::Api::Cli::V1::Ci::ApplicationController
6
+ skip_before_action :authenticate_request!, only: [:create]
7
+
8
+ # Create session
9
+ #
10
+ # @path [POST] /api/cli/v1/github/session
11
+ #
12
+ # @parameter user(required,body) [object<token: string >]
13
+ # @response [object<account_id: string, project_slug: string>] 201 Created successfully
14
+ # @response [object<errors: object<token: string >>] 422 Unprocessable entity
15
+ def create
16
+ return render json: { errors: { title: [I18n.t('session.unsupported_login_type')] } }, status: :unprocessable_entity unless ci_session
17
+
18
+ session_data, errors = ci_session.session_data_from_ci(user_params)
19
+ return render json: { errors: errors }, status: :unprocessable_entity if errors.present?
20
+
21
+ sign_in(session_data[:user])
22
+
23
+ data = {
24
+ account_id: session_data[:account_id],
25
+ project_slug: session_data[:project_slug],
26
+ }
27
+
28
+ render json: data, status: :created
29
+ end
30
+
31
+ private
32
+
33
+ def user_params
34
+ params.require(:user).permit(:token)
35
+ end
36
+ end
@@ -5,7 +5,11 @@ class UffizziCore::Api::Cli::V1::Projects::ApplicationController < UffizziCore::
5
5
  @resource_project ||= current_user.projects.find_by!(slug: params[:project_slug])
6
6
  end
7
7
 
8
+ def resource_account
9
+ @resource_account ||= resource_project.account
10
+ end
11
+
8
12
  def policy_context
9
- UffizziCore::ProjectContext.new(current_user, user_access_module, resource_project, params)
13
+ UffizziCore::ProjectContext.new(current_user, user_access_module, resource_project, resource_account, params)
10
14
  end
11
15
  end
@@ -15,7 +15,14 @@ class UffizziCore::Api::Cli::V1::Projects::Deployments::ActivityItemsController
15
15
  # @response 401 Not authorized
16
16
  # @response 404 Not found
17
17
  def index
18
- activity_items = resource_deployment
18
+ deployment = resource_project.deployments.existed.find(params[:deployment_id])
19
+
20
+ unless deployment.active?
21
+ return render json: { errors: { title: [I18n.t('deployment.invalid_state', state: deployment.state)] } },
22
+ status: :unprocessable_entity
23
+ end
24
+
25
+ activity_items = deployment
19
26
  .activity_items
20
27
  .page(page)
21
28
  .per(per_page)
@@ -25,30 +25,7 @@ class UffizziCore::Api::Cli::V1::ProjectsController < UffizziCore::Api::Cli::V1:
25
25
  # @response 404 Not Found
26
26
  # @response 401 Not authorized
27
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
- UffizziCore::ProjectService.add_users_to_project!(project_form, current_user)
49
- end
50
-
51
- respond_with project_form
28
+ respond_with resource_project
52
29
  end
53
30
 
54
31
  # Delete a project
@@ -60,8 +37,7 @@ class UffizziCore::Api::Cli::V1::ProjectsController < UffizziCore::Api::Cli::V1:
60
37
  # @response 401 Not authorized
61
38
 
62
39
  def destroy
63
- project = current_user.organizational_account.active_projects.find_by!(slug: params[:slug])
64
- project.disable!
40
+ resource_project.disable!
65
41
 
66
42
  head :no_content
67
43
  end
@@ -71,4 +47,14 @@ class UffizziCore::Api::Cli::V1::ProjectsController < UffizziCore::Api::Cli::V1:
71
47
  def project_params
72
48
  params.require(:project)
73
49
  end
50
+
51
+ def resource_project
52
+ @resource_project ||= current_user.projects.find_by(slug: params[:slug])
53
+ end
54
+
55
+ def policy_context
56
+ account = resource_project&.account || current_user.organizational_account
57
+
58
+ UffizziCore::AccountContext.new(current_user, user_access_module, account, params)
59
+ end
74
60
  end
@@ -19,10 +19,16 @@ class UffizziCore::ApplicationController < ActionController::Base
19
19
  render_not_found(exception)
20
20
  end
21
21
 
22
+ rescue_from Pundit::NotAuthorizedError, with: :render_not_authorized
23
+
22
24
  before_action :authenticate_request!
23
25
  skip_before_action :verify_authenticity_token
24
26
  respond_to :json
25
27
 
28
+ def render_not_authorized
29
+ render json: { errors: { title: [I18n.t('session.unauthorized')] } }, status: :forbidden
30
+ end
31
+
26
32
  def policy_context
27
33
  UffizziCore::BaseContext.new(current_user, user_access_module, params)
28
34
  end
@@ -17,10 +17,10 @@ class UffizziCore::Api::Cli::V1::Deployment::CreateForm < UffizziCore::Deploymen
17
17
  :command,
18
18
  :receive_incoming_requests,
19
19
  :continuously_deploy,
20
- { healthcheck: {} },
21
20
  { variables: [:name, :value],
22
21
  secret_variables: [:name, :value],
23
22
  volumes: [:source, :target, :type, :read_only],
23
+ healthcheck: [:test, :interval, :timeout, :retries, :start_period, :disable, { test: [] }],
24
24
  repo_attributes: [
25
25
  :namespace,
26
26
  :name,
@@ -51,6 +51,7 @@ class UffizziCore::Api::Cli::V1::Deployment::CreateForm < UffizziCore::Deploymen
51
51
  validate :check_exists_ingress_container
52
52
  validate :check_max_memory_limit
53
53
  validate :check_max_memory_request
54
+ validate :check_secrets_exist_in_database
54
55
 
55
56
  def assign_dependences!(project, user)
56
57
  self.project = project
@@ -91,4 +92,17 @@ class UffizziCore::Api::Cli::V1::Deployment::CreateForm < UffizziCore::Deploymen
91
92
 
92
93
  errors.add(:containers, :max_memory_request_error, max: project.account.container_memory_limit)
93
94
  end
95
+
96
+ def check_secrets_exist_in_database
97
+ return if compose_file.nil?
98
+
99
+ existing_secrets = project.secrets.pluck('name')
100
+ compose_file.template.payload['containers_attributes']
101
+ .map { |container| container['secret_variables'].map { |secret| secret['name'] } }.flatten.uniq
102
+ .select { |secret| existing_secrets.exclude?(secret) }
103
+ .each do |secret|
104
+ error_message = I18n.t('compose.project_secret_not_found', secret: secret)
105
+ errors.add(:secret_variables, error_message)
106
+ end
107
+ end
94
108
  end
@@ -19,6 +19,7 @@ class UffizziCore::Api::Cli::V1::Deployment::UpdateForm < UffizziCore::Deploymen
19
19
  { variables: [:name, :value],
20
20
  secret_variables: [:name, :value],
21
21
  volumes: [:source, :target, :type, :read_only],
22
+ healthcheck: [:test, :interval, :timeout, :retries, :start_period, :disable, { test: [] }],
22
23
  repo_attributes: [
23
24
  :namespace,
24
25
  :name,
@@ -18,10 +18,10 @@ class UffizziCore::Api::Cli::V1::Template::CreateForm < UffizziCore::Template
18
18
  :continuously_deploy,
19
19
  :service_name,
20
20
  :name,
21
- :healthcheck,
22
21
  { variables: [:name, :value],
23
22
  secret_variables: [:name, :value],
24
23
  volumes: [:source, :target, :type, :read_only],
24
+ healthcheck: [:test, :interval, :timeout, :retries, :start_period, :disable, { test: [] }],
25
25
  repo_attributes: [
26
26
  :namespace,
27
27
  :name,
@@ -24,7 +24,6 @@ module UffizziCore::Concerns::Models::Account
24
24
  has_many :projects, dependent: :destroy
25
25
  has_many :deployments, through: :projects
26
26
  has_many :payments, dependent: :destroy
27
- has_many :invitations, as: :entityable
28
27
 
29
28
  aasm(:state) do
30
29
  state :active, initial: true
@@ -16,7 +16,6 @@ module UffizziCore::Concerns::Models::Project
16
16
  has_many :deployments, dependent: :destroy
17
17
  has_many :user_projects, dependent: :destroy
18
18
  has_many :users, through: :user_projects
19
- has_many :invitations, as: :entityable
20
19
  has_many :config_files, dependent: :destroy
21
20
  has_many :templates, dependent: :destroy
22
21
  has_many :credentials, through: :account
@@ -8,7 +8,7 @@ module UffizziCore::Concerns::Models::UserProject
8
8
 
9
9
  self.table_name = UffizziCore.table_names[:user_projects]
10
10
 
11
- enumerize :role, in: UffizziCore.user_project_roles, predicates: true
11
+ enumerize :role, in: UffizziCore.user_project_roles, predicates: true, scope: true
12
12
  validates :role, presence: true
13
13
 
14
14
  belongs_to :user
@@ -8,6 +8,7 @@
8
8
  # @property secrets [string]
9
9
  # @property default_compose [object<source: string>]
10
10
  # @property deployments [object<id: integer, domain: string>]
11
+ # @property account [object<id: integer, kind: string, state: string>]
11
12
 
12
13
  class UffizziCore::Project < UffizziCore::ApplicationRecord
13
14
  include UffizziCore::Concerns::Models::Project
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class UffizziCore::Api::Cli::V1::Account::CredentialsPolicy < UffizziCore::ApplicationPolicy
3
+ class UffizziCore::Api::Cli::V1::Accounts::CredentialsPolicy < UffizziCore::ApplicationPolicy
4
4
  def index?
5
5
  context.user_access_module.admin_access_to_account?(context.user, context.account)
6
6
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::Accounts::ProjectsPolicy < UffizziCore::ApplicationPolicy
4
+ def create?
5
+ context.user_access_module.admin_or_developer_access_to_account?(context.user, context.account)
6
+ end
7
+ end
@@ -9,10 +9,6 @@ class UffizziCore::Api::Cli::V1::ProjectsPolicy < UffizziCore::ApplicationPolicy
9
9
  context.user_access_module.any_access_to_account?(context.user, context.account)
10
10
  end
11
11
 
12
- def create?
13
- context.user_access_module.admin_or_developer_access_to_account?(context.user, context.account)
14
- end
15
-
16
12
  def destroy?
17
13
  context.user_access_module.admin_or_developer_access_to_account?(context.user, context.account)
18
14
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class UffizziCore::Api::Cli::V1::Account::CredentialSerializer < UffizziCore::BaseSerializer
3
+ class UffizziCore::Api::Cli::V1::Accounts::CredentialSerializer < UffizziCore::BaseSerializer
4
4
  attributes :id, :username, :password, :type, :state
5
5
 
6
6
  def password
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::Accounts::ProjectSerializer < UffizziCore::BaseSerializer
4
+ type :project
5
+
6
+ attributes :name,
7
+ :slug,
8
+ :account_id,
9
+ :description,
10
+ :created_at
11
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UffizziCore::Api::Cli::V1::ProjectSerializer::AccountSerializer < UffizziCore::BaseSerializer
4
+ attributes :id, :kind, :state, :name
5
+ end
@@ -5,6 +5,7 @@ class UffizziCore::Api::Cli::V1::ProjectSerializer < UffizziCore::BaseSerializer
5
5
  has_many :deployments
6
6
  has_many :secrets
7
7
  has_one :default_compose
8
+ belongs_to :account
8
9
 
9
10
  attributes :name,
10
11
  :slug,
@@ -3,5 +3,5 @@
3
3
  class UffizziCore::Api::Cli::V1::ShortProjectSerializer < UffizziCore::BaseSerializer
4
4
  type :project
5
5
 
6
- attributes :name, :slug
6
+ attributes :name, :slug, :account_id
7
7
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UffizziCore::Api::Cli::V1::UserSerializer::AccountSerializer < UffizziCore::BaseSerializer
4
- attributes :id, :state
4
+ attributes :id, :kind, :state, :name
5
5
  end
@@ -41,12 +41,7 @@ class UffizziCore::Controller::DeployContainers::ContainerSerializer < UffizziCo
41
41
  end
42
42
 
43
43
  def tag
44
- case object.repo.type
45
- when UffizziCore::Repo::Github.name
46
- UffizziCore::RepoService.tag(object.repo)
47
- else
48
- object.tag
49
- end
44
+ object.tag
50
45
  end
51
46
 
52
47
  def entrypoint
@@ -58,7 +53,7 @@ class UffizziCore::Controller::DeployContainers::ContainerSerializer < UffizziCo
58
53
  end
59
54
 
60
55
  def healthcheck
61
- return {} if object.healthcheck.nil?
56
+ return {} if object.healthcheck.blank?
62
57
 
63
58
  command = object.healthcheck['test']
64
59
  new_command = if command.is_a?(Array)
@@ -68,6 +63,6 @@ class UffizziCore::Controller::DeployContainers::ContainerSerializer < UffizziCo
68
63
  command.split
69
64
  end
70
65
 
71
- object.healthcheck.merge(test: new_command)
66
+ object.healthcheck.merge('test' => new_command)
72
67
  end
73
68
  end
@@ -11,10 +11,10 @@ class UffizziCore::ComposeFile::Parsers::Services::HealthcheckParserService
11
11
 
12
12
  {
13
13
  test: command,
14
- interval: parse_time(healthcheck_data['interval']),
15
- timeout: parse_time(healthcheck_data['timeout']),
14
+ interval: parse_time(:interval, healthcheck_data['interval']),
15
+ timeout: parse_time(:timeout, healthcheck_data['timeout']),
16
16
  retries: parse_retries(healthcheck_data['retries']),
17
- start_period: parse_time(healthcheck_data['start_period']),
17
+ start_period: parse_time(:start_period, healthcheck_data['start_period']),
18
18
  disable: parse_disable_option(healthcheck_data['disable'], command),
19
19
  }
20
20
  end
@@ -28,7 +28,11 @@ class UffizziCore::ComposeFile::Parsers::Services::HealthcheckParserService
28
28
  case command
29
29
  when Array
30
30
  start_command = command.first
31
- raise UffizziCore::ComposeFile::ParseError unless REQUIRED_START_COMMANDS.include?(start_command)
31
+
32
+ unless REQUIRED_START_COMMANDS.include?(start_command)
33
+ raise UffizziCore::ComposeFile::ParseError,
34
+ I18n.t('compose.required_start_commands', available_commands: REQUIRED_START_COMMANDS.join(', '))
35
+ end
32
36
 
33
37
  command
34
38
  when String
@@ -39,10 +43,22 @@ class UffizziCore::ComposeFile::Parsers::Services::HealthcheckParserService
39
43
  end
40
44
 
41
45
  def parse_retries(value)
42
- raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.invalid_integer', option: :retries) unless value.is_a?(Integer)
46
+ return if value.nil?
47
+
48
+ unless value.is_a?(Integer)
49
+ raise UffizziCore::ComposeFile::ParseError,
50
+ I18n.t('compose.invalid_retries', value: value)
51
+ end
52
+
53
+ value
43
54
  end
44
55
 
45
- def parse_time(value)
56
+ def parse_time(key, value)
57
+ return if value.nil?
58
+
59
+ error_message = I18n.t('compose.invalid_time_interval', key: key, value: value)
60
+ raise UffizziCore::ComposeFile::ParseError, error_message if value.is_a?(Integer)
61
+
46
62
  tokens = {
47
63
  's' => 1,
48
64
  'm' => 60,
@@ -58,7 +74,7 @@ class UffizziCore::ComposeFile::Parsers::Services::HealthcheckParserService
58
74
 
59
75
  acc
60
76
  rescue StandardError
61
- raise UffizziCore::ComposeFile::ParseError, I18n.t('compose.invalid_time_interval')
77
+ raise UffizziCore::ComposeFile::ParseError, error_message
62
78
  end
63
79
  end
64
80
 
@@ -20,11 +20,7 @@ class UffizziCore::DeploymentService
20
20
  deployment_form.creation_source = UffizziCore::Deployment.creation_source.compose_file_manual
21
21
  deployment_form.metadata = metadata || {}
22
22
 
23
- if deployment_form.save
24
- update_subdomain!(deployment_form)
25
-
26
- UffizziCore::Deployment::CreateJob.perform_async(deployment_form.id)
27
- end
23
+ run_deployment_creation_tasks(deployment_form) if deployment_form.save
28
24
 
29
25
  deployment_form
30
26
  end
@@ -91,27 +87,28 @@ class UffizziCore::DeploymentService
91
87
  end
92
88
 
93
89
  def build_subdomain(deployment)
94
- if deployment.continuous_preview_payload.present?
95
- continuous_preview_payload = deployment.continuous_preview_payload
90
+ return build_docker_continuous_preview_subdomain(deployment) if deployment&.continuous_preview_payload&.fetch('docker', nil).present?
96
91
 
97
- return build_pull_request_subdomain(deployment) if continuous_preview_payload['pull_request'].present?
98
- return build_docker_continuous_preview_subdomain(deployment) if continuous_preview_payload['docker'].present?
99
- end
92
+ github_metadata = deployment.metadata.dig('labels', 'github')
93
+ return build_pull_request_subdomain(deployment) if
94
+ github_metadata&.dig('pull_request', 'number').present? && github_metadata&.dig('repository').present?
100
95
 
101
96
  build_default_subdomain(deployment)
102
97
  end
103
98
 
104
99
  def build_pull_request_subdomain(deployment)
105
- project = deployment.project
106
- continuous_preview_payload = deployment.continuous_preview_payload
107
- pull_request_payload = continuous_preview_payload['pull_request']
108
- repo_name = pull_request_payload['repository_full_name'].split('/').last
109
- deployment_name = name(deployment)
110
- subdomain = "pr#{pull_request_payload['id']}-#{deployment_name}-#{repo_name}-#{project.slug}"
111
-
100
+ github_payload = deployment.metadata.dig('labels', 'github')
101
+ repo_name = github_payload['repository'].split('/').last
102
+ pull_request_number = github_payload['pull_request']['number']
103
+ subdomain = "pr-#{pull_request_number}-#{name(deployment)}-#{repo_name}-#{deployment.project.slug}"
112
104
  format_subdomain(subdomain)
113
105
  end
114
106
 
107
+ def update_subdomain!(deployment)
108
+ deployment.subdomain = build_subdomain(deployment)
109
+ deployment.save!
110
+ end
111
+
115
112
  def build_docker_continuous_preview_subdomain(deployment)
116
113
  project = deployment.project
117
114
  continuous_preview_payload = deployment.continuous_preview_payload
@@ -204,12 +201,6 @@ class UffizziCore::DeploymentService
204
201
  "deployment-#{deployment.id}"
205
202
  end
206
203
 
207
- def update_subdomain!(deployment)
208
- deployment.subdomain = build_subdomain(deployment)
209
-
210
- deployment.save!
211
- end
212
-
213
204
  def pull_request_payload_present?(deployment)
214
205
  deployment.continuous_preview_payload.present? && deployment.continuous_preview_payload['pull_request'].present?
215
206
  end
@@ -222,6 +213,12 @@ class UffizziCore::DeploymentService
222
213
 
223
214
  private
224
215
 
216
+ def run_deployment_creation_tasks(deployment)
217
+ update_subdomain!(deployment)
218
+
219
+ UffizziCore::Deployment::CreateJob.perform_async(deployment.id)
220
+ end
221
+
225
222
  def deployment_process_status(deployment)
226
223
  containers = deployment.active_containers
227
224
  activity_items = containers.map { |container| container.activity_items.order_by_id.last }.compact
@@ -56,8 +56,8 @@ en:
56
56
  project_secret_not_found: Project secret '%{secret}' not found
57
57
  continuous_preview_in_service_level: The option '%{option}' is not supported for service-level. Use 'x-uffizzi-continuous-preview' instead
58
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
- invalid_healthcheck_command: "Service '%{name}' defines an invalid healthcheck: when 'test' is a list the first item must be either NONE, CMD or CMD-SHELL"
60
- invalid_time_interval: The time interval should be in the following format '{hours}h{minutes}m{seconds}s'. At least one value must be present.
59
+ invalid_time_interval: "Invalid time interval: '%{key}:%{value}'. The time interval should be in the following format '{hours}h{minutes}m{seconds}s'. At least one value must be present."
60
+ invalid_retries: "Invalid retries value: 'retries:%{value}'. The value should be an integer."
61
61
  string_or_array_error: "'%{option}' contains an invalid type, it should be a string, or an array"
62
62
  not_implemented: "'%{option}' option is not implemented"
63
63
  infinite_recursion: "Found infinite recursion for key '%{key}'"
@@ -67,6 +67,12 @@ en:
67
67
  volume_type_not_supported: Volumes with type '%{type}' does not supported
68
68
  named_volume_not_exists: Named volume '%{source_path}:%{target_path}' is used in service '%{service_name}' but no declaration was found in the volumes section.
69
69
  invalid_volume_destination: Invalid volume specification '%{spec}' destination can't be '/'
70
+ required_start_commands: "When 'test' is a list the first item must be one of: '%{available_commands}'"
70
71
  secrets:
71
72
  duplicates_exists: Secret with key %{secrets} already exist.
72
73
  invalid_key_length: A secret key must be no longer than 256 characters.
74
+ deployment:
75
+ invalid_state: Deployment %{state}
76
+ session:
77
+ unsupported_login_type: This type of login is not supported
78
+ unauthorized: Unauthorized
data/config/routes.rb CHANGED
@@ -7,7 +7,7 @@ UffizziCore::Engine.routes.draw do
7
7
  namespace :api, defaults: { format: :json } do
8
8
  namespace :cli do
9
9
  namespace :v1 do
10
- resources :projects, only: ['index', 'show', 'create', 'destroy'], param: :slug do
10
+ resources :projects, only: ['index', 'show', 'destroy'], param: :slug do
11
11
  scope module: :projects do
12
12
  resource :compose_file, only: ['show', 'create', 'destroy']
13
13
  resources :deployments, only: ['index', 'show', 'create', 'destroy', 'update'] do
@@ -36,8 +36,13 @@ UffizziCore::Engine.routes.draw do
36
36
  end
37
37
  resource :session, only: ['create', 'destroy']
38
38
 
39
- resource :account, only: [] do
40
- scope module: :account do
39
+ namespace :ci do
40
+ resource :session, only: ['create']
41
+ end
42
+
43
+ resources :accounts, only: [] do
44
+ scope module: :accounts do
45
+ resources :projects, only: ['create']
41
46
  resources :credentials, only: ['index', 'create', 'update', 'destroy'], param: :type do
42
47
  member do
43
48
  get :check_credential
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module UffizziCore
4
- VERSION = '0.7.1'
4
+ VERSION = '1.0.1'
5
5
  end
data/lib/uffizzi_core.rb CHANGED
@@ -60,4 +60,5 @@ module UffizziCore
60
60
  }
61
61
  mattr_accessor :user_creation_sources, default: [:system, :online_registration, :google, :sso]
62
62
  mattr_accessor :user_project_roles, default: [:admin, :developer, :viewer]
63
+ mattr_accessor :account_sources, default: [:manual]
63
64
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uffizzi_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Thurman
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-08-23 00:00:00.000000000 Z
12
+ date: 2022-09-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: aasm
@@ -701,15 +701,19 @@ files:
701
701
  - app/clients/uffizzi_core/github_container_registry_client/request_result.rb
702
702
  - app/clients/uffizzi_core/google_registry_client.rb
703
703
  - app/clients/uffizzi_core/google_registry_client/request_result.rb
704
+ - app/contexts/uffizzi_core/account_context.rb
704
705
  - app/contexts/uffizzi_core/base_context.rb
705
706
  - app/contexts/uffizzi_core/project_context.rb
706
707
  - app/contexts/uffizzi_core/webhooks_context.rb
707
708
  - app/controllers/concerns/uffizzi_core/auth_management.rb
708
709
  - app/controllers/concerns/uffizzi_core/authorization_concern.rb
709
710
  - app/controllers/concerns/uffizzi_core/dependency_injection_concern.rb
710
- - app/controllers/uffizzi_core/api/cli/v1/account/application_controller.rb
711
- - app/controllers/uffizzi_core/api/cli/v1/account/credentials_controller.rb
711
+ - app/controllers/uffizzi_core/api/cli/v1/accounts/application_controller.rb
712
+ - app/controllers/uffizzi_core/api/cli/v1/accounts/credentials_controller.rb
713
+ - app/controllers/uffizzi_core/api/cli/v1/accounts/projects_controller.rb
712
714
  - app/controllers/uffizzi_core/api/cli/v1/application_controller.rb
715
+ - app/controllers/uffizzi_core/api/cli/v1/ci/application_controller.rb
716
+ - app/controllers/uffizzi_core/api/cli/v1/ci/sessions_controller.rb
713
717
  - app/controllers/uffizzi_core/api/cli/v1/projects/application_controller.rb
714
718
  - app/controllers/uffizzi_core/api/cli/v1/projects/compose_files_controller.rb
715
719
  - app/controllers/uffizzi_core/api/cli/v1/projects/deployments/activity_items_controller.rb
@@ -774,7 +778,6 @@ files:
774
778
  - app/lib/uffizzi_core/concerns/models/credential.rb
775
779
  - app/lib/uffizzi_core/concerns/models/deployment.rb
776
780
  - app/lib/uffizzi_core/concerns/models/event.rb
777
- - app/lib/uffizzi_core/concerns/models/invitation.rb
778
781
  - app/lib/uffizzi_core/concerns/models/membership.rb
779
782
  - app/lib/uffizzi_core/concerns/models/payment.rb
780
783
  - app/lib/uffizzi_core/concerns/models/price.rb
@@ -817,7 +820,6 @@ files:
817
820
  - app/models/uffizzi_core/database_offering.rb
818
821
  - app/models/uffizzi_core/deployment.rb
819
822
  - app/models/uffizzi_core/event.rb
820
- - app/models/uffizzi_core/invitation.rb
821
823
  - app/models/uffizzi_core/membership.rb
822
824
  - app/models/uffizzi_core/payment.rb
823
825
  - app/models/uffizzi_core/price.rb
@@ -829,7 +831,6 @@ files:
829
831
  - app/models/uffizzi_core/repo/azure.rb
830
832
  - app/models/uffizzi_core/repo/docker_hub.rb
831
833
  - app/models/uffizzi_core/repo/docker_registry.rb
832
- - app/models/uffizzi_core/repo/github.rb
833
834
  - app/models/uffizzi_core/repo/github_container_registry.rb
834
835
  - app/models/uffizzi_core/repo/google.rb
835
836
  - app/models/uffizzi_core/role.rb
@@ -837,7 +838,8 @@ files:
837
838
  - app/models/uffizzi_core/template.rb
838
839
  - app/models/uffizzi_core/user.rb
839
840
  - app/models/uffizzi_core/user_project.rb
840
- - app/policies/uffizzi_core/api/cli/v1/account/credentials_policy.rb
841
+ - app/policies/uffizzi_core/api/cli/v1/accounts/credentials_policy.rb
842
+ - app/policies/uffizzi_core/api/cli/v1/accounts/projects_policy.rb
841
843
  - app/policies/uffizzi_core/api/cli/v1/projects/compose_files_policy.rb
842
844
  - app/policies/uffizzi_core/api/cli/v1/projects/deployments/activity_items_policy.rb
843
845
  - app/policies/uffizzi_core/api/cli/v1/projects/deployments/containers_policy.rb
@@ -865,8 +867,10 @@ files:
865
867
  - app/repositories/uffizzi_core/usage_repo.rb
866
868
  - app/repositories/uffizzi_core/user_repo.rb
867
869
  - app/responders/uffizzi_core/json_responder.rb
868
- - app/serializers/uffizzi_core/api/cli/v1/account/credential_serializer.rb
870
+ - app/serializers/uffizzi_core/api/cli/v1/accounts/credential_serializer.rb
871
+ - app/serializers/uffizzi_core/api/cli/v1/accounts/project_serializer.rb
869
872
  - app/serializers/uffizzi_core/api/cli/v1/project_serializer.rb
873
+ - app/serializers/uffizzi_core/api/cli/v1/project_serializer/account_serializer.rb
870
874
  - app/serializers/uffizzi_core/api/cli/v1/project_serializer/compose_file_serializer.rb
871
875
  - app/serializers/uffizzi_core/api/cli/v1/project_serializer/deployment_serializer.rb
872
876
  - app/serializers/uffizzi_core/api/cli/v1/projects/compose_file_serializer.rb
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class UffizziCore::Api::Cli::V1::Account::ApplicationController < UffizziCore::Api::Cli::V1::ApplicationController
4
- def resource_account
5
- @resource_account ||= current_user.organizational_account
6
- end
7
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module UffizziCore::Concerns::Models::Invitation
4
- extend ActiveSupport::Concern
5
-
6
- included do
7
- include AASM
8
- include UffizziCore::StateMachineConcern
9
- extend Enumerize
10
-
11
- self.table_name = UffizziCore.table_names[:invitations]
12
-
13
- enumerize :role, in: [:admin, :developer, :viewer], predicates: true
14
-
15
- belongs_to :entityable, polymorphic: true
16
- belongs_to :invited_by, class_name: UffizziCore::User.name, foreign_key: :invited_by_id
17
- belongs_to :invitee, class_name: UffizziCore::User.name, foreign_key: :invitee_id, optional: true
18
-
19
- validates :email, presence: true, 'uffizzi_core/email': true
20
- validates :token, presence: true, uniqueness: true
21
-
22
- aasm(:status) do
23
- state :pending, initial: true
24
- state :accepted
25
-
26
- event :accept do
27
- transitions from: :pending, to: :accepted
28
- end
29
- end
30
- end
31
- end
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class UffizziCore::Invitation < UffizziCore::ApplicationRecord
4
- include UffizziCore::Concerns::Models::Invitation
5
- end
@@ -1,4 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class UffizziCore::Repo::Github < UffizziCore::Repo
4
- end