diff options
Diffstat (limited to 'app/controllers/projects')
109 files changed, 689 insertions, 141 deletions
diff --git a/app/controllers/projects/alert_management_controller.rb b/app/controllers/projects/alert_management_controller.rb index 054dc8e6a35..0d0ef9b05cb 100644 --- a/app/controllers/projects/alert_management_controller.rb +++ b/app/controllers/projects/alert_management_controller.rb @@ -3,10 +3,13 @@ class Projects::AlertManagementController < Projects::ApplicationController before_action :authorize_read_alert_management_alert! + feature_category :alert_management + def index end def details @alert_id = params[:id] + push_frontend_feature_flag(:expose_environment_path_in_alert_details, @project) end end diff --git a/app/controllers/projects/alerting/notifications_controller.rb b/app/controllers/projects/alerting/notifications_controller.rb index fef8235628d..2241ded2db8 100644 --- a/app/controllers/projects/alerting/notifications_controller.rb +++ b/app/controllers/projects/alerting/notifications_controller.rb @@ -10,6 +10,8 @@ module Projects prepend_before_action :repository, :project_without_auth + feature_category :alert_management + def create token = extract_alert_manager_token(request) result = notify_service.execute(token) diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index 652687932fd..f6a92b07295 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -15,6 +15,8 @@ class Projects::ArtifactsController < Projects::ApplicationController MAX_PER_PAGE = 20 + feature_category :continuous_integration + def index # Loading artifacts is very expensive in projects with a lot of artifacts. # This feature flag prevents a DOS attack vector. diff --git a/app/controllers/projects/autocomplete_sources_controller.rb b/app/controllers/projects/autocomplete_sources_controller.rb index 605d70d440b..e9c533daa80 100644 --- a/app/controllers/projects/autocomplete_sources_controller.rb +++ b/app/controllers/projects/autocomplete_sources_controller.rb @@ -3,6 +3,11 @@ class Projects::AutocompleteSourcesController < Projects::ApplicationController before_action :authorize_read_milestone!, only: :milestones + feature_category :issue_tracking, [:issues, :labels, :milestones, :commands] + feature_category :code_review, [:merge_requests] + feature_category :users, [:members] + feature_category :snippets, [:snippets] + def members render json: ::Projects::ParticipantsService.new(@project, current_user).execute(target) end diff --git a/app/controllers/projects/avatars_controller.rb b/app/controllers/projects/avatars_controller.rb index 6e6bf09a32a..f228206032d 100644 --- a/app/controllers/projects/avatars_controller.rb +++ b/app/controllers/projects/avatars_controller.rb @@ -5,6 +5,8 @@ class Projects::AvatarsController < Projects::ApplicationController before_action :authorize_admin_project!, only: [:destroy] + feature_category :projects + def show @blob = @repository.blob_at_branch(@repository.root_ref, @project.avatar_in_git) diff --git a/app/controllers/projects/badges_controller.rb b/app/controllers/projects/badges_controller.rb index eb47fec2b7e..855965ca6e1 100644 --- a/app/controllers/projects/badges_controller.rb +++ b/app/controllers/projects/badges_controller.rb @@ -6,6 +6,8 @@ class Projects::BadgesController < Projects::ApplicationController before_action :no_cache_headers, only: [:pipeline, :coverage] before_action :authorize_read_build!, only: [:pipeline, :coverage] + feature_category :continuous_integration + def pipeline pipeline_status = Gitlab::Badge::Pipeline::Status .new(project, params[:ref], opts: { diff --git a/app/controllers/projects/blame_controller.rb b/app/controllers/projects/blame_controller.rb index 374b4921dbc..d5de0d38152 100644 --- a/app/controllers/projects/blame_controller.rb +++ b/app/controllers/projects/blame_controller.rb @@ -9,6 +9,8 @@ class Projects::BlameController < Projects::ApplicationController before_action :assign_ref_vars before_action :authorize_download_code! + feature_category :source_code_management + def show @blob = @repository.blob_at(@commit.id, @path) diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index 1568d9966dd..c6251d27b05 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -33,13 +33,14 @@ class Projects::BlobController < Projects::ApplicationController before_action :set_last_commit_sha, only: [:edit, :update] before_action only: :show do - push_frontend_feature_flag(:code_navigation, @project, default_enabled: true) - push_frontend_feature_flag(:suggest_pipeline) if experiment_enabled?(:suggest_pipeline) + push_frontend_experiment(:suggest_pipeline) push_frontend_feature_flag(:gitlab_ci_yml_preview, @project, default_enabled: false) end track_redis_hll_event :create, :update, name: 'g_edit_by_sfe', feature: :track_editor_edit_actions, feature_default_enabled: true + feature_category :source_code_management + def new commit unless @repository.empty? end diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb index 5ed35094476..193352ffa70 100644 --- a/app/controllers/projects/boards_controller.rb +++ b/app/controllers/projects/boards_controller.rb @@ -12,6 +12,8 @@ class Projects::BoardsController < Projects::ApplicationController push_frontend_feature_flag(:boards_with_swimlanes, project, default_enabled: false) end + feature_category :boards + private def assign_endpoint_vars diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index 7cfb4a508da..9124728ee25 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -13,6 +13,8 @@ class Projects::BranchesController < Projects::ApplicationController before_action :redirect_for_legacy_index_sort_or_search, only: [:index] before_action :limit_diverging_commit_counts!, only: [:diverging_commit_counts] + feature_category :source_code_management + def index respond_to do |format| format.html do diff --git a/app/controllers/projects/build_artifacts_controller.rb b/app/controllers/projects/build_artifacts_controller.rb index 99f4524eec5..148080a71f4 100644 --- a/app/controllers/projects/build_artifacts_controller.rb +++ b/app/controllers/projects/build_artifacts_controller.rb @@ -8,6 +8,8 @@ class Projects::BuildArtifactsController < Projects::ApplicationController before_action :extract_ref_name_and_path before_action :validate_artifacts!, except: [:download] + feature_category :continuous_integration + def download redirect_to download_project_job_artifacts_path(project, job, params: request.query_parameters) end diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb index 6b3d70cb720..c5f6ed1c105 100644 --- a/app/controllers/projects/builds_controller.rb +++ b/app/controllers/projects/builds_controller.rb @@ -3,6 +3,8 @@ class Projects::BuildsController < Projects::ApplicationController before_action :authorize_read_build! + feature_category :continuous_integration + def index redirect_to project_jobs_path(project) end diff --git a/app/controllers/projects/ci/daily_build_group_report_results_controller.rb b/app/controllers/projects/ci/daily_build_group_report_results_controller.rb index b36c5f1aea6..d05ab1b4977 100644 --- a/app/controllers/projects/ci/daily_build_group_report_results_controller.rb +++ b/app/controllers/projects/ci/daily_build_group_report_results_controller.rb @@ -6,10 +6,11 @@ class Projects::Ci::DailyBuildGroupReportResultsController < Projects::Applicati MAX_ITEMS = 1000 REPORT_WINDOW = 90.days - before_action :validate_feature_flag! before_action :authorize_read_build_report_results! before_action :validate_param_type! + feature_category :continuous_integration + def index respond_to do |format| format.csv { send_data(render_csv(report_results), type: 'text/csv; charset=utf-8') } @@ -19,10 +20,6 @@ class Projects::Ci::DailyBuildGroupReportResultsController < Projects::Applicati private - def validate_feature_flag! - render_404 unless Feature.enabled?(:ci_download_daily_code_coverage, project, default_enabled: true) - end - def validate_param_type! respond_422 unless allowed_param_types.include?(param_type) end @@ -43,7 +40,7 @@ class Projects::Ci::DailyBuildGroupReportResultsController < Projects::Applicati end def report_results - Ci::DailyBuildGroupReportResultsFinder.new(finder_params).execute + Ci::DailyBuildGroupReportResultsFinder.new(**finder_params).execute end def finder_params diff --git a/app/controllers/projects/ci/lints_controller.rb b/app/controllers/projects/ci/lints_controller.rb index 813a0a9ddd5..7e900fc6051 100644 --- a/app/controllers/projects/ci/lints_controller.rb +++ b/app/controllers/projects/ci/lints_controller.rb @@ -6,6 +6,8 @@ class Projects::Ci::LintsController < Projects::ApplicationController push_frontend_feature_flag(:ci_lint_vue, project) end + feature_category :pipeline_authoring + def show end diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index b0c6f3cc6a1..2e48f2f0e45 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -21,6 +21,8 @@ class Projects::CommitController < Projects::ApplicationController BRANCH_SEARCH_LIMIT = 1000 + feature_category :source_code_management + def show apply_diff_view_cookie! diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb index b161e44660e..d267ab732f9 100644 --- a/app/controllers/projects/commits_controller.rb +++ b/app/controllers/projects/commits_controller.rb @@ -15,6 +15,8 @@ class Projects::CommitsController < Projects::ApplicationController before_action :validate_ref!, except: :commits_root before_action :set_commits, except: :commits_root + feature_category :source_code_management + def commits_root redirect_to project_commits_path(@project, @project.default_branch) end diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb index 943277afe95..6be0b465402 100644 --- a/app/controllers/projects/compare_controller.rb +++ b/app/controllers/projects/compare_controller.rb @@ -19,6 +19,8 @@ class Projects::CompareController < Projects::ApplicationController # Validation before_action :validate_refs! + feature_category :source_code_management + def index end diff --git a/app/controllers/projects/confluences_controller.rb b/app/controllers/projects/confluences_controller.rb index d563b34a362..fccbdf0bf91 100644 --- a/app/controllers/projects/confluences_controller.rb +++ b/app/controllers/projects/confluences_controller.rb @@ -3,6 +3,8 @@ class Projects::ConfluencesController < Projects::ApplicationController before_action :ensure_confluence + feature_category :integrations + def show end diff --git a/app/controllers/projects/cycle_analytics/events_controller.rb b/app/controllers/projects/cycle_analytics/events_controller.rb index c69bf029c73..3a5dd23047c 100644 --- a/app/controllers/projects/cycle_analytics/events_controller.rb +++ b/app/controllers/projects/cycle_analytics/events_controller.rb @@ -11,6 +11,8 @@ module Projects before_action :authorize_read_issue!, only: [:issue, :production] before_action :authorize_read_merge_request!, only: [:code, :review] + feature_category :planning_analytics + def issue render_events(cycle_analytics[:issue].events) end diff --git a/app/controllers/projects/cycle_analytics_controller.rb b/app/controllers/projects/cycle_analytics_controller.rb index ef97bc795f9..1ddc9d567e0 100644 --- a/app/controllers/projects/cycle_analytics_controller.rb +++ b/app/controllers/projects/cycle_analytics_controller.rb @@ -12,6 +12,8 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController track_unique_visits :show, target_id: 'p_analytics_valuestream' + feature_category :planning_analytics + def show @cycle_analytics = ::CycleAnalytics::ProjectLevel.new(@project, options: options(cycle_analytics_project_params)) diff --git a/app/controllers/projects/deploy_keys_controller.rb b/app/controllers/projects/deploy_keys_controller.rb index 4f4adaea56e..ce25f86d692 100644 --- a/app/controllers/projects/deploy_keys_controller.rb +++ b/app/controllers/projects/deploy_keys_controller.rb @@ -10,6 +10,8 @@ class Projects::DeployKeysController < Projects::ApplicationController layout 'project_settings' + feature_category :continuous_delivery + def index respond_to do |format| format.html { redirect_to_repository } diff --git a/app/controllers/projects/deploy_tokens_controller.rb b/app/controllers/projects/deploy_tokens_controller.rb index 830b1f4fe4a..3c890bbafdf 100644 --- a/app/controllers/projects/deploy_tokens_controller.rb +++ b/app/controllers/projects/deploy_tokens_controller.rb @@ -3,6 +3,8 @@ class Projects::DeployTokensController < Projects::ApplicationController before_action :authorize_admin_project! + feature_category :continuous_delivery + def revoke @token = @project.deploy_tokens.find(params[:id]) @token.revoke! diff --git a/app/controllers/projects/deployments_controller.rb b/app/controllers/projects/deployments_controller.rb index 1344cf775e4..231684427fb 100644 --- a/app/controllers/projects/deployments_controller.rb +++ b/app/controllers/projects/deployments_controller.rb @@ -3,6 +3,8 @@ class Projects::DeploymentsController < Projects::ApplicationController before_action :authorize_read_deployment! + feature_category :continuous_delivery + # rubocop: disable CodeReuse/ActiveRecord def index deployments = environment.deployments.reorder(created_at: :desc) diff --git a/app/controllers/projects/design_management/designs_controller.rb b/app/controllers/projects/design_management/designs_controller.rb index fec09fa9515..550d8578396 100644 --- a/app/controllers/projects/design_management/designs_controller.rb +++ b/app/controllers/projects/design_management/designs_controller.rb @@ -3,6 +3,8 @@ class Projects::DesignManagement::DesignsController < Projects::ApplicationController before_action :authorize_read_design! + feature_category :design_management + private def authorize_read_design! diff --git a/app/controllers/projects/discussions_controller.rb b/app/controllers/projects/discussions_controller.rb index 06231607f73..b9ab1076999 100644 --- a/app/controllers/projects/discussions_controller.rb +++ b/app/controllers/projects/discussions_controller.rb @@ -9,6 +9,8 @@ class Projects::DiscussionsController < Projects::ApplicationController before_action :discussion, only: [:resolve, :unresolve] before_action :authorize_resolve_discussion!, only: [:resolve, :unresolve] + feature_category :issue_tracking + def resolve Discussions::ResolveService.new(project, current_user, one_or_more_discussions: discussion).execute diff --git a/app/controllers/projects/environments/prometheus_api_controller.rb b/app/controllers/projects/environments/prometheus_api_controller.rb index f0bb5360f84..97810d7d439 100644 --- a/app/controllers/projects/environments/prometheus_api_controller.rb +++ b/app/controllers/projects/environments/prometheus_api_controller.rb @@ -5,6 +5,8 @@ class Projects::Environments::PrometheusApiController < Projects::ApplicationCon before_action :proxyable + feature_category :metrics + private def proxyable diff --git a/app/controllers/projects/environments/sample_metrics_controller.rb b/app/controllers/projects/environments/sample_metrics_controller.rb index 9176c7cbd56..3df20810cb3 100644 --- a/app/controllers/projects/environments/sample_metrics_controller.rb +++ b/app/controllers/projects/environments/sample_metrics_controller.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class Projects::Environments::SampleMetricsController < Projects::ApplicationController + feature_category :metrics + def query result = Metrics::SampleMetricsService.new(params[:identifier], range_start: params[:start], range_end: params[:end]).query diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb index 71195fdb892..c37abf82fe9 100644 --- a/app/controllers/projects/environments_controller.rb +++ b/app/controllers/projects/environments_controller.rb @@ -25,6 +25,8 @@ class Projects::EnvironmentsController < Projects::ApplicationController before_action :expire_etag_cache, only: [:index], unless: -> { request.format.json? } after_action :expire_etag_cache, only: [:cancel_auto_stop] + feature_category :continuous_delivery + def index @environments = project.environments .with_state(params[:scope] || :available) diff --git a/app/controllers/projects/error_tracking/base_controller.rb b/app/controllers/projects/error_tracking/base_controller.rb index 6efc6d00702..ffbe487d8a1 100644 --- a/app/controllers/projects/error_tracking/base_controller.rb +++ b/app/controllers/projects/error_tracking/base_controller.rb @@ -3,6 +3,8 @@ class Projects::ErrorTracking::BaseController < Projects::ApplicationController POLLING_INTERVAL = 1_000 + feature_category :error_tracking + def set_polling_interval Gitlab::PollingInterval.set_header(response, interval: POLLING_INTERVAL) end diff --git a/app/controllers/projects/error_tracking/projects_controller.rb b/app/controllers/projects/error_tracking/projects_controller.rb index 75a2c976d8b..d59cbc25d25 100644 --- a/app/controllers/projects/error_tracking/projects_controller.rb +++ b/app/controllers/projects/error_tracking/projects_controller.rb @@ -7,6 +7,8 @@ module Projects before_action :authorize_read_sentry_issue! + feature_category :error_tracking + def index service = ::ErrorTracking::ListProjectsService.new( project, diff --git a/app/controllers/projects/feature_flags_clients_controller.rb b/app/controllers/projects/feature_flags_clients_controller.rb new file mode 100644 index 00000000000..9a1f8932a27 --- /dev/null +++ b/app/controllers/projects/feature_flags_clients_controller.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +class Projects::FeatureFlagsClientsController < Projects::ApplicationController + before_action :authorize_admin_feature_flags_client! + before_action :feature_flags_client + + feature_category :feature_flags + + def reset_token + feature_flags_client.reset_token! + + respond_to do |format| + format.json do + render json: feature_flags_client_token_json, status: :ok + end + end + end + + private + + def feature_flags_client + project.operations_feature_flags_client || not_found + end + + def feature_flags_client_token_json + FeatureFlagsClientSerializer.new + .represent_token(feature_flags_client) + end +end diff --git a/app/controllers/projects/feature_flags_controller.rb b/app/controllers/projects/feature_flags_controller.rb new file mode 100644 index 00000000000..e9d450a6ce3 --- /dev/null +++ b/app/controllers/projects/feature_flags_controller.rb @@ -0,0 +1,174 @@ +# frozen_string_literal: true + +class Projects::FeatureFlagsController < Projects::ApplicationController + respond_to :html + + before_action :authorize_read_feature_flag! + before_action :authorize_create_feature_flag!, only: [:new, :create] + before_action :authorize_update_feature_flag!, only: [:edit, :update] + before_action :authorize_destroy_feature_flag!, only: [:destroy] + + before_action :feature_flag, only: [:edit, :update, :destroy] + + before_action :ensure_legacy_flags_writable!, only: [:update] + + before_action do + push_frontend_feature_flag(:feature_flag_permissions) + push_frontend_feature_flag(:feature_flags_new_version, project, default_enabled: true) + push_frontend_feature_flag(:feature_flags_legacy_read_only, project, default_enabled: true) + push_frontend_feature_flag(:feature_flags_legacy_read_only_override, project) + end + + feature_category :feature_flags + + def index + @feature_flags = FeatureFlagsFinder + .new(project, current_user, scope: params[:scope]) + .execute + .page(params[:page]) + .per(30) + + respond_to do |format| + format.html + format.json do + Gitlab::PollingInterval.set_header(response, interval: 10_000) + + render json: { feature_flags: feature_flags_json }.merge(summary_json) + end + end + end + + def new + end + + def show + respond_to do |format| + format.json do + Gitlab::PollingInterval.set_header(response, interval: 10_000) + + render_success_json(feature_flag) + end + end + end + + def create + result = FeatureFlags::CreateService.new(project, current_user, create_params).execute + + if result[:status] == :success + respond_to do |format| + format.json { render_success_json(result[:feature_flag]) } + end + else + respond_to do |format| + format.json { render_error_json(result[:message]) } + end + end + end + + def edit + end + + def update + result = FeatureFlags::UpdateService.new(project, current_user, update_params).execute(feature_flag) + + if result[:status] == :success + respond_to do |format| + format.json { render_success_json(result[:feature_flag]) } + end + else + respond_to do |format| + format.json { render_error_json(result[:message]) } + end + end + end + + def destroy + result = FeatureFlags::DestroyService.new(project, current_user).execute(feature_flag) + + if result[:status] == :success + respond_to do |format| + format.html { redirect_to_index(notice: _('Feature flag was successfully removed.')) } + format.json { render_success_json(feature_flag) } + end + else + respond_to do |format| + format.html { redirect_to_index(alert: _('Feature flag was not removed.')) } + format.json { render_error_json(result[:message]) } + end + end + end + + protected + + def feature_flag + @feature_flag ||= @noteable = if new_version_feature_flags_enabled? + project.operations_feature_flags.find_by_iid!(params[:iid]) + else + project.operations_feature_flags.legacy_flag.find_by_iid!(params[:iid]) + end + end + + def new_version_feature_flags_enabled? + ::Feature.enabled?(:feature_flags_new_version, project, default_enabled: true) + end + + def ensure_legacy_flags_writable! + if ::Feature.enabled?(:feature_flags_legacy_read_only, project, default_enabled: true) && + ::Feature.disabled?(:feature_flags_legacy_read_only_override, project) && + feature_flag.legacy_flag? + render_error_json(['Legacy feature flags are read-only']) + end + end + + def create_params + params.require(:operations_feature_flag) + .permit(:name, :description, :active, :version, + scopes_attributes: [:environment_scope, :active, + strategies: [:name, parameters: [:groupId, :percentage, :userIds]]], + strategies_attributes: [:name, :user_list_id, + parameters: [:groupId, :percentage, :userIds, :rollout, :stickiness], + scopes_attributes: [:environment_scope]]) + end + + def update_params + params.require(:operations_feature_flag) + .permit(:name, :description, :active, + scopes_attributes: [:id, :environment_scope, :active, :_destroy, + strategies: [:name, parameters: [:groupId, :percentage, :userIds]]], + strategies_attributes: [:id, :name, :user_list_id, :_destroy, + parameters: [:groupId, :percentage, :userIds, :rollout, :stickiness], + scopes_attributes: [:id, :environment_scope, :_destroy]]) + end + + def feature_flag_json(feature_flag) + FeatureFlagSerializer + .new(project: @project, current_user: @current_user) + .represent(feature_flag) + end + + def feature_flags_json + FeatureFlagSerializer + .new(project: @project, current_user: @current_user) + .with_pagination(request, response) + .represent(@feature_flags) + end + + def summary_json + FeatureFlagSummarySerializer + .new(project: @project, current_user: @current_user) + .represent(@project) + end + + def redirect_to_index(**args) + redirect_to project_feature_flags_path(@project), status: :found, **args + end + + def render_success_json(feature_flag) + render json: feature_flag_json(feature_flag), status: :ok + end + + def render_error_json(messages) + render json: { message: messages }, + status: :bad_request + end +end diff --git a/app/controllers/projects/feature_flags_user_lists_controller.rb b/app/controllers/projects/feature_flags_user_lists_controller.rb new file mode 100644 index 00000000000..7be3254e966 --- /dev/null +++ b/app/controllers/projects/feature_flags_user_lists_controller.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +class Projects::FeatureFlagsUserListsController < Projects::ApplicationController + before_action :authorize_admin_feature_flags_user_lists! + before_action :user_list, only: [:edit, :show] + + feature_category :feature_flags + + def new + end + + def edit + end + + def show + end + + private + + def user_list + @user_list = project.operations_feature_flags_user_lists.find_by_iid!(params[:iid]) + end +end diff --git a/app/controllers/projects/find_file_controller.rb b/app/controllers/projects/find_file_controller.rb index c026e9ff332..89e72d98a33 100644 --- a/app/controllers/projects/find_file_controller.rb +++ b/app/controllers/projects/find_file_controller.rb @@ -10,6 +10,8 @@ class Projects::FindFileController < Projects::ApplicationController before_action :assign_ref_vars before_action :authorize_download_code! + feature_category :source_code_management + def show return render_404 unless @repository.commit(@ref) diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb index c6b6b825bb7..1c2930f6e9b 100644 --- a/app/controllers/projects/forks_controller.rb +++ b/app/controllers/projects/forks_controller.rb @@ -14,6 +14,8 @@ class Projects::ForksController < Projects::ApplicationController before_action :authorize_fork_project!, only: [:new, :create] before_action :authorize_fork_namespace!, only: [:create] + feature_category :source_code_management + def index @total_forks_count = project.forks.size @public_forks_count = project.forks.public_only.size diff --git a/app/controllers/projects/grafana_api_controller.rb b/app/controllers/projects/grafana_api_controller.rb index c9870f1be2b..9c5d6c8ebc3 100644 --- a/app/controllers/projects/grafana_api_controller.rb +++ b/app/controllers/projects/grafana_api_controller.rb @@ -4,6 +4,8 @@ class Projects::GrafanaApiController < Projects::ApplicationController include RenderServiceResults include MetricsDashboard + feature_category :metrics + def proxy result = ::Grafana::ProxyService.new( project, diff --git a/app/controllers/projects/graphs_controller.rb b/app/controllers/projects/graphs_controller.rb index 9b889f9e837..2b030793c58 100644 --- a/app/controllers/projects/graphs_controller.rb +++ b/app/controllers/projects/graphs_controller.rb @@ -11,6 +11,8 @@ class Projects::GraphsController < Projects::ApplicationController track_unique_visits :charts, target_id: 'p_analytics_repo' + feature_category :source_code_management + def show respond_to do |format| format.html @@ -57,7 +59,6 @@ class Projects::GraphsController < Projects::ApplicationController end def get_daily_coverage_options - return unless Feature.enabled?(:ci_download_daily_code_coverage, @project, default_enabled: true) return unless can?(current_user, :read_build_report_results, project) date_today = Date.current diff --git a/app/controllers/projects/group_links_controller.rb b/app/controllers/projects/group_links_controller.rb index a30c455a7e4..c6c90ffaba2 100644 --- a/app/controllers/projects/group_links_controller.rb +++ b/app/controllers/projects/group_links_controller.rb @@ -5,6 +5,8 @@ class Projects::GroupLinksController < Projects::ApplicationController before_action :authorize_admin_project! before_action :authorize_admin_project_member!, only: [:update] + feature_category :subgroups + def create group = Group.find(params[:link_group_id]) if params[:link_group_id].present? @@ -21,8 +23,17 @@ class Projects::GroupLinksController < Projects::ApplicationController end def update - @group_link = @project.project_group_links.find(params[:id]) - Projects::GroupLinks::UpdateService.new(@group_link).execute(group_link_params) + group_link = @project.project_group_links.find(params[:id]) + Projects::GroupLinks::UpdateService.new(group_link).execute(group_link_params) + + if group_link.expires? + render json: { + expires_in: helpers.distance_of_time_in_words_to_now(group_link.expires_at), + expires_soon: group_link.expires_soon? + } + else + render json: {} + end end def destroy diff --git a/app/controllers/projects/hook_logs_controller.rb b/app/controllers/projects/hook_logs_controller.rb index ed7e7b68acb..99ebe3335c0 100644 --- a/app/controllers/projects/hook_logs_controller.rb +++ b/app/controllers/projects/hook_logs_controller.rb @@ -12,6 +12,8 @@ class Projects::HookLogsController < Projects::ApplicationController layout 'project_settings' + feature_category :integrations + def show end diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb index 2f4dc1ddc3a..8dabf3e640b 100644 --- a/app/controllers/projects/hooks_controller.rb +++ b/app/controllers/projects/hooks_controller.rb @@ -12,6 +12,8 @@ class Projects::HooksController < Projects::ApplicationController layout "project_settings" + feature_category :integrations + def index @hooks = @project.hooks @hook = ProjectHook.new @@ -50,7 +52,7 @@ class Projects::HooksController < Projects::ApplicationController end def destroy - hook.destroy + destroy_hook(hook) redirect_to action: :index, status: :found end diff --git a/app/controllers/projects/import/jira_controller.rb b/app/controllers/projects/import/jira_controller.rb index 976ac7df976..8418a607659 100644 --- a/app/controllers/projects/import/jira_controller.rb +++ b/app/controllers/projects/import/jira_controller.rb @@ -7,6 +7,8 @@ module Projects before_action :authorize_read_project! before_action :validate_jira_import_settings! + feature_category :integrations + def show end diff --git a/app/controllers/projects/imports_controller.rb b/app/controllers/projects/imports_controller.rb index 9bed12fd151..6cdd1c0bc8c 100644 --- a/app/controllers/projects/imports_controller.rb +++ b/app/controllers/projects/imports_controller.rb @@ -11,6 +11,8 @@ class Projects::ImportsController < Projects::ApplicationController before_action :redirect_if_progress, except: :show before_action :redirect_if_no_import, only: :show + feature_category :importers + def new end diff --git a/app/controllers/projects/incident_management/pager_duty_incidents_controller.rb b/app/controllers/projects/incident_management/pager_duty_incidents_controller.rb index dac1640dd08..f1264ca4a45 100644 --- a/app/controllers/projects/incident_management/pager_duty_incidents_controller.rb +++ b/app/controllers/projects/incident_management/pager_duty_incidents_controller.rb @@ -10,6 +10,8 @@ module Projects prepend_before_action :project_without_auth + feature_category :incident_management + def create result = webhook_processor.execute(params[:token]) diff --git a/app/controllers/projects/incidents_controller.rb b/app/controllers/projects/incidents_controller.rb index 12cc4dde1f4..3395e75666e 100644 --- a/app/controllers/projects/incidents_controller.rb +++ b/app/controllers/projects/incidents_controller.rb @@ -1,8 +1,45 @@ # frozen_string_literal: true class Projects::IncidentsController < Projects::ApplicationController - before_action :authorize_read_incidents! + include IssuableActions + include Gitlab::Utils::StrongMemoize + + before_action :authorize_read_issue! + before_action :load_incident, only: [:show] + + feature_category :incident_management def index end + + private + + def incident + strong_memoize(:incident) do + incident_finder + .execute + .inc_relations_for_view + .iid_in(params[:id]) + .without_order + .first + end + end + + def load_incident + @issue = incident # needed by rendered view + return render_404 unless can?(current_user, :read_issue, incident) + + @noteable = incident + @note = incident.project.notes.new(noteable: issuable) + end + + alias_method :issuable, :incident + + def incident_finder + IssuesFinder.new(current_user, project_id: @project.id, issue_types: :incident) + end + + def serializer + IssueSerializer.new(current_user: current_user, project: incident.project) + end end diff --git a/app/controllers/projects/issue_links_controller.rb b/app/controllers/projects/issue_links_controller.rb index 2f7489373ed..35f3e00fae7 100644 --- a/app/controllers/projects/issue_links_controller.rb +++ b/app/controllers/projects/issue_links_controller.rb @@ -7,6 +7,8 @@ module Projects before_action :authorize_admin_issue_link!, only: [:create, :destroy] before_action :authorize_issue_link_association!, only: :destroy + feature_category :issue_tracking + private def authorize_admin_issue_link! diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 7f0d23b79ce..9a8965dbeb6 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -44,8 +44,6 @@ class Projects::IssuesController < Projects::ApplicationController push_frontend_feature_flag(:vue_issuable_sidebar, project.group) push_frontend_feature_flag(:tribute_autocomplete, @project) push_frontend_feature_flag(:vue_issuables_list, project) - push_frontend_feature_flag(:design_management_todo_button, project, default_enabled: true) - push_frontend_feature_flag(:vue_sidebar_labels, @project) end before_action only: :show do @@ -53,10 +51,13 @@ class Projects::IssuesController < Projects::ApplicationController real_time_enabled = Gitlab::ActionCable::Config.in_app? || Feature.enabled?(real_time_feature_flag, @project) gon.push({ features: { real_time_feature_flag.to_s.camelize(:lower) => real_time_enabled } }, true) + + record_experiment_user(:invite_members_version_a) + record_experiment_user(:invite_members_version_b) end before_action only: :index do - push_frontend_feature_flag(:scoped_labels, @project) + push_frontend_feature_flag(:scoped_labels, @project, type: :licensed) end around_action :allow_gitaly_ref_name_caching, only: [:discussions] @@ -65,6 +66,17 @@ class Projects::IssuesController < Projects::ApplicationController alias_method :designs, :show + feature_category :issue_tracking, [ + :index, :calendar, :show, :new, :create, :edit, :update, + :destroy, :move, :reorder, :designs, :toggle_subscription, + :discussions, :bulk_update, :realtime_changes, + :toggle_award_emoji, :mark_as_spam, :related_branches, + :can_create_branch, :create_merge_request + ] + + feature_category :service_desk, [:service_desk] + feature_category :importers, [:import_csv, :export_csv] + def index @issues = @issuables @@ -204,7 +216,7 @@ class Projects::IssuesController < Projects::ApplicationController end def export_csv - ExportCsvWorker.perform_async(current_user.id, project.id, finder_options.to_h) # rubocop:disable CodeReuse/Worker + IssuableExportCsvWorker.perform_async(:issue, current_user.id, project.id, finder_options.to_h) # rubocop:disable CodeReuse/Worker index_path = project_issues_path(project) message = _('Your CSV export has started. It will be emailed to %{email} when complete.') % { email: current_user.notification_email } @@ -239,7 +251,7 @@ class Projects::IssuesController < Projects::ApplicationController return @issue if defined?(@issue) # The Sortable default scope causes performance issues when used with find_by - @issuable = @noteable = @issue ||= @project.issues.includes(author: :status).where(iid: params[:id]).reorder(nil).take! + @issuable = @noteable = @issue ||= @project.issues.inc_relations_for_view.iid_in(params[:id]).without_order.take! @note = @project.notes.new(noteable: @issuable) return render_404 unless can?(current_user, :read_issue, @issue) @@ -313,7 +325,7 @@ class Projects::IssuesController < Projects::ApplicationController end def store_uri - if request.get? && !request.xhr? + if request.get? && request.format.html? store_location_for :user, request.fullpath end end diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb index 3f7f8da3478..3ceb60a6aef 100644 --- a/app/controllers/projects/jobs_controller.rb +++ b/app/controllers/projects/jobs_controller.rb @@ -4,7 +4,8 @@ class Projects::JobsController < Projects::ApplicationController include SendFileUpload include ContinueParams - before_action :build, except: [:index] + before_action :find_job_as_build, except: [:index, :play] + before_action :find_job_as_processable, only: [:play] before_action :authorize_read_build! before_action :authorize_update_build!, except: [:index, :show, :status, :raw, :trace, :erase] @@ -16,6 +17,8 @@ class Projects::JobsController < Projects::ApplicationController layout 'project' + feature_category :continuous_integration + def index # We need all builds for tabs counters @all_builds = Ci::JobsFinder.new(current_user: current_user, project: @project).execute @@ -28,11 +31,6 @@ class Projects::JobsController < Projects::ApplicationController # rubocop: disable CodeReuse/ActiveRecord def show - @pipeline = @build.pipeline - @builds = @pipeline.builds - .order('id DESC') - .present(current_user: current_user) - respond_to do |format| format.html format.json do @@ -47,10 +45,10 @@ class Projects::JobsController < Projects::ApplicationController # rubocop: enable CodeReuse/ActiveRecord def trace - build.trace.read do |stream| + @build.trace.read do |stream| respond_to do |format| format.json do - build.trace.being_watched! + @build.trace.being_watched! build_trace = Ci::BuildTrace.new( build: @build, @@ -75,8 +73,13 @@ class Projects::JobsController < Projects::ApplicationController def play return respond_422 unless @build.playable? - build = @build.play(current_user, play_params[:job_variables_attributes]) - redirect_to build_path(build) + job = @build.play(current_user, play_params[:job_variables_attributes]) + + if job.is_a?(Ci::Bridge) + redirect_to pipeline_path(job.pipeline) + else + redirect_to build_path(job) + end end def cancel @@ -120,7 +123,7 @@ class Projects::JobsController < Projects::ApplicationController send_params: raw_send_params, redirect_params: raw_redirect_params) else - build.trace.read do |stream| + @build.trace.read do |stream| if stream.file? workhorse_set_content_type! send_file stream.path, type: 'text/plain; charset=utf-8', disposition: 'inline' @@ -152,19 +155,19 @@ class Projects::JobsController < Projects::ApplicationController private def authorize_update_build! - return access_denied! unless can?(current_user, :update_build, build) + return access_denied! unless can?(current_user, :update_build, @build) end def authorize_erase_build! - return access_denied! unless can?(current_user, :erase_build, build) + return access_denied! unless can?(current_user, :erase_build, @build) end def authorize_use_build_terminal! - return access_denied! unless can?(current_user, :create_build_terminal, build) + return access_denied! unless can?(current_user, :create_build_terminal, @build) end def authorize_create_proxy_build! - return access_denied! unless can?(current_user, :create_build_service_proxy, build) + return access_denied! unless can?(current_user, :create_build_service_proxy, @build) end def verify_api_request! @@ -189,14 +192,22 @@ class Projects::JobsController < Projects::ApplicationController end def trace_artifact_file - @trace_artifact_file ||= build.job_artifacts_trace&.file + @trace_artifact_file ||= @build.job_artifacts_trace&.file end - def build - @build ||= project.builds.find(params[:id]) + def find_job_as_build + @build = project.builds.find(params[:id]) .present(current_user: current_user) end + def find_job_as_processable + if ::Gitlab::Ci::Features.manual_bridges_enabled?(project) + @build = project.processables.find(params[:id]) + else + find_job_as_build + end + end + def build_path(build) project_job_path(build.project, build) end @@ -211,10 +222,10 @@ class Projects::JobsController < Projects::ApplicationController end def build_service_specification - build.service_specification(service: params['service'], - port: params['port'], - path: params['path'], - subprotocols: proxy_subprotocol) + @build.service_specification(service: params['service'], + port: params['port'], + path: params['path'], + subprotocols: proxy_subprotocol) end def proxy_subprotocol diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb index b7aeab8f5ff..ba8e6b90971 100644 --- a/app/controllers/projects/labels_controller.rb +++ b/app/controllers/projects/labels_controller.rb @@ -2,6 +2,7 @@ class Projects::LabelsController < Projects::ApplicationController include ToggleSubscriptionAction + include ShowInheritedLabelsChecker before_action :check_issuables_available! before_action :label, only: [:edit, :update, :destroy, :promote] @@ -14,6 +15,8 @@ class Projects::LabelsController < Projects::ApplicationController respond_to :js, :html + feature_category :issue_tracking + def index @prioritized_labels = @available_labels.prioritized(@project) @labels = @available_labels.unprioritized(@project).page(params[:page]) @@ -161,7 +164,7 @@ class Projects::LabelsController < Projects::ApplicationController @available_labels ||= LabelsFinder.new(current_user, project_id: @project.id, - include_ancestor_groups: params[:include_ancestor_groups], + include_ancestor_groups: show_inherited_labels?(params[:include_ancestor_groups]), search: params[:search], subscribed: params[:subscribed], sort: sort).execute diff --git a/app/controllers/projects/logs_controller.rb b/app/controllers/projects/logs_controller.rb index b9027b3a2cb..b9aa9bfc947 100644 --- a/app/controllers/projects/logs_controller.rb +++ b/app/controllers/projects/logs_controller.rb @@ -7,6 +7,8 @@ module Projects before_action :authorize_read_pod_logs! before_action :ensure_deployments, only: %i(k8s elasticsearch) + feature_category :logging + def index if environment || cluster render :index diff --git a/app/controllers/projects/mattermosts_controller.rb b/app/controllers/projects/mattermosts_controller.rb index cfaeddf711a..63a36732d87 100644 --- a/app/controllers/projects/mattermosts_controller.rb +++ b/app/controllers/projects/mattermosts_controller.rb @@ -10,6 +10,8 @@ class Projects::MattermostsController < Projects::ApplicationController before_action :service before_action :teams, only: [:new] + feature_category :integrations + def new end diff --git a/app/controllers/projects/merge_requests/application_controller.rb b/app/controllers/projects/merge_requests/application_controller.rb index 921da788ad2..9cac9f37eb7 100644 --- a/app/controllers/projects/merge_requests/application_controller.rb +++ b/app/controllers/projects/merge_requests/application_controller.rb @@ -5,6 +5,8 @@ class Projects::MergeRequests::ApplicationController < Projects::ApplicationCont before_action :merge_request before_action :authorize_read_merge_request! + feature_category :code_review + private def merge_request @@ -35,6 +37,7 @@ class Projects::MergeRequests::ApplicationController < Projects::ApplicationCont :source_branch, :source_project_id, :state_event, + :wip_event, :squash, :target_branch, :target_project_id, diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb index 8aacfdce094..07c38431f0f 100644 --- a/app/controllers/projects/merge_requests/diffs_controller.rb +++ b/app/controllers/projects/merge_requests/diffs_controller.rb @@ -64,7 +64,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic render: ->(partial, locals) { view_to_html_string(partial, locals) } } - options = additional_attributes.merge(diff_view: Feature.enabled?(:unified_diff_lines, @merge_request.project) ? "inline" : diff_view) + options = additional_attributes.merge(diff_view: Feature.enabled?(:unified_diff_lines, @merge_request.project, default_enabled: true) ? "inline" : diff_view) if @merge_request.project.context_commits_enabled? options[:context_commits] = @merge_request.recent_context_commits @@ -173,7 +173,6 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic 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? diff --git a/app/controllers/projects/merge_requests/drafts_controller.rb b/app/controllers/projects/merge_requests/drafts_controller.rb index f4846b1aa81..ca3f36cafe1 100644 --- a/app/controllers/projects/merge_requests/drafts_controller.rb +++ b/app/controllers/projects/merge_requests/drafts_controller.rb @@ -45,7 +45,7 @@ class Projects::MergeRequests::DraftsController < Projects::MergeRequests::Appli if result[:status] == :success head :ok else - render json: { message: result[:message] }, status: result[:status] + render json: { message: result[:message] }, status: :internal_server_error end end diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 92785540172..91a041bb35b 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -27,11 +27,8 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo before_action :authenticate_user!, only: [:assign_related_issues] before_action :check_user_can_push_to_source_branch!, only: [:rebase] before_action only: [:show] do - push_frontend_feature_flag(:deploy_from_footer, @project, default_enabled: true) - push_frontend_feature_flag(:suggest_pipeline) if experiment_enabled?(:suggest_pipeline) - push_frontend_feature_flag(:code_navigation, @project, default_enabled: true) + push_frontend_experiment(:suggest_pipeline) push_frontend_feature_flag(:widget_visibility_polling, @project, default_enabled: true) - push_frontend_feature_flag(:merge_ref_head_comments, @project, default_enabled: true) push_frontend_feature_flag(:mr_commit_neighbor_nav, @project, default_enabled: true) push_frontend_feature_flag(:multiline_comments, @project, default_enabled: true) push_frontend_feature_flag(:file_identifier_hash) @@ -39,25 +36,35 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo push_frontend_feature_flag(:approvals_commented_by, @project, default_enabled: true) push_frontend_feature_flag(:hide_jump_to_next_unresolved_in_threads, default_enabled: true) push_frontend_feature_flag(:merge_request_widget_graphql, @project) - push_frontend_feature_flag(:unified_diff_lines, @project) + push_frontend_feature_flag(:unified_diff_lines, @project, default_enabled: true) push_frontend_feature_flag(:highlight_current_diff_row, @project) push_frontend_feature_flag(:default_merge_ref_for_diffs, @project) + push_frontend_feature_flag(:core_security_mr_widget, @project, default_enabled: true) + + record_experiment_user(:invite_members_version_a) + record_experiment_user(:invite_members_version_b) end before_action do push_frontend_feature_flag(:vue_issuable_sidebar, @project.group) + push_frontend_feature_flag(:deployment_filters) end around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions] after_action :log_merge_request_show, only: [:show] - 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] + feature_category :code_review, [ + :assign_related_issues, :bulk_update, :cancel_auto_merge, + :ci_environments_status, :commit_change_content, :commits, + :context_commits, :destroy, :diff_for_path, :discussions, + :edit, :exposed_artifacts, :index, :merge, + :pipeline_status, :pipelines, :rebase, :remove_wip, :show, + :toggle_award_emoji, :toggle_subscription, :update + ] + + feature_category :code_testing, [:test_reports, :coverage_reports, :terraform_reports] + feature_category :accessibility_testing, [:accessibility_reports] def index @merge_requests = @issuables diff --git a/app/controllers/projects/metrics/dashboards/builder_controller.rb b/app/controllers/projects/metrics/dashboards/builder_controller.rb index 2ab574d7d10..96ca6d89111 100644 --- a/app/controllers/projects/metrics/dashboards/builder_controller.rb +++ b/app/controllers/projects/metrics/dashboards/builder_controller.rb @@ -6,6 +6,8 @@ module Projects class BuilderController < Projects::ApplicationController before_action :authorize_metrics_dashboard! + feature_category :metrics + def panel_preview respond_to do |format| format.json do diff --git a/app/controllers/projects/metrics_dashboard_controller.rb b/app/controllers/projects/metrics_dashboard_controller.rb index bc0a701b9fd..3f10749602e 100644 --- a/app/controllers/projects/metrics_dashboard_controller.rb +++ b/app/controllers/projects/metrics_dashboard_controller.rb @@ -14,6 +14,8 @@ module Projects push_frontend_feature_flag(:disable_metric_dashboard_refresh_rate) end + feature_category :metrics + def show if environment render 'projects/environments/metrics' diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb index 16d63cc184f..e6c4af00b29 100644 --- a/app/controllers/projects/milestones_controller.rb +++ b/app/controllers/projects/milestones_controller.rb @@ -5,7 +5,7 @@ class Projects::MilestonesController < Projects::ApplicationController include MilestoneActions before_action :check_issuables_available! - before_action :milestone, only: [:edit, :update, :destroy, :show, :merge_requests, :participants, :labels, :promote] + before_action :milestone, only: [:edit, :update, :destroy, :show, :issues, :merge_requests, :participants, :labels, :promote] before_action do push_frontend_feature_flag(:burnup_charts, @project) end @@ -14,13 +14,15 @@ class Projects::MilestonesController < Projects::ApplicationController before_action :authorize_read_milestone! # Allow admin milestone - before_action :authorize_admin_milestone!, except: [:index, :show, :merge_requests, :participants, :labels] + before_action :authorize_admin_milestone!, except: [:index, :show, :issues, :merge_requests, :participants, :labels] # Allow to promote milestone before_action :authorize_promote_milestone!, only: :promote respond_to :html + feature_category :issue_tracking + def index @sort = params[:sort] || 'due_date_asc' @milestones = milestones.sort_by_attribute(@sort) diff --git a/app/controllers/projects/mirrors_controller.rb b/app/controllers/projects/mirrors_controller.rb index 518e6a92afa..01abb72fc86 100644 --- a/app/controllers/projects/mirrors_controller.rb +++ b/app/controllers/projects/mirrors_controller.rb @@ -10,6 +10,8 @@ class Projects::MirrorsController < Projects::ApplicationController layout "project_settings" + feature_category :source_code_management + def show redirect_to_repository_settings(project, anchor: 'js-push-remote-settings') end diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb index 47788438da9..89b679fc033 100644 --- a/app/controllers/projects/network_controller.rb +++ b/app/controllers/projects/network_controller.rb @@ -11,6 +11,8 @@ class Projects::NetworkController < Projects::ApplicationController before_action :assign_options before_action :assign_commit + feature_category :source_code_management + def show @url = project_network_path(@project, @ref, @options.merge(format: :json)) @commit_url = project_commit_path(@project, 'ae45ca32').gsub("ae45ca32", "%s") diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index c0b8c9e550d..e50e293a103 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -11,6 +11,8 @@ class Projects::NotesController < Projects::ApplicationController before_action :authorize_create_note!, only: [:create] before_action :authorize_resolve_note!, only: [:resolve, :unresolve] + feature_category :issue_tracking + def delete_attachment note.remove_attachment! note.update_attribute(:attachment, nil) diff --git a/app/controllers/projects/packages/package_files_controller.rb b/app/controllers/projects/packages/package_files_controller.rb index dd6d875cd1e..32aadb4fcf4 100644 --- a/app/controllers/projects/packages/package_files_controller.rb +++ b/app/controllers/projects/packages/package_files_controller.rb @@ -6,6 +6,8 @@ module Projects include PackagesAccess include SendFileUpload + feature_category :package_registry + def download package_file = project.package_files.find(params[:id]) diff --git a/app/controllers/projects/packages/packages_controller.rb b/app/controllers/projects/packages/packages_controller.rb index fc4ef7a01dc..15dc11f5df8 100644 --- a/app/controllers/projects/packages/packages_controller.rb +++ b/app/controllers/projects/packages/packages_controller.rb @@ -5,20 +5,13 @@ module Projects class PackagesController < Projects::ApplicationController include PackagesAccess - before_action :authorize_destroy_package!, only: [:destroy] + feature_category :package_registry def show @package = project.packages.find(params[:id]) @package_files = @package.package_files.recent @maven_metadatum = @package.maven_metadatum end - - def destroy - @package = project.packages.find(params[:id]) - @package.destroy - - redirect_to project_packages_path(@project), status: :found, notice: _('Package was removed') - end end end end diff --git a/app/controllers/projects/pages_controller.rb b/app/controllers/projects/pages_controller.rb index 9ad6bf4095a..0aac517e3e3 100644 --- a/app/controllers/projects/pages_controller.rb +++ b/app/controllers/projects/pages_controller.rb @@ -8,6 +8,8 @@ class Projects::PagesController < Projects::ApplicationController before_action :authorize_update_pages!, except: [:show, :destroy] before_action :authorize_remove_pages!, only: [:destroy] + feature_category :pages + # rubocop: disable CodeReuse/ActiveRecord def show @domains = @project.pages_domains.order(:domain).present(current_user: current_user) diff --git a/app/controllers/projects/pages_domains_controller.rb b/app/controllers/projects/pages_domains_controller.rb index cccf8fe4358..a6b22a28b17 100644 --- a/app/controllers/projects/pages_domains_controller.rb +++ b/app/controllers/projects/pages_domains_controller.rb @@ -9,6 +9,8 @@ class Projects::PagesDomainsController < Projects::ApplicationController helper_method :domain_presenter + feature_category :pages + def show end diff --git a/app/controllers/projects/performance_monitoring/dashboards_controller.rb b/app/controllers/projects/performance_monitoring/dashboards_controller.rb index ec5a33f5dd6..51a07c1b7a5 100644 --- a/app/controllers/projects/performance_monitoring/dashboards_controller.rb +++ b/app/controllers/projects/performance_monitoring/dashboards_controller.rb @@ -12,6 +12,8 @@ module Projects respond_error(http_status: :bad_request, message: _('Request parameter %{param} is missing.') % { param: exception.param }) end + feature_category :metrics + def create result = ::Metrics::Dashboard::CloneDashboardService.new(project, current_user, dashboard_params).execute diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb index e7e8a900060..5655d3b4c0d 100644 --- a/app/controllers/projects/pipeline_schedules_controller.rb +++ b/app/controllers/projects/pipeline_schedules_controller.rb @@ -10,6 +10,8 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController before_action :authorize_update_pipeline_schedule!, except: [:index, :new, :create, :play] before_action :authorize_admin_pipeline_schedule!, only: [:destroy] + feature_category :continuous_integration + # rubocop: disable CodeReuse/ActiveRecord def index @scope = params[:scope] diff --git a/app/controllers/projects/pipelines/application_controller.rb b/app/controllers/projects/pipelines/application_controller.rb index 92887750813..c147d697888 100644 --- a/app/controllers/projects/pipelines/application_controller.rb +++ b/app/controllers/projects/pipelines/application_controller.rb @@ -10,6 +10,8 @@ module Projects before_action :pipeline before_action :authorize_read_pipeline! + feature_category :continuous_integration + private def pipeline diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index c1734d2cd8a..953dce4d63c 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -5,17 +5,19 @@ class Projects::PipelinesController < Projects::ApplicationController include Analytics::UniqueVisitsHelper before_action :whitelist_query_limiting, only: [:create, :retry] - before_action :pipeline, except: [:index, :new, :create, :charts] + before_action :pipeline, except: [:index, :new, :create, :charts, :config_variables] before_action :set_pipeline_path, only: [:show] before_action :authorize_read_pipeline! before_action :authorize_read_build!, only: [:index] - before_action :authorize_create_pipeline!, only: [:new, :create] + before_action :authorize_create_pipeline!, only: [:new, :create, :config_variables] before_action :authorize_update_pipeline!, only: [:retry, :cancel] before_action do push_frontend_feature_flag(:filter_pipelines_search, project, default_enabled: true) push_frontend_feature_flag(:dag_pipeline_tab, project, default_enabled: true) push_frontend_feature_flag(:pipelines_security_report_summary, project) - push_frontend_feature_flag(:new_pipeline_form) + push_frontend_feature_flag(:new_pipeline_form, project) + push_frontend_feature_flag(:graphql_pipeline_header, project, type: :development, default_enabled: false) + push_frontend_feature_flag(:new_pipeline_form_prefilled_vars, project, type: :development) end before_action :ensure_pipeline, only: [:show] @@ -30,6 +32,8 @@ class Projects::PipelinesController < Projects::ApplicationController POLLING_INTERVAL = 10_000 + feature_category :continuous_integration + def index @pipelines = Ci::PipelinesFinder .new(project, current_user, index_params) @@ -206,6 +210,14 @@ class Projects::PipelinesController < Projects::ApplicationController end end + def config_variables + respond_to do |format| + format.json do + render json: Ci::ListConfigVariablesService.new(@project).execute(params[:sha]) + end + end + end + private def serialize_pipelines diff --git a/app/controllers/projects/pipelines_settings_controller.rb b/app/controllers/projects/pipelines_settings_controller.rb index 7f988110977..6e08a889520 100644 --- a/app/controllers/projects/pipelines_settings_controller.rb +++ b/app/controllers/projects/pipelines_settings_controller.rb @@ -3,6 +3,8 @@ class Projects::PipelinesSettingsController < Projects::ApplicationController before_action :authorize_admin_pipeline! + feature_category :continuous_integration + def show redirect_to project_settings_ci_cd_path(@project, params: params.to_unsafe_h) end diff --git a/app/controllers/projects/product_analytics_controller.rb b/app/controllers/projects/product_analytics_controller.rb index c019dc191d6..5db7585d8e0 100644 --- a/app/controllers/projects/product_analytics_controller.rb +++ b/app/controllers/projects/product_analytics_controller.rb @@ -5,6 +5,8 @@ class Projects::ProductAnalyticsController < Projects::ApplicationController before_action :authorize_read_product_analytics! before_action :tracker_variables, only: [:setup, :test] + feature_category :product_analytics + def index @events = product_analytics_events.order_by_time.page(params[:page]) end diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index 3e52248f292..631f627838b 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -8,6 +8,8 @@ class Projects::ProjectMembersController < Projects::ApplicationController # Authorize before_action :authorize_admin_project_member!, except: [:index, :leave, :request_access] + feature_category :authentication_and_authorization + def index @sort = params[:sort].presence || sort_value_name @@ -55,6 +57,10 @@ class Projects::ProjectMembersController < Projects::ApplicationController def filter_params params.permit(:search).merge(sort: @sort) end + + def membershipable_members + project.members + end end Projects::ProjectMembersController.prepend_if_ee('EE::Projects::ProjectMembersController') diff --git a/app/controllers/projects/prometheus/alerts_controller.rb b/app/controllers/projects/prometheus/alerts_controller.rb index c6ae65f7832..2892542e63c 100644 --- a/app/controllers/projects/prometheus/alerts_controller.rb +++ b/app/controllers/projects/prometheus/alerts_controller.rb @@ -16,6 +16,8 @@ module Projects before_action :authorize_read_prometheus_alerts!, except: [:notify] before_action :alert, only: [:update, :show, :destroy, :metrics_dashboard] + feature_category :alert_management + def index render json: serialize_as_json(alerts) end diff --git a/app/controllers/projects/prometheus/metrics_controller.rb b/app/controllers/projects/prometheus/metrics_controller.rb index 0340cb5beb0..d70d29a341f 100644 --- a/app/controllers/projects/prometheus/metrics_controller.rb +++ b/app/controllers/projects/prometheus/metrics_controller.rb @@ -6,6 +6,8 @@ module Projects before_action :authorize_admin_project! before_action :require_prometheus_metrics! + feature_category :metrics + def active_common respond_to do |format| format.json do diff --git a/app/controllers/projects/protected_refs_controller.rb b/app/controllers/projects/protected_refs_controller.rb index 060403a9cd9..4cba1a75330 100644 --- a/app/controllers/projects/protected_refs_controller.rb +++ b/app/controllers/projects/protected_refs_controller.rb @@ -10,6 +10,8 @@ class Projects::ProtectedRefsController < Projects::ApplicationController layout "project_settings" + feature_category :source_code_management + def index redirect_to_repository_settings(@project) end @@ -62,7 +64,7 @@ class Projects::ProtectedRefsController < Projects::ApplicationController end def access_level_attributes - %i[access_level id _destroy] + %i[access_level id _destroy deploy_key_id] end end diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb index 29f1e4bfd44..a9490c106d4 100644 --- a/app/controllers/projects/raw_controller.rb +++ b/app/controllers/projects/raw_controller.rb @@ -15,6 +15,8 @@ class Projects::RawController < Projects::ApplicationController before_action :no_cache_headers, only: [:show] before_action :redirect_to_external_storage, only: :show, if: :static_objects_external_storage_enabled? + feature_category :source_code_management + def show @blob = @repository.blob_at(@commit.id, @path) diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb index db770d3e438..4d23c853334 100644 --- a/app/controllers/projects/refs_controller.rb +++ b/app/controllers/projects/refs_controller.rb @@ -11,6 +11,8 @@ class Projects::RefsController < Projects::ApplicationController before_action :assign_ref_vars before_action :authorize_download_code! + feature_category :source_code_management + def switch respond_to do |format| format.html do diff --git a/app/controllers/projects/registry/application_controller.rb b/app/controllers/projects/registry/application_controller.rb index 2f891d78c91..e7bf8c8e757 100644 --- a/app/controllers/projects/registry/application_controller.rb +++ b/app/controllers/projects/registry/application_controller.rb @@ -8,6 +8,8 @@ module Projects before_action :verify_registry_enabled! before_action :authorize_read_container_image! + feature_category :container_registry + private def verify_registry_enabled! diff --git a/app/controllers/projects/registry/repositories_controller.rb b/app/controllers/projects/registry/repositories_controller.rb index 19d0cb9acdc..28a86ecc9f0 100644 --- a/app/controllers/projects/registry/repositories_controller.rb +++ b/app/controllers/projects/registry/repositories_controller.rb @@ -3,6 +3,8 @@ module Projects module Registry class RepositoriesController < ::Projects::Registry::ApplicationController + include PackagesHelper + before_action :authorize_update_container_image!, only: [:destroy] before_action :ensure_root_container_repository!, only: [:index] @@ -13,7 +15,7 @@ module Projects @images = ContainerRepositoriesFinder.new(user: current_user, subject: project, params: params.slice(:name)) .execute - track_event(:list_repositories) + track_package_event(:list_repositories, :container) serializer = ContainerRepositoriesSerializer .new(project: project, current_user: current_user) @@ -31,7 +33,7 @@ module Projects def destroy image.delete_scheduled! DeleteContainerRepositoryWorker.perform_async(current_user.id, image.id) # rubocop:disable CodeReuse/Worker - track_event(:delete_repository) + track_package_event(:delete_repository, :container) respond_to do |format| format.json { head :no_content } diff --git a/app/controllers/projects/registry/tags_controller.rb b/app/controllers/projects/registry/tags_controller.rb index c42e3f6bdba..ebdb668207f 100644 --- a/app/controllers/projects/registry/tags_controller.rb +++ b/app/controllers/projects/registry/tags_controller.rb @@ -3,12 +3,15 @@ module Projects module Registry class TagsController < ::Projects::Registry::ApplicationController + include PackagesHelper + before_action :authorize_destroy_container_image!, only: [:destroy] LIMIT = 15 def index - track_event(:list_tags) + track_package_event(:list_tags, :tag) + respond_to do |format| format.json do render json: ContainerTagsSerializer @@ -23,7 +26,7 @@ module Projects result = Projects::ContainerRepository::DeleteTagsService .new(image.project, current_user, tags: [params[:id]]) .execute(image) - track_event(:delete_tag) + track_package_event(:delete_tag, :tag) respond_to do |format| format.json { head(result[:status] == :success ? :ok : bad_request) } @@ -40,7 +43,7 @@ module Projects result = Projects::ContainerRepository::DeleteTagsService .new(image.project, current_user, tags: tag_names) .execute(image) - track_event(:delete_tag_bulk) + track_package_event(:delete_tag_bulk, :tag) respond_to do |format| format.json { head(result[:status] == :success ? :no_content : :bad_request) } diff --git a/app/controllers/projects/releases/evidences_controller.rb b/app/controllers/projects/releases/evidences_controller.rb index 34e450d903f..1e2dbf8047c 100644 --- a/app/controllers/projects/releases/evidences_controller.rb +++ b/app/controllers/projects/releases/evidences_controller.rb @@ -7,6 +7,8 @@ module Projects before_action :release before_action :authorize_read_release_evidence! + feature_category :release_evidence + def show respond_to do |format| format.json do diff --git a/app/controllers/projects/releases_controller.rb b/app/controllers/projects/releases_controller.rb index bd24aae980c..4e8260d9e53 100644 --- a/app/controllers/projects/releases_controller.rb +++ b/app/controllers/projects/releases_controller.rb @@ -6,18 +6,16 @@ class Projects::ReleasesController < Projects::ApplicationController before_action :release, only: %i[edit show update downloads] before_action :authorize_read_release! before_action do - push_frontend_feature_flag(:release_issue_summary, project, default_enabled: true) - push_frontend_feature_flag(:release_evidence_collection, project, default_enabled: true) - push_frontend_feature_flag(:release_show_page, project, default_enabled: true) - push_frontend_feature_flag(:release_asset_link_editing, project, default_enabled: true) - push_frontend_feature_flag(:release_asset_link_type, project, default_enabled: true) push_frontend_feature_flag(:graphql_release_data, project, default_enabled: true) push_frontend_feature_flag(:graphql_milestone_stats, project, default_enabled: true) - push_frontend_feature_flag(:graphql_releases_page, project, default_enabled: false) + push_frontend_feature_flag(:graphql_releases_page, project, default_enabled: true) + push_frontend_feature_flag(:graphql_individual_release_page, project, default_enabled: true) end before_action :authorize_update_release!, only: %i[edit update] before_action :authorize_create_release!, only: :new + feature_category :release_orchestration + def index respond_to do |format| format.html do @@ -27,10 +25,6 @@ class Projects::ReleasesController < Projects::ApplicationController end end - def show - return render_404 unless Feature.enabled?(:release_show_page, project, default_enabled: true) - end - def new unless Feature.enabled?(:new_release_page, project, default_enabled: true) redirect_to(new_project_tag_path(@project)) diff --git a/app/controllers/projects/repositories_controller.rb b/app/controllers/projects/repositories_controller.rb index 303326bbe23..ba3ab52e3af 100644 --- a/app/controllers/projects/repositories_controller.rb +++ b/app/controllers/projects/repositories_controller.rb @@ -18,6 +18,8 @@ class Projects::RepositoriesController < Projects::ApplicationController before_action :authorize_admin_project!, only: :create before_action :redirect_to_external_storage, only: :archive, if: :static_objects_external_storage_enabled? + feature_category :source_code_management + def create @project.create_repository diff --git a/app/controllers/projects/runner_projects_controller.rb b/app/controllers/projects/runner_projects_controller.rb index cbeb32fd610..d225d5e104c 100644 --- a/app/controllers/projects/runner_projects_controller.rb +++ b/app/controllers/projects/runner_projects_controller.rb @@ -5,6 +5,8 @@ class Projects::RunnerProjectsController < Projects::ApplicationController layout 'project_settings' + feature_category :continuous_integration + def create @runner = Ci::Runner.find(params[:runner_project][:runner_id]) diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb index ca62f54813b..544074f9840 100644 --- a/app/controllers/projects/runners_controller.rb +++ b/app/controllers/projects/runners_controller.rb @@ -6,6 +6,8 @@ class Projects::RunnersController < Projects::ApplicationController layout 'project_settings' + feature_category :continuous_integration + def index redirect_to project_settings_ci_cd_path(@project, anchor: 'js-runners-settings') end @@ -50,6 +52,10 @@ class Projects::RunnersController < Projects::ApplicationController end def toggle_shared_runners + if Feature.enabled?(:disable_shared_runners_on_group, default_enabled: true) && !project.shared_runners_enabled && project.group && project.group.shared_runners_setting == 'disabled_and_unoverridable' + return redirect_to project_runners_path(@project), alert: _("Cannot enable shared runners because parent group does not allow it") + end + project.toggle!(:shared_runners_enabled) redirect_to project_settings_ci_cd_path(@project, anchor: 'js-runners-settings') diff --git a/app/controllers/projects/serverless/functions_controller.rb b/app/controllers/projects/serverless/functions_controller.rb index 0b55414d390..4168880001c 100644 --- a/app/controllers/projects/serverless/functions_controller.rb +++ b/app/controllers/projects/serverless/functions_controller.rb @@ -5,6 +5,8 @@ module Projects class FunctionsController < Projects::ApplicationController before_action :authorize_read_cluster! + feature_category :serverless + def index respond_to do |format| format.json do diff --git a/app/controllers/projects/service_desk_controller.rb b/app/controllers/projects/service_desk_controller.rb index bcd190bbc2c..f7c0a54fb9e 100644 --- a/app/controllers/projects/service_desk_controller.rb +++ b/app/controllers/projects/service_desk_controller.rb @@ -3,6 +3,8 @@ class Projects::ServiceDeskController < Projects::ApplicationController before_action :authorize_admin_project! + feature_category :service_desk + def show json_response end diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index 9a69ef991dd..93ad549bc50 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -12,13 +12,15 @@ 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(:jira_issues_integration, @project, { default_enabled: true }) + push_frontend_feature_flag(:jira_issues_integration, @project, type: :licensed, default_enabled: true) end respond_to :html layout "project_settings" + feature_category :integrations + def edit @default_integration = Service.default_integration(service.type, project) end diff --git a/app/controllers/projects/settings/access_tokens_controller.rb b/app/controllers/projects/settings/access_tokens_controller.rb index d6b4c4dd5dc..cbd6716fdf7 100644 --- a/app/controllers/projects/settings/access_tokens_controller.rb +++ b/app/controllers/projects/settings/access_tokens_controller.rb @@ -7,6 +7,8 @@ module Projects before_action :check_feature_availability + feature_category :authentication_and_authorization + def index @project_access_token = PersonalAccessToken.new set_index_vars diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index d0d100fd88c..2963321f803 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -3,15 +3,25 @@ module Projects module Settings class CiCdController < Projects::ApplicationController + include RunnerSetupScripts + before_action :authorize_admin_pipeline! before_action :define_variables before_action do push_frontend_feature_flag(:new_variables_ui, @project, default_enabled: true) push_frontend_feature_flag(:ajax_new_deploy_token, @project) - push_frontend_feature_flag(:ci_key_autocomplete, default_enabled: true) end + helper_method :highlight_badge + + feature_category :continuous_integration + def show + if Feature.enabled?(:ci_pipeline_triggers_settings_vue_ui, @project) + @triggers_json = ::Ci::TriggerSerializer.new.represent( + @project.triggers, current_user: current_user, project: @project + ).to_json + end end def update @@ -48,8 +58,16 @@ module Projects redirect_to namespace_project_settings_ci_cd_path end + def runner_setup_scripts + private_runner_setup_scripts(project: @project) + 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 @@ -58,9 +76,9 @@ module Projects [ :runners_token, :builds_enabled, :build_allow_git_fetch, :build_timeout_human_readable, :build_coverage_regex, :public_builds, - :auto_cancel_pending_pipelines, :forward_deployment_enabled, :ci_config_path, + :auto_cancel_pending_pipelines, :ci_config_path, auto_devops_attributes: [:id, :domain, :enabled, :deploy_strategy], - ci_cd_settings_attributes: [:default_git_depth] + 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 @@ -116,6 +134,7 @@ module Projects def define_triggers_variables @triggers = @project.triggers .present(current_user: current_user) + @trigger = ::Ci::Trigger.new .present(current_user: current_user) end diff --git a/app/controllers/projects/settings/integrations_controller.rb b/app/controllers/projects/settings/integrations_controller.rb index 96bf7f474d1..fba11ff1497 100644 --- a/app/controllers/projects/settings/integrations_controller.rb +++ b/app/controllers/projects/settings/integrations_controller.rb @@ -6,6 +6,8 @@ module Projects before_action :authorize_admin_project! layout "project_settings" + feature_category :integrations + def show @services = @project.find_or_initialize_services end diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb index 781b850ddfe..c407b15e29f 100644 --- a/app/controllers/projects/settings/operations_controller.rb +++ b/app/controllers/projects/settings/operations_controller.rb @@ -9,6 +9,9 @@ module Projects respond_to :json, only: [:reset_alerting_token, :reset_pagerduty_token] helper_method :error_tracking_setting + helper_method :tracing_setting + + feature_category :incident_management def update result = ::Projects::Operations::UpdateService.new(project, current_user, update_params).execute @@ -17,15 +20,6 @@ module Projects render_update_response(result) end - # overridden in EE - def track_events(result) - if result[:status] == :success - ::Gitlab::Tracking::IncidentManagement.track_from_params( - update_params[:incident_management_setting_attributes] - ) - end - end - def reset_alerting_token result = ::Projects::Operations::UpdateService .new(project, current_user, alerting_params) @@ -55,6 +49,24 @@ module Projects private + def track_events(result) + if result[:status] == :success + ::Gitlab::Tracking::IncidentManagement.track_from_params( + update_params[:incident_management_setting_attributes] + ) + track_tracing_external_url + end + end + + def track_tracing_external_url + external_url_previous_change = project&.tracing_setting&.external_url_previous_change + + return unless external_url_previous_change + return unless external_url_previous_change[0].blank? && external_url_previous_change[1].present? + + ::Gitlab::Tracking.event('project:operations:tracing', 'external_url_populated') + end + def alerting_params { alerting_setting_attributes: { regenerate_token: true } } end @@ -106,6 +118,10 @@ module Projects project.build_error_tracking_setting end + def tracing_setting + @tracing_setting ||= project.tracing_setting || project.build_tracing_setting + end + def update_params params.require(:project).permit(permitted_project_params) end @@ -124,7 +140,8 @@ module Projects project: [:slug, :name, :organization_slug, :organization_name] ], - grafana_integration_attributes: [:token, :grafana_url, :enabled] + grafana_integration_attributes: [:token, :grafana_url, :enabled], + tracing_setting_attributes: [:external_url] } if Feature.enabled?(:settings_operations_prometheus_service, project) diff --git a/app/controllers/projects/settings/repository_controller.rb b/app/controllers/projects/settings/repository_controller.rb index 35ca9336613..0994bebb1d0 100644 --- a/app/controllers/projects/settings/repository_controller.rb +++ b/app/controllers/projects/settings/repository_controller.rb @@ -7,8 +7,12 @@ module Projects before_action :define_variables, only: [:create_deploy_token] before_action do push_frontend_feature_flag(:ajax_new_deploy_token, @project) + push_frontend_feature_flag(:deploy_keys_on_protected_branches, @project) end + feature_category :source_code_management, [:show, :cleanup] + feature_category :continuous_delivery, [:create_deploy_token] + def show render_show end @@ -125,6 +129,7 @@ module Projects gon.push(protectable_tags_for_dropdown) gon.push(protectable_branches_for_dropdown) gon.push(access_levels_options) + gon.push(current_project_id: project.id) if project end end end diff --git a/app/controllers/projects/snippets/application_controller.rb b/app/controllers/projects/snippets/application_controller.rb index 3f488b07e96..8ee12bf3795 100644 --- a/app/controllers/projects/snippets/application_controller.rb +++ b/app/controllers/projects/snippets/application_controller.rb @@ -4,6 +4,8 @@ class Projects::Snippets::ApplicationController < Projects::ApplicationControlle include FindSnippet include SnippetAuthorizations + feature_category :snippets + private # This overrides the default snippet create authorization diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb index 632e8db9796..779e149bb9c 100644 --- a/app/controllers/projects/snippets_controller.rb +++ b/app/controllers/projects/snippets_controller.rb @@ -7,16 +7,11 @@ class Projects::SnippetsController < Projects::Snippets::ApplicationController before_action :check_snippets_available! - before_action :snippet, only: [:show, :edit, :destroy, :update, :raw, :toggle_award_emoji, :mark_as_spam] + before_action :snippet, only: [:show, :edit, :raw, :toggle_award_emoji, :mark_as_spam] - before_action :authorize_create_snippet!, only: [:new, :create] - before_action :authorize_read_snippet!, except: [:new, :create, :index] - before_action :authorize_update_snippet!, only: [:edit, :update] - before_action :authorize_admin_snippet!, only: [:destroy] - - before_action do - push_frontend_feature_flag(:snippet_multiple_files, current_user) - end + before_action :authorize_create_snippet!, only: :new + before_action :authorize_read_snippet!, except: [:new, :index] + before_action :authorize_update_snippet!, only: :edit def index @snippet_counts = ::Snippets::CountService @@ -37,14 +32,6 @@ class Projects::SnippetsController < Projects::Snippets::ApplicationController @snippet = @noteable = @project.snippets.build end - def create - create_params = snippet_params.merge(spammable_params) - service_response = ::Snippets::CreateService.new(project, current_user, create_params).execute - @snippet = service_response.payload[:snippet] - - handle_repository_error(:new) - end - protected alias_method :awardable, :snippet @@ -53,8 +40,4 @@ class Projects::SnippetsController < Projects::Snippets::ApplicationController def spammable_path project_snippet_path(@project, @snippet) end - - def snippet_params - params.require(:project_snippet).permit(:title, :content, :file_name, :private, :visibility_level, :description) - end end diff --git a/app/controllers/projects/starrers_controller.rb b/app/controllers/projects/starrers_controller.rb index d9654f4f72a..91f49fc4d66 100644 --- a/app/controllers/projects/starrers_controller.rb +++ b/app/controllers/projects/starrers_controller.rb @@ -3,6 +3,8 @@ class Projects::StarrersController < Projects::ApplicationController include SortingHelper + feature_category :projects + def index @starrers = UsersStarProjectsFinder.new(@project, params, current_user: @current_user).execute @sort = params[:sort].presence || sort_value_name diff --git a/app/controllers/projects/static_site_editor_controller.rb b/app/controllers/projects/static_site_editor_controller.rb index e97a8db0b79..7e2e32a843f 100644 --- a/app/controllers/projects/static_site_editor_controller.rb +++ b/app/controllers/projects/static_site_editor_controller.rb @@ -13,6 +13,8 @@ class Projects::StaticSiteEditorController < Projects::ApplicationController push_frontend_feature_flag(:sse_image_uploads) end + feature_category :static_site_editor + def show service_response = ::StaticSiteEditor::ConfigService.new( container: project, @@ -25,14 +27,32 @@ class Projects::StaticSiteEditorController < Projects::ApplicationController ).execute if service_response.success? - @data = service_response.payload + Gitlab::UsageDataCounters::StaticSiteEditorCounter.increment_views_count + + @data = serialize_necessary_payload_values_to_json(service_response.payload) else - respond_422 + # TODO: For now, if the service returns any error, the user is redirected + # to the root project page with the error message displayed as an alert. + # See https://gitlab.com/gitlab-org/gitlab/-/issues/213285#note_414808004 + # for discussion of plans to handle this via a page owned by the Static Site Editor. + flash[:alert] = service_response.message + redirect_to project_path(project) end end private + def serialize_necessary_payload_values_to_json(payload) + # This will convert booleans, Array-like and Hash-like objects to JSON + payload.transform_values do |value| + if value.is_a?(String) || value.is_a?(Integer) + value + else + value.to_json + end + end + end + def assign_ref_and_path @ref, @path = extract_ref(params.fetch(:id)) diff --git a/app/controllers/projects/tags/releases_controller.rb b/app/controllers/projects/tags/releases_controller.rb index c1f4cbce054..8e5539f546b 100644 --- a/app/controllers/projects/tags/releases_controller.rb +++ b/app/controllers/projects/tags/releases_controller.rb @@ -8,6 +8,8 @@ class Projects::Tags::ReleasesController < Projects::ApplicationController before_action :tag before_action :release + feature_category :release_evidence + def edit end diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb index 475ca8894e4..1d783241196 100644 --- a/app/controllers/projects/tags_controller.rb +++ b/app/controllers/projects/tags_controller.rb @@ -10,6 +10,9 @@ class Projects::TagsController < Projects::ApplicationController before_action :authorize_download_code! before_action :authorize_admin_tag!, only: [:new, :create, :destroy] + feature_category :source_code_management, [:index, :show, :new, :destroy] + feature_category :release_evidence, [:create] + # rubocop: disable CodeReuse/ActiveRecord def index params[:sort] = params[:sort].presence || sort_value_recently_updated @@ -76,25 +79,10 @@ class Projects::TagsController < Projects::ApplicationController def destroy result = ::Tags::DestroyService.new(project, current_user).execute(params[:id]) - respond_to do |format| - if result[:status] == :success - format.html do - redirect_to project_tags_path(@project), status: :see_other - end - - format.js - else - @error = result[:message] - - format.html do - redirect_to project_tags_path(@project), - alert: @error, status: :see_other - end - - format.js do - render status: :ok - end - end + if result[:status] == :success + render json: result + else + render json: { message: result[:message] }, status: result[:return_code] end end diff --git a/app/controllers/projects/templates_controller.rb b/app/controllers/projects/templates_controller.rb index 95739f96d39..7ab23e39cf0 100644 --- a/app/controllers/projects/templates_controller.rb +++ b/app/controllers/projects/templates_controller.rb @@ -5,6 +5,8 @@ class Projects::TemplatesController < Projects::ApplicationController before_action :authorize_can_read_issuable! before_action :get_template_class + feature_category :templates + def show template = @template_type.find(params[:key], project) diff --git a/app/controllers/projects/todos_controller.rb b/app/controllers/projects/todos_controller.rb index 33205b93317..6ba89ab34f8 100644 --- a/app/controllers/projects/todos_controller.rb +++ b/app/controllers/projects/todos_controller.rb @@ -6,6 +6,8 @@ class Projects::TodosController < Projects::ApplicationController before_action :authenticate_user!, only: [:create] + feature_category :issue_tracking + private def issuable diff --git a/app/controllers/projects/tracings_controller.rb b/app/controllers/projects/tracings_controller.rb new file mode 100644 index 00000000000..2bc0c590e8d --- /dev/null +++ b/app/controllers/projects/tracings_controller.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module Projects + class TracingsController < Projects::ApplicationController + content_security_policy do |p| + next if p.directives.blank? + + global_frame_src = p.frame_src + + p.frame_src -> { frame_src_csp_policy(global_frame_src) } + end + + before_action :authorize_update_environment! + + feature_category :tracing + + def show + end + + private + + def frame_src_csp_policy(global_frame_src) + external_url = @project&.tracing_setting&.external_url + + external_url.presence || global_frame_src + end + end +end diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb index 638e1a05c18..b5cfc3990b2 100644 --- a/app/controllers/projects/tree_controller.rb +++ b/app/controllers/projects/tree_controller.rb @@ -15,6 +15,8 @@ class Projects::TreeController < Projects::ApplicationController before_action :authorize_download_code! before_action :authorize_edit_tree!, only: [:create_dir] + feature_category :source_code_management + def show return render_404 unless @commit diff --git a/app/controllers/projects/triggers_controller.rb b/app/controllers/projects/triggers_controller.rb index 7159d0243a3..eec35fcec8d 100644 --- a/app/controllers/projects/triggers_controller.rb +++ b/app/controllers/projects/triggers_controller.rb @@ -8,6 +8,8 @@ class Projects::TriggersController < Projects::ApplicationController layout 'project_settings' + feature_category :continuous_integration + def index redirect_to project_settings_ci_cd_path(@project, anchor: 'js-pipeline-triggers') end diff --git a/app/controllers/projects/uploads_controller.rb b/app/controllers/projects/uploads_controller.rb index 72251988b5e..c15768e7bbb 100644 --- a/app/controllers/projects/uploads_controller.rb +++ b/app/controllers/projects/uploads_controller.rb @@ -11,6 +11,8 @@ class Projects::UploadsController < Projects::ApplicationController before_action :authorize_upload_file!, only: [:create, :authorize] before_action :verify_workhorse_api!, only: [:authorize] + feature_category :not_owned + private def upload_model_class diff --git a/app/controllers/projects/usage_ping_controller.rb b/app/controllers/projects/usage_ping_controller.rb index 0e2c8f879b1..9b4ddb326c1 100644 --- a/app/controllers/projects/usage_ping_controller.rb +++ b/app/controllers/projects/usage_ping_controller.rb @@ -3,6 +3,8 @@ class Projects::UsagePingController < Projects::ApplicationController before_action :authenticate_user! + feature_category :collection + def web_ide_clientside_preview return render_404 unless Gitlab::CurrentSettings.web_ide_clientside_preview_enabled? diff --git a/app/controllers/projects/variables_controller.rb b/app/controllers/projects/variables_controller.rb index 0fd047f90cf..d8efc1b7b54 100644 --- a/app/controllers/projects/variables_controller.rb +++ b/app/controllers/projects/variables_controller.rb @@ -3,6 +3,8 @@ class Projects::VariablesController < Projects::ApplicationController before_action :authorize_admin_build! + feature_category :continuous_integration + def show respond_to do |format| format.json do diff --git a/app/controllers/projects/web_ide_schemas_controller.rb b/app/controllers/projects/web_ide_schemas_controller.rb index 3d16a6fafd4..84a191815f4 100644 --- a/app/controllers/projects/web_ide_schemas_controller.rb +++ b/app/controllers/projects/web_ide_schemas_controller.rb @@ -3,6 +3,8 @@ class Projects::WebIdeSchemasController < Projects::ApplicationController before_action :authenticate_user! + feature_category :web_ide + def show return respond_422 unless branch_sha diff --git a/app/controllers/projects/web_ide_terminals_controller.rb b/app/controllers/projects/web_ide_terminals_controller.rb index 76bcaa9e80c..1d179765ad9 100644 --- a/app/controllers/projects/web_ide_terminals_controller.rb +++ b/app/controllers/projects/web_ide_terminals_controller.rb @@ -8,6 +8,8 @@ class Projects::WebIdeTerminalsController < Projects::ApplicationController before_action :authorize_read_web_ide_terminal!, except: [:check_config, :create] before_action :authorize_update_web_ide_terminal!, only: [:cancel, :retry] + feature_category :web_ide + def check_config return respond_422 unless branch_sha diff --git a/app/controllers/projects/wikis_controller.rb b/app/controllers/projects/wikis_controller.rb index d0aa733cadb..8f794512486 100644 --- a/app/controllers/projects/wikis_controller.rb +++ b/app/controllers/projects/wikis_controller.rb @@ -5,6 +5,8 @@ class Projects::WikisController < Projects::ApplicationController alias_method :container, :project + feature_category :wiki + def git_access end end |