diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-07-20 15:26:25 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-07-20 15:26:25 +0300 |
commit | a09983ae35713f5a2bbb100981116d31ce99826e (patch) | |
tree | 2ee2af7bd104d57086db360a7e6d8c9d5d43667a /app/controllers/projects | |
parent | 18c5ab32b738c0b6ecb4d0df3994000482f34bd8 (diff) |
Add latest changes from gitlab-org/gitlab@13-2-stable-ee
Diffstat (limited to 'app/controllers/projects')
38 files changed, 445 insertions, 185 deletions
diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb index b1f285f76d7..518d414be1b 100644 --- a/app/controllers/projects/application_controller.rb +++ b/app/controllers/projects/application_controller.rb @@ -42,7 +42,7 @@ class Projects::ApplicationController < ApplicationController def authorize_action!(action) unless can?(current_user, action, project) - return access_denied! + access_denied! end end @@ -81,10 +81,6 @@ class Projects::ApplicationController < ApplicationController end end - def apply_diff_view_cookie! - set_secure_cookie(:diff_view, params.delete(:view), permanent: true) if params[:view].present? - end - def require_pages_enabled! not_found unless @project.pages_available? end diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index 14dca1bdc30..7f14522e61b 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -9,6 +9,7 @@ class Projects::BlobController < Projects::ApplicationController include ActionView::Helpers::SanitizeHelper include RedirectsForMissingPathOnTree include SourcegraphDecorator + include DiffHelper prepend_before_action :authenticate_user!, only: [:edit] @@ -129,7 +130,7 @@ class Projects::BlobController < Projects::ApplicationController end end - return redirect_to_tree_root_for_missing_path(@project, @ref, @path) + redirect_to_tree_root_for_missing_path(@project, @ref, @path) end end @@ -207,14 +208,14 @@ class Projects::BlobController < Projects::ApplicationController def set_last_commit_sha @last_commit_sha = Gitlab::Git::Commit - .last_for_path(@repository, @ref, @path).sha + .last_for_path(@repository, @ref, @path, literal_pathspec: true).sha end def show_html environment_params = @repository.branch_exists?(@ref) ? { ref: @ref } : { commit: @commit } environment_params[:find_latest] = true @environment = EnvironmentsFinder.new(@project, current_user, environment_params).execute.last - @last_commit = @repository.last_commit_for_path(@commit.id, @blob.path) + @last_commit = @repository.last_commit_for_path(@commit.id, @blob.path, literal_pathspec: true) @code_navigation_path = Gitlab::CodeNavigationPath.new(@project, @blob.commit_id).full_json_path_for(@blob.path) render 'show' diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb index 8fa823e0be1..db05da0bb7f 100644 --- a/app/controllers/projects/boards_controller.rb +++ b/app/controllers/projects/boards_controller.rb @@ -9,7 +9,6 @@ class Projects::BoardsController < Projects::ApplicationController before_action :assign_endpoint_vars before_action do push_frontend_feature_flag(:multi_select_board, default_enabled: true) - push_frontend_feature_flag(:sfc_issue_boards, default_enabled: true) end private diff --git a/app/controllers/projects/ci/lints_controller.rb b/app/controllers/projects/ci/lints_controller.rb index b50afa12da0..73b3eb9c205 100644 --- a/app/controllers/projects/ci/lints_controller.rb +++ b/app/controllers/projects/ci/lints_controller.rb @@ -14,7 +14,7 @@ class Projects::Ci::LintsController < Projects::ApplicationController @errors = result.errors if result.valid? - @config_processor = result.content + @config_processor = result.config @stages = @config_processor.stages @builds = @config_processor.builds @jobs = @config_processor.jobs diff --git a/app/controllers/projects/clusters_controller.rb b/app/controllers/projects/clusters_controller.rb index 079d30127d6..8acf5235c1a 100644 --- a/app/controllers/projects/clusters_controller.rb +++ b/app/controllers/projects/clusters_controller.rb @@ -23,6 +23,13 @@ class Projects::ClustersController < Clusters::ClustersController def repository @repository ||= project.repository end -end -Projects::ClustersController.prepend_if_ee('EE::Projects::ClustersController') + def metrics_dashboard_params + params.permit(:embedded, :group, :title, :y_label).merge( + { + cluster: cluster, + cluster_type: :project + } + ) + end +end diff --git a/app/controllers/projects/confluences_controller.rb b/app/controllers/projects/confluences_controller.rb new file mode 100644 index 00000000000..d563b34a362 --- /dev/null +++ b/app/controllers/projects/confluences_controller.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class Projects::ConfluencesController < Projects::ApplicationController + before_action :ensure_confluence + + def show + end + + private + + def ensure_confluence + render_404 unless project.has_confluence? + end +end diff --git a/app/controllers/projects/cycle_analytics_controller.rb b/app/controllers/projects/cycle_analytics_controller.rb index f13c75ac4cc..898d888c978 100644 --- a/app/controllers/projects/cycle_analytics_controller.rb +++ b/app/controllers/projects/cycle_analytics_controller.rb @@ -4,10 +4,13 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController include ActionView::Helpers::DateHelper include ActionView::Helpers::TextHelper include CycleAnalyticsParams + include Analytics::UniqueVisitsHelper before_action :whitelist_query_limiting, only: [:show] before_action :authorize_read_cycle_analytics! + track_unique_visits :show, target_id: 'p_analytics_valuestream' + def show @cycle_analytics = ::CycleAnalytics::ProjectLevel.new(@project, options: options(cycle_analytics_project_params)) diff --git a/app/controllers/projects/deployments_controller.rb b/app/controllers/projects/deployments_controller.rb index 766e2f86ea2..1344cf775e4 100644 --- a/app/controllers/projects/deployments_controller.rb +++ b/app/controllers/projects/deployments_controller.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true class Projects::DeploymentsController < Projects::ApplicationController - before_action :authorize_read_environment! before_action :authorize_read_deployment! # rubocop: disable CodeReuse/ActiveRecord diff --git a/app/controllers/projects/environments/prometheus_api_controller.rb b/app/controllers/projects/environments/prometheus_api_controller.rb index 98fcc594d6e..f0bb5360f84 100644 --- a/app/controllers/projects/environments/prometheus_api_controller.rb +++ b/app/controllers/projects/environments/prometheus_api_controller.rb @@ -1,51 +1,17 @@ # frozen_string_literal: true class Projects::Environments::PrometheusApiController < Projects::ApplicationController - include RenderServiceResults + include Metrics::Dashboard::PrometheusApiProxy - before_action :authorize_read_prometheus! - before_action :environment - - def proxy - variable_substitution_result = - variable_substitution_service.new(environment, permit_params).execute - - if variable_substitution_result[:status] == :error - return error_response(variable_substitution_result) - end - - prometheus_result = Prometheus::ProxyService.new( - environment, - proxy_method, - proxy_path, - variable_substitution_result[:params] - ).execute - - return continue_polling_response if prometheus_result.nil? - return error_response(prometheus_result) if prometheus_result[:status] == :error - - success_response(prometheus_result) - end + before_action :proxyable private - def variable_substitution_service - Prometheus::ProxyVariableSubstitutionService - end - - def permit_params - params.permit! - end - - def environment - @environment ||= project.environments.find(params[:id]) + def proxyable + @proxyable ||= project.environments.find(params[:id]) end - def proxy_method - request.method - end - - def proxy_path - params[:proxy_path] + def proxy_variable_substitution_service + Prometheus::ProxyVariableSubstitutionService end end diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb index 4d774123ef1..d5da24a76de 100644 --- a/app/controllers/projects/environments_controller.rb +++ b/app/controllers/projects/environments_controller.rb @@ -1,6 +1,10 @@ # frozen_string_literal: true class Projects::EnvironmentsController < Projects::ApplicationController + # Metrics dashboard code is getting decoupled from environments and is being moved + # into app/controllers/projects/metrics_dashboard_controller.rb + # See https://gitlab.com/gitlab-org/gitlab/-/issues/226002 for more details. + include MetricsDashboard layout 'project' diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb index ebc81976529..b93f6384e0c 100644 --- a/app/controllers/projects/forks_controller.rb +++ b/app/controllers/projects/forks_controller.rb @@ -3,6 +3,7 @@ class Projects::ForksController < Projects::ApplicationController include ContinueParams include RendersMemberAccess + include RendersProjectsList include Gitlab::Utils::StrongMemoize # Authorize diff --git a/app/controllers/projects/graphs_controller.rb b/app/controllers/projects/graphs_controller.rb index a8b90f8685f..9b889f9e837 100644 --- a/app/controllers/projects/graphs_controller.rb +++ b/app/controllers/projects/graphs_controller.rb @@ -2,12 +2,15 @@ class Projects::GraphsController < Projects::ApplicationController include ExtractsPath + include Analytics::UniqueVisitsHelper # Authorize before_action :require_non_empty_project before_action :assign_ref_vars before_action :authorize_read_repository_graphs! + track_unique_visits :charts, target_id: 'p_analytics_repo' + def show respond_to do |format| format.html diff --git a/app/controllers/projects/imports_controller.rb b/app/controllers/projects/imports_controller.rb index 67a7daf8445..deba71c9dd3 100644 --- a/app/controllers/projects/imports_controller.rb +++ b/app/controllers/projects/imports_controller.rb @@ -5,7 +5,8 @@ class Projects::ImportsController < Projects::ApplicationController include ImportUrlParams # Authorize - before_action :authorize_admin_project! + before_action :authorize_admin_project!, only: [:new, :create] + before_action :require_namespace_project_creation_permission, only: :show before_action :require_no_repo, only: [:new, :create] before_action :redirect_if_progress, only: [:new, :create] before_action :redirect_if_no_import, only: :show @@ -51,6 +52,10 @@ class Projects::ImportsController < Projects::ApplicationController end end + def require_namespace_project_creation_permission + render_404 unless current_user.can?(:admin_project, @project) || current_user.can?(:create_projects, @project.namespace) + end + def redirect_if_progress if @project.import_in_progress? redirect_to project_import_path(@project) diff --git a/app/controllers/projects/incident_management/pager_duty_incidents_controller.rb b/app/controllers/projects/incident_management/pager_duty_incidents_controller.rb new file mode 100644 index 00000000000..dac1640dd08 --- /dev/null +++ b/app/controllers/projects/incident_management/pager_duty_incidents_controller.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module Projects + module IncidentManagement + class PagerDutyIncidentsController < Projects::ApplicationController + respond_to :json + + skip_before_action :verify_authenticity_token + skip_before_action :project + + prepend_before_action :project_without_auth + + def create + result = webhook_processor.execute(params[:token]) + + head result.http_status + end + + private + + def project_without_auth + @project ||= Project + .find_by_full_path("#{params[:namespace_id]}/#{params[:project_id]}") + end + + def webhook_processor + ::IncidentManagement::PagerDuty::ProcessWebhookService.new(project, nil, payload) + end + + def payload + @payload ||= params.permit![:pager_duty_incident].to_h + end + end + end +end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 693329848de..12b5a538bc9 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -11,11 +11,11 @@ class Projects::IssuesController < Projects::ApplicationController include RecordUserLastActivity def issue_except_actions - %i[index calendar new create bulk_update import_csv export_csv] + %i[index calendar new create bulk_update import_csv export_csv service_desk] end def set_issuables_index_only_actions - %i[index calendar] + %i[index calendar service_desk] end prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) } @@ -46,10 +46,17 @@ class Projects::IssuesController < Projects::ApplicationController before_action do push_frontend_feature_flag(:vue_issuable_sidebar, project.group) + push_frontend_feature_flag(:tribute_autocomplete, @project) + push_frontend_feature_flag(:vue_issuables_list, project) end before_action only: :show do push_frontend_feature_flag(:real_time_issue_sidebar, @project) + push_frontend_feature_flag(:confidential_apollo_sidebar, @project) + end + + before_action only: :index do + push_frontend_feature_flag(:scoped_labels, @project) end around_action :allow_gitaly_ref_name_caching, only: [:discussions] @@ -216,6 +223,11 @@ class Projects::IssuesController < Projects::ApplicationController redirect_to project_issues_path(project) end + def service_desk + @issues = @issuables # rubocop:disable Gitlab/ModuleWithInstanceVariables + @users.push(User.support_bot) # rubocop:disable Gitlab/ModuleWithInstanceVariables + end + protected def sorting_field @@ -313,6 +325,17 @@ class Projects::IssuesController < Projects::ApplicationController private + def finder_options + options = super + + return options unless service_desk? + + options.reject! { |key| key == 'author_username' || key == 'author_id' } + options[:author_id] = User.support_bot + + options + end + def branch_link(branch) project_compare_path(project, from: project.default_branch, to: branch[:name]) end @@ -330,6 +353,10 @@ class Projects::IssuesController < Projects::ApplicationController def rate_limiter ::Gitlab::ApplicationRateLimiter end + + def service_desk? + action_name == 'service_desk' + end end Projects::IssuesController.prepend_if_ee('EE::Projects::IssuesController') diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb index e1f6cbe3dca..3f7f8da3478 100644 --- a/app/controllers/projects/jobs_controller.rb +++ b/app/controllers/projects/jobs_controller.rb @@ -11,9 +11,6 @@ class Projects::JobsController < Projects::ApplicationController before_action :authorize_erase_build!, only: [:erase] before_action :authorize_use_build_terminal!, only: [:terminal, :terminal_websocket_authorize] before_action :verify_api_request!, only: :terminal_websocket_authorize - before_action only: [:show] do - push_frontend_feature_flag(:job_log_json, project, default_enabled: true) - end before_action :authorize_create_proxy_build!, only: :proxy_websocket_authorize before_action :verify_proxy_request!, only: :proxy_websocket_authorize @@ -55,15 +52,10 @@ class Projects::JobsController < Projects::ApplicationController format.json do build.trace.being_watched! - # TODO: when the feature flag is removed we should not pass - # content_format to serialize method. - content_format = Feature.enabled?(:job_log_json, @project, default_enabled: true) ? :json : :html - build_trace = Ci::BuildTrace.new( build: @build, stream: stream, - state: params[:state], - content_format: content_format) + state: params[:state]) render json: BuildTraceSerializer .new(project: @project, current_user: @current_user) diff --git a/app/controllers/projects/logs_controller.rb b/app/controllers/projects/logs_controller.rb index ba509235417..b9027b3a2cb 100644 --- a/app/controllers/projects/logs_controller.rb +++ b/app/controllers/projects/logs_controller.rb @@ -2,15 +2,16 @@ module Projects class LogsController < Projects::ApplicationController + include ::Gitlab::Utils::StrongMemoize + before_action :authorize_read_pod_logs! - before_action :environment before_action :ensure_deployments, only: %i(k8s elasticsearch) def index - if environment.nil? - render :empty_logs - else + if environment || cluster render :index + else + render :empty_logs end end @@ -39,8 +40,9 @@ module Projects end end - def index_params - params.permit(:environment_name) + # cluster is selected either via environment or directly by id + def cluster_params + params.permit(:environment_name, :cluster_id) end def k8s_params @@ -52,22 +54,36 @@ module Projects end def environment - @environment ||= if index_params.key?(:environment_name) - EnvironmentsFinder.new(project, current_user, name: index_params[:environment_name]).find.first - else - project.default_environment - end + strong_memoize(:environment) do + if cluster_params.key?(:environment_name) + EnvironmentsFinder.new(project, current_user, name: cluster_params[:environment_name]).find.first + else + project.default_environment + end + end end def cluster - environment.deployment_platform&.cluster + strong_memoize(:cluster) do + if gitlab_managed_apps_logs? + clusters = ClusterAncestorsFinder.new(project, current_user).execute + clusters.find { |cluster| cluster.id == cluster_params[:cluster_id].to_i } + else + environment&.deployment_platform&.cluster + end + end end def namespace - environment.deployment_namespace + if gitlab_managed_apps_logs? + Gitlab::Kubernetes::Helm::NAMESPACE + else + environment.deployment_namespace + end end def ensure_deployments + return if gitlab_managed_apps_logs? return if cluster && namespace.present? render status: :bad_request, json: { @@ -75,5 +91,9 @@ module Projects message: _('Environment does not have deployments') } end + + def gitlab_managed_apps_logs? + cluster_params.key?(:cluster_id) + end end end diff --git a/app/controllers/projects/merge_requests/application_controller.rb b/app/controllers/projects/merge_requests/application_controller.rb index b7e99cb7ed0..0bb4e0fb5ee 100644 --- a/app/controllers/projects/merge_requests/application_controller.rb +++ b/app/controllers/projects/merge_requests/application_controller.rb @@ -48,12 +48,9 @@ class Projects::MergeRequests::ApplicationController < Projects::ApplicationCont end def set_pipeline_variables - @pipelines = - if can?(current_user, :read_pipeline, @merge_request.source_project) - @merge_request.all_pipelines - else - Ci::Pipeline.none - end + @pipelines = Ci::PipelinesForMergeRequestFinder + .new(@merge_request, current_user) + .execute end def close_merge_request_if_no_source_project diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb index 28aa1b300aa..3e077c1af37 100644 --- a/app/controllers/projects/merge_requests/creations_controller.rb +++ b/app/controllers/projects/merge_requests/creations_controller.rb @@ -32,13 +32,13 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap end def pipelines - @pipelines = @merge_request.all_pipelines + @pipelines = Ci::PipelinesForMergeRequestFinder.new(@merge_request, current_user).execute Gitlab::PollingInterval.set_header(response, interval: 10_000) render json: { pipelines: PipelineSerializer - .new(project: @project, current_user: @current_user) + .new(project: @project, current_user: current_user) .represent(@pipelines) } end diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb index 1bf143c9a91..98b0abc89e9 100644 --- a/app/controllers/projects/merge_requests/diffs_controller.rb +++ b/app/controllers/projects/merge_requests/diffs_controller.rb @@ -8,6 +8,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic before_action :commit before_action :define_diff_vars before_action :define_diff_comment_vars, except: [:diffs_batch, :diffs_metadata] + before_action :update_diff_discussion_positions! around_action :allow_gitaly_ref_name_caching @@ -171,4 +172,12 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic @notes.concat(draft_notes) end + + def update_diff_discussion_positions! + return unless Feature.enabled?(:merge_ref_head_comments, @merge_request.target_project, default_enabled: true) + return unless Feature.enabled?(:merge_red_head_comments_position_on_demand, @merge_request.target_project, default_enabled: true) + return if @merge_request.has_any_diff_note_positions? + + Discussions::CaptureDiffNotePositionsService.new(@merge_request).execute + end end diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 6c1ffc35276..e65e5531b88 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -35,15 +35,23 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo push_frontend_feature_flag(:mr_commit_neighbor_nav, @project, default_enabled: true) push_frontend_feature_flag(:multiline_comments, @project) push_frontend_feature_flag(:file_identifier_hash) - push_frontend_feature_flag(:batch_suggestions, @project) + push_frontend_feature_flag(:batch_suggestions, @project, default_enabled: true) end before_action do push_frontend_feature_flag(:vue_issuable_sidebar, @project.group) + push_frontend_feature_flag(:junit_pipeline_view, @project.group) end around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions] + feature_category :source_code_management, + unless: -> (action) { action.ends_with?("_reports") } + feature_category :code_testing, + only: [:test_reports, :coverage_reports, :terraform_reports] + feature_category :accessibility_testing, + only: [:accessibility_reports] + def index @merge_requests = @issuables @@ -76,7 +84,9 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo @issuable_sidebar = serializer.represent(@merge_request, serializer: 'sidebar') @current_user_data = UserSerializer.new(project: @project).represent(current_user, {}, MergeRequestUserEntity).to_json @show_whitespace_default = current_user.nil? || current_user.show_whitespace_in_diffs + @file_by_file_default = Feature.enabled?(:view_diffs_file_by_file) && current_user&.view_diffs_file_by_file @coverage_path = coverage_reports_project_merge_request_path(@project, @merge_request, format: :json) if @merge_request.has_coverage_reports? + @endpoint_metadata_url = endpoint_metadata_url(@project, @merge_request) set_pipeline_variables @@ -108,8 +118,8 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo # or from cache if already merged @commits = set_commits_for_rendering( - @merge_request.recent_commits.with_latest_pipeline(@merge_request.source_branch), - commits_count: @merge_request.commits_count + @merge_request.recent_commits.with_latest_pipeline(@merge_request.source_branch).with_markdown_cache, + commits_count: @merge_request.commits_count ) render json: { html: view_to_html_string('projects/merge_requests/_commits') } @@ -178,7 +188,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo end def update - @merge_request = ::MergeRequests::UpdateService.new(project, current_user, merge_request_params).execute(@merge_request) + @merge_request = ::MergeRequests::UpdateService.new(project, current_user, merge_request_update_params).execute(@merge_request) respond_to do |format| format.html do @@ -312,6 +322,10 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo private + def merge_request_update_params + merge_request_params.merge!(params.permit(:merge_request_diff_head_sha)) + end + def head_pipeline strong_memoize(:head_pipeline) do pipeline = @merge_request.head_pipeline @@ -422,6 +436,13 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo def authorize_read_actual_head_pipeline! return render_404 unless can?(current_user, :read_build, merge_request.actual_head_pipeline) end + + def endpoint_metadata_url(project, merge_request) + params = request.query_parameters + params[:view] = cookies[:diff_view] if params[:view].blank? && cookies[:diff_view].present? + + diffs_metadata_project_json_merge_request_path(project, merge_request, 'json', params) + end end Projects::MergeRequestsController.prepend_if_ee('EE::Projects::MergeRequestsController') diff --git a/app/controllers/projects/metrics_dashboard_controller.rb b/app/controllers/projects/metrics_dashboard_controller.rb new file mode 100644 index 00000000000..235ee1dfbf2 --- /dev/null +++ b/app/controllers/projects/metrics_dashboard_controller.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true +module Projects + class MetricsDashboardController < Projects::ApplicationController + # Metrics dashboard code is in the process of being decoupled from environments + # and is getting moved to this controller. Some code may be duplicated from + # app/controllers/projects/environments_controller.rb + # See https://gitlab.com/gitlab-org/gitlab/-/issues/226002 for more details. + + before_action :authorize_metrics_dashboard! + before_action do + push_frontend_feature_flag(:prometheus_computed_alerts) + end + + def show + if environment + render 'projects/environments/metrics' + else + render_404 + end + end + + private + + def environment + @environment ||= + if params[:environment] + project.environments.find(params[:environment]) + else + project.default_environment + end + end + end +end diff --git a/app/controllers/projects/pipelines/application_controller.rb b/app/controllers/projects/pipelines/application_controller.rb new file mode 100644 index 00000000000..92887750813 --- /dev/null +++ b/app/controllers/projects/pipelines/application_controller.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +# Abstract class encapsulating common logic for creating new controllers in a pipeline context + +module Projects + module Pipelines + class ApplicationController < Projects::ApplicationController + include Gitlab::Utils::StrongMemoize + + before_action :pipeline + before_action :authorize_read_pipeline! + + private + + def pipeline + strong_memoize(:pipeline) do + project.all_pipelines.find(params[:pipeline_id]).tap do |pipeline| + render_404 unless can?(current_user, :read_pipeline, pipeline) + end + end + end + end + end +end diff --git a/app/controllers/projects/pipelines/stages_controller.rb b/app/controllers/projects/pipelines/stages_controller.rb new file mode 100644 index 00000000000..ce08b49ce9f --- /dev/null +++ b/app/controllers/projects/pipelines/stages_controller.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +module Projects + module Pipelines + class StagesController < Projects::Pipelines::ApplicationController + before_action :authorize_update_pipeline! + + def play_manual + ::Ci::PlayManualStageService + .new(@project, current_user, pipeline: pipeline) + .execute(stage) + + respond_to do |format| + format.json do + render json: StageSerializer + .new(project: @project, current_user: @current_user) + .represent(stage) + end + end + end + + private + + def stage + @pipeline_stage ||= pipeline.find_stage_by_name!(params[:stage_name]) + end + end + end +end diff --git a/app/controllers/projects/pipelines/tests_controller.rb b/app/controllers/projects/pipelines/tests_controller.rb new file mode 100644 index 00000000000..f03274bf32e --- /dev/null +++ b/app/controllers/projects/pipelines/tests_controller.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +module Projects + module Pipelines + class TestsController < Projects::Pipelines::ApplicationController + before_action :validate_feature_flag! + before_action :authorize_read_build! + before_action :builds, only: [:show] + + def summary + respond_to do |format| + format.json do + render json: TestReportSummarySerializer + .new(project: project, current_user: @current_user) + .represent(pipeline.test_report_summary) + end + end + end + + def show + respond_to do |format| + format.json do + render json: TestSuiteSerializer + .new(project: project, current_user: @current_user) + .represent(test_suite, details: true) + end + end + end + + private + + def validate_feature_flag! + render_404 unless Feature.enabled?(:build_report_summary, project) + end + + # rubocop: disable CodeReuse/ActiveRecord + def builds + pipeline.latest_builds.where(id: build_params) + end + + def build_params + return [] unless params[:build_ids] + + params[:build_ids].split(",") + end + + def test_suite + if builds.present? + builds.map do |build| + build.collect_test_reports!(Gitlab::Ci::Reports::TestReports.new) + end.sum + else + render_404 + end + end + # rubocop: enable CodeReuse/ActiveRecord + end + end +end diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 0b6c0db211e..d8e11ddd423 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -2,6 +2,7 @@ class Projects::PipelinesController < Projects::ApplicationController include ::Gitlab::Utils::StrongMemoize + include Analytics::UniqueVisitsHelper before_action :whitelist_query_limiting, only: [:create, :retry] before_action :pipeline, except: [:index, :new, :create, :charts] @@ -12,14 +13,20 @@ class Projects::PipelinesController < Projects::ApplicationController before_action :authorize_update_pipeline!, only: [:retry, :cancel] before_action do push_frontend_feature_flag(:junit_pipeline_view, project) + push_frontend_feature_flag(:build_report_summary, project) push_frontend_feature_flag(:filter_pipelines_search, project, default_enabled: true) - push_frontend_feature_flag(:dag_pipeline_tab, project, default_enabled: false) + push_frontend_feature_flag(:dag_pipeline_tab, project, default_enabled: true) push_frontend_feature_flag(:pipelines_security_report_summary, project) end before_action :ensure_pipeline, only: [:show] + # Will be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/225596 + before_action :redirect_for_legacy_scope_filter, only: [:index], if: -> { request.format.html? } + around_action :allow_gitaly_ref_name_caching, only: [:index, :show] + track_unique_visits :charts, target_id: 'p_analytics_pipelines' + wrap_parameters Ci::Pipeline POLLING_INTERVAL = 10_000 @@ -31,9 +38,6 @@ class Projects::PipelinesController < Projects::ApplicationController .page(params[:page]) .per(30) - @running_count = limited_pipelines_count(project, 'running') - @pending_count = limited_pipelines_count(project, 'pending') - @finished_count = limited_pipelines_count(project, 'finished') @pipelines_count = limited_pipelines_count(project) respond_to do |format| @@ -44,10 +48,7 @@ class Projects::PipelinesController < Projects::ApplicationController render json: { pipelines: serialize_pipelines, count: { - all: @pipelines_count, - running: @running_count, - pending: @pending_count, - finished: @finished_count + all: @pipelines_count } } end @@ -186,7 +187,7 @@ class Projects::PipelinesController < Projects::ApplicationController format.json do render json: TestReportSerializer .new(current_user: @current_user) - .represent(pipeline_test_report, project: project) + .represent(pipeline_test_report, project: project, details: true) end end end @@ -226,6 +227,12 @@ class Projects::PipelinesController < Projects::ApplicationController render_404 unless pipeline end + def redirect_for_legacy_scope_filter + return unless %w[running pending].include?(params[:scope]) + + redirect_to url_for(safe_params.except(:scope).merge(status: safe_params[:scope])), status: :moved_permanently + end + # rubocop: disable CodeReuse/ActiveRecord def pipeline @pipeline ||= if params[:id].blank? && params[:latest] diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb index a2581e72257..db770d3e438 100644 --- a/app/controllers/projects/refs_controller.rb +++ b/app/controllers/projects/refs_controller.rb @@ -11,10 +11,6 @@ class Projects::RefsController < Projects::ApplicationController before_action :assign_ref_vars before_action :authorize_download_code! - before_action only: [:logs_tree] do - push_frontend_feature_flag(:vue_file_list_lfs_badge, default_enabled: true) - end - def switch respond_to do |format| format.html do @@ -57,22 +53,11 @@ class Projects::RefsController < Projects::ApplicationController render json: logs end - - # Deprecated due to https://gitlab.com/gitlab-org/gitlab/-/issues/36863 - # Will be removed soon https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29895 - format.js do - @logs, _ = tree_summary.summarize - @more_log_url = more_url(tree_summary.next_offset) if tree_summary.more? - end end end private - def more_url(offset) - logs_file_project_ref_path(@project, @ref, @path, offset: offset) - end - def validate_ref_id return not_found! if params[:id].present? && params[:id] !~ Gitlab::PathRegex.git_reference_regex end diff --git a/app/controllers/projects/releases_controller.rb b/app/controllers/projects/releases_controller.rb index d3285b64dab..d58755c2655 100644 --- a/app/controllers/projects/releases_controller.rb +++ b/app/controllers/projects/releases_controller.rb @@ -13,6 +13,7 @@ class Projects::ReleasesController < Projects::ApplicationController push_frontend_feature_flag(:release_asset_link_type, project, default_enabled: true) end before_action :authorize_update_release!, only: %i[edit update] + before_action :authorize_create_release!, only: :new def index respond_to do |format| @@ -25,11 +26,11 @@ class Projects::ReleasesController < Projects::ApplicationController def show return render_404 unless Feature.enabled?(:release_show_page, project, default_enabled: true) + end - respond_to do |format| - format.html do - render :show - end + def new + unless Feature.enabled?(:new_release_page, project) + redirect_to(new_project_tag_path(@project)) end end @@ -37,22 +38,12 @@ class Projects::ReleasesController < Projects::ApplicationController redirect_to link.url end - protected + private def releases ReleasesFinder.new(@project, current_user).execute end - def edit - respond_to do |format| - format.html do - render :edit - end - end - end - - private - def authorize_update_release! access_denied! unless can?(current_user, :update_release, release) end diff --git a/app/controllers/projects/service_desk_controller.rb b/app/controllers/projects/service_desk_controller.rb new file mode 100644 index 00000000000..bcd190bbc2c --- /dev/null +++ b/app/controllers/projects/service_desk_controller.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +class Projects::ServiceDeskController < Projects::ApplicationController + before_action :authorize_admin_project! + + def show + json_response + end + + def update + Projects::UpdateService.new(project, current_user, { service_desk_enabled: params[:service_desk_enabled] }).execute + + result = ServiceDeskSettings::UpdateService.new(project, current_user, setting_params).execute + + if result[:status] == :success + json_response + else + render json: { message: result[:message] }, status: :unprocessable_entity + end + end + + private + + def setting_params + params.permit(:issue_template_key, :outgoing_name, :project_key) + end + + def json_response + respond_to do |format| + service_desk_settings = project.service_desk_setting + + service_desk_attributes = + { + service_desk_address: project.service_desk_address, + service_desk_enabled: project.service_desk_enabled, + issue_template_key: service_desk_settings&.issue_template_key, + template_file_missing: service_desk_settings&.issue_template_missing?, + outgoing_name: service_desk_settings&.outgoing_name, + project_key: service_desk_settings&.project_key + } + + format.json { render json: service_desk_attributes } + end + end +end diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index 710ad546e64..6b7e253595c 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -12,7 +12,8 @@ class Projects::ServicesController < Projects::ApplicationController before_action :set_deprecation_notice_for_prometheus_service, only: [:edit, :update] before_action :redirect_deprecated_prometheus_service, only: [:update] before_action only: :edit do - push_frontend_feature_flag(:integration_form_refactor) + push_frontend_feature_flag(:integration_form_refactor, default_enabled: true) + push_frontend_feature_flag(:jira_issues_integration, @project, { default_enabled: true }) end respond_to :html @@ -20,17 +21,19 @@ class Projects::ServicesController < Projects::ApplicationController layout "project_settings" def edit + @admin_integration = Service.instance_for(service.type) end def update @service.attributes = service_params[:service] + @service.inherit_from_id = nil if service_params[:service][:inherit_from_id].blank? saved = @service.save(context: :manual_change) respond_to do |format| format.html do if saved - target_url = safe_redirect_path(params[:redirect_to]).presence || project_settings_integrations_path(@project) + target_url = safe_redirect_path(params[:redirect_to]).presence || edit_project_service_path(@project, @service) redirect_to target_url, notice: success_message else render 'edit' @@ -60,7 +63,7 @@ class Projects::ServicesController < Projects::ApplicationController return { error: true, message: _('Validations failed.'), service_response: @service.errors.full_messages.join(','), test_failed: false } end - result = Integrations::Test::ProjectService.new(@service, current_user, params[:event]).execute + result = ::Integrations::Test::ProjectService.new(@service, current_user, params[:event]).execute unless result[:success] return { error: true, message: _('Test failed.'), service_response: result[:message].to_s, test_failed: true } diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb index c2292511e0f..d7a6f1b0139 100644 --- a/app/controllers/projects/settings/operations_controller.rb +++ b/app/controllers/projects/settings/operations_controller.rb @@ -6,13 +6,13 @@ module Projects before_action :authorize_admin_operations! before_action :authorize_read_prometheus_alerts!, only: [:reset_alerting_token] - respond_to :json, only: [:reset_alerting_token] + before_action do + push_frontend_feature_flag(:pagerduty_webhook, project) + end - helper_method :error_tracking_setting + respond_to :json, only: [:reset_alerting_token, :reset_pagerduty_token] - def show - render locals: { prometheus_service: prometheus_service } - end + helper_method :error_tracking_setting def update result = ::Projects::Operations::UpdateService.new(project, current_user, update_params).execute @@ -42,14 +42,29 @@ module Projects end end + def reset_pagerduty_token + result = ::Projects::Operations::UpdateService + .new(project, current_user, pagerduty_token_params) + .execute + + if result[:status] == :success + pagerduty_token = project.incident_management_setting&.pagerduty_token + webhook_url = project_incidents_pagerduty_url(project, token: pagerduty_token) + + render json: { pagerduty_webhook_url: webhook_url, pagerduty_token: pagerduty_token } + else + render json: {}, status: :unprocessable_entity + end + end + private def alerting_params { alerting_setting_attributes: { regenerate_token: true } } end - def prometheus_service - project.find_or_initialize_service(::PrometheusService.to_param) + def pagerduty_token_params + { incident_management_setting_attributes: { regenerate_token: true } } end def render_update_response(result) diff --git a/app/controllers/projects/snippets/blobs_controller.rb b/app/controllers/projects/snippets/blobs_controller.rb new file mode 100644 index 00000000000..148fc7c96f8 --- /dev/null +++ b/app/controllers/projects/snippets/blobs_controller.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class Projects::Snippets::BlobsController < Projects::Snippets::ApplicationController + include Snippets::BlobsActions +end diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb index 5ee6abef804..49840e847f2 100644 --- a/app/controllers/projects/snippets_controller.rb +++ b/app/controllers/projects/snippets_controller.rb @@ -15,11 +15,11 @@ class Projects::SnippetsController < Projects::Snippets::ApplicationController before_action :authorize_admin_snippet!, only: [:destroy] def index - @snippet_counts = Snippets::CountService + @snippet_counts = ::Snippets::CountService .new(current_user, project: @project) .execute - @snippets = SnippetsFinder.new(current_user, project: @project, scope: params[:scope]) + @snippets = SnippetsFinder.new(current_user, project: @project, scope: params[:scope], sort: sort_param) .execute .page(params[:page]) .inc_author @@ -35,7 +35,7 @@ class Projects::SnippetsController < Projects::Snippets::ApplicationController def create create_params = snippet_params.merge(spammable_params) - service_response = Snippets::CreateService.new(project, current_user, create_params).execute + service_response = ::Snippets::CreateService.new(project, current_user, create_params).execute @snippet = service_response.payload[:snippet] handle_repository_error(:new) diff --git a/app/controllers/projects/stages_controller.rb b/app/controllers/projects/stages_controller.rb deleted file mode 100644 index c8db5b1277f..00000000000 --- a/app/controllers/projects/stages_controller.rb +++ /dev/null @@ -1,25 +0,0 @@ -# frozen_string_literal: true - -class Projects::StagesController < Projects::PipelinesController - before_action :authorize_update_pipeline! - - def play_manual - ::Ci::PlayManualStageService - .new(@project, current_user, pipeline: pipeline) - .execute(stage) - - respond_to do |format| - format.json do - render json: StageSerializer - .new(project: @project, current_user: @current_user) - .represent(stage) - end - end - end - - private - - def stage - @pipeline_stage ||= pipeline.find_stage_by_name!(params[:stage_name]) - end -end diff --git a/app/controllers/projects/static_site_editor_controller.rb b/app/controllers/projects/static_site_editor_controller.rb index 74f28c3da67..9ec50ff8196 100644 --- a/app/controllers/projects/static_site_editor_controller.rb +++ b/app/controllers/projects/static_site_editor_controller.rb @@ -9,6 +9,9 @@ class Projects::StaticSiteEditorController < Projects::ApplicationController prepend_before_action :authenticate_user!, only: [:show] before_action :assign_ref_and_path, only: [:show] before_action :authorize_edit_tree!, only: [:show] + before_action do + push_frontend_feature_flag(:sse_image_uploads) + end def show @config = Gitlab::StaticSiteEditor::Config.new(@repository, @ref, @path, params[:return_url]) diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb index 9cb345724cc..638e1a05c18 100644 --- a/app/controllers/projects/tree_controller.rb +++ b/app/controllers/projects/tree_controller.rb @@ -15,26 +15,14 @@ class Projects::TreeController < Projects::ApplicationController before_action :authorize_download_code! before_action :authorize_edit_tree!, only: [:create_dir] - before_action only: [:show] do - push_frontend_feature_flag(:vue_file_list_lfs_badge, default_enabled: true) - end - def show - return render_404 unless @repository.commit(@ref) + return render_404 unless @commit if tree.entries.empty? if @repository.blob_at(@commit.id, @path) - return redirect_to project_blob_path(@project, File.join(@ref, @path)) + redirect_to project_blob_path(@project, File.join(@ref, @path)) elsif @path.present? - return redirect_to_tree_root_for_missing_path(@project, @ref, @path) - end - end - - respond_to do |format| - format.html do - lfs_blob_ids if Feature.disabled?(:vue_file_list, @project, default_enabled: true) - - @last_commit = @repository.last_commit_for_path(@commit.id, @tree.path) || @commit + redirect_to_tree_root_for_missing_path(@project, @ref, @path) end end end diff --git a/app/controllers/projects/variables_controller.rb b/app/controllers/projects/variables_controller.rb index 1dffc57fcf0..2cc030d18fc 100644 --- a/app/controllers/projects/variables_controller.rb +++ b/app/controllers/projects/variables_controller.rb @@ -6,7 +6,7 @@ class Projects::VariablesController < Projects::ApplicationController def show respond_to do |format| format.json do - render status: :ok, json: { variables: VariableSerializer.new.represent(@project.variables) } + render status: :ok, json: { variables: ::Ci::VariableSerializer.new.represent(@project.variables) } end end end @@ -26,7 +26,7 @@ class Projects::VariablesController < Projects::ApplicationController private def render_variables - render status: :ok, json: { variables: VariableSerializer.new.represent(@project.variables) } + render status: :ok, json: { variables: ::Ci::VariableSerializer.new.represent(@project.variables) } end def render_error diff --git a/app/controllers/projects/wikis_controller.rb b/app/controllers/projects/wikis_controller.rb index 85e643aa212..d0aa733cadb 100644 --- a/app/controllers/projects/wikis_controller.rb +++ b/app/controllers/projects/wikis_controller.rb @@ -2,7 +2,6 @@ class Projects::WikisController < Projects::ApplicationController include WikiActions - include PreviewMarkdown alias_method :container, :project |