summaryrefslogtreecommitdiff
path: root/app/controllers/projects/settings/ci_cd_controller.rb
blob: cf07de4dc298714308def56a160335e95aa7f9c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# frozen_string_literal: true

module Projects
  module Settings
    class CiCdController < Projects::ApplicationController
      include RunnerSetupScripts

      NUMBER_OF_RUNNERS_PER_PAGE = 20

      layout 'project_settings'
      before_action :authorize_admin_pipeline!
      before_action :check_builds_available!
      before_action :define_variables

      helper_method :highlight_badge

      feature_category :continuous_integration
      urgency :low

      def show
        @entity = :project
        @variable_limit = ::Plan.default.actual_limits.project_ci_variables

        if Feature.enabled?(:ci_pipeline_triggers_settings_vue_ui, @project)
          triggers = ::Ci::TriggerSerializer.new.represent(
            @project.triggers, current_user: current_user, project: @project
          )

          @triggers_json = Gitlab::Json.dump(triggers)
        end

        render
      end

      def update
        Projects::UpdateService.new(project, current_user, update_params).tap do |service|
          result = service.execute
          if result[:status] == :success
            flash[:toast] = _("Pipelines settings for '%{project_name}' were successfully updated.") % { project_name: @project.name }

            run_autodevops_pipeline(service)

            redirect_to project_settings_ci_cd_path(@project)
          else
            redirect_to project_settings_ci_cd_path(@project), alert: result[:message]
          end
        end
      end

      def reset_cache
        if ResetProjectCacheService.new(@project, current_user).execute
          respond_to do |format|
            format.json { head :ok }
          end
        else
          respond_to do |format|
            format.json { head :bad_request }
          end
        end
      end

      def reset_registration_token
        ::Ci::Runners::ResetRegistrationTokenService.new(@project, current_user).execute

        flash[:toast] = _("New runners registration token has been generated!")
        redirect_to namespace_project_settings_ci_cd_path
      end

      def runner_setup_scripts
        private_runner_setup_scripts
      end

      private

      def highlight_badge(name, content, language = nil)
        Gitlab::Highlight.highlight(name, content, language: language)
      end

      def update_params
        params.require(:project).permit(*permitted_project_params)
      end

      def permitted_project_params
        [
          :runners_token, :builds_enabled, :build_allow_git_fetch,
          :build_timeout_human_readable, :public_builds, :ci_separated_caches,
          :auto_cancel_pending_pipelines, :ci_config_path, :auto_rollback_enabled,
          auto_devops_attributes: [:id, :domain, :enabled, :deploy_strategy],
          ci_cd_settings_attributes: [:default_git_depth, :forward_deployment_enabled]
        ].tap do |list|
          list << :max_artifacts_size if can?(current_user, :update_max_artifacts_size, project)
        end
      end

      def run_autodevops_pipeline(service)
        return unless service.run_auto_devops_pipeline?

        if @project.empty_repo?
          flash[:notice] = _("This repository is currently empty. A new Auto DevOps pipeline will be created after a new file has been pushed to a branch.")
          return
        end

        # rubocop:disable CodeReuse/Worker
        CreatePipelineWorker.perform_async(project.id, current_user.id, project.default_branch, :web, ignore_skip_ci: true, save_on_errors: false)
        # rubocop:enable CodeReuse/Worker

        flash[:toast] = _("A new Auto DevOps pipeline has been created, go to the Pipelines page for details")
      end

      def define_variables
        define_runners_variables
        define_ci_variables
        define_triggers_variables
        define_badges_variables
        define_auto_devops_variables
      end

      def define_runners_variables
        @project_runners = @project.runners.ordered.page(params[:project_page]).per(NUMBER_OF_RUNNERS_PER_PAGE).with_tags

        @assignable_runners = current_user
          .ci_owned_runners
          .assignable_for(project)
          .ordered
          .page(params[:specific_page]).per(NUMBER_OF_RUNNERS_PER_PAGE)
          .with_tags

        active_shared_runners = ::Ci::Runner.instance_type.active
        @shared_runners_count = active_shared_runners.count
        @shared_runners = active_shared_runners.page(params[:shared_runners_page]).per(NUMBER_OF_RUNNERS_PER_PAGE).with_tags

        parent_group_runners = ::Ci::Runner.belonging_to_parent_group_of_project(@project.id)
        @group_runners_count = parent_group_runners.count
        @group_runners = parent_group_runners.page(params[:group_runners_page]).per(NUMBER_OF_RUNNERS_PER_PAGE).with_tags
      end

      def define_ci_variables
        @variable = ::Ci::Variable.new(project: project)
          .present(current_user: current_user)
        @variables = project.variables.order_key_asc
          .map { |variable| variable.present(current_user: current_user) }
      end

      def define_triggers_variables
        @triggers = @project.triggers
          .present(current_user: current_user)

        @trigger = ::Ci::Trigger.new
          .present(current_user: current_user)
      end

      def define_badges_variables
        @ref = params[:ref] || @project.default_branch_or_main

        @badges = [Gitlab::Ci::Badge::Pipeline::Status,
                   Gitlab::Ci::Badge::Coverage::Report]

        @badges.map! do |badge|
          badge.new(@project, @ref).metadata
        end

        @badges.append(Gitlab::Ci::Badge::Release::LatestRelease.new(@project, current_user).metadata)
      end

      def define_auto_devops_variables
        @auto_devops = @project.auto_devops || ProjectAutoDevops.new
      end
    end
  end
end

Projects::Settings::CiCdController.prepend_mod_with('Projects::Settings::CiCdController')