diff options
author | Mike Lewis <mlewis@gitlab.com> | 2019-06-07 20:13:17 +0000 |
---|---|---|
committer | Mike Lewis <mlewis@gitlab.com> | 2019-06-07 20:13:17 +0000 |
commit | 99df0218f82b851b017bd0eea1b8351dc89df6ed (patch) | |
tree | b01f884fbd1418dd5465fc1741f1620061ae8c5c /app/controllers/projects | |
parent | 3eea6906747d10bea501426febaf15d2c209e06a (diff) | |
parent | e07b2b277f79bc25cdce22ca2defba1ba80791aa (diff) | |
download | gitlab-ce-99df0218f82b851b017bd0eea1b8351dc89df6ed.tar.gz |
Merge branch 'master' into 'docs/fix-example-dot-net'
# Conflicts:
# doc/user/project/clusters/serverless/index.md
Diffstat (limited to 'app/controllers/projects')
43 files changed, 400 insertions, 299 deletions
diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb index e0677ce3fbc..80e4f54bbf4 100644 --- a/app/controllers/projects/application_controller.rb +++ b/app/controllers/projects/application_controller.rb @@ -3,7 +3,6 @@ class Projects::ApplicationController < ApplicationController include CookiesHelper include RoutableActions - include ProjectUnauthorized include ChecksCollaboration skip_before_action :authenticate_user! @@ -17,12 +16,12 @@ class Projects::ApplicationController < ApplicationController def project return @project if @project - return nil unless params[:project_id] || params[:id] + return unless params[:project_id] || params[:id] path = File.join(params[:namespace_id], params[:project_id] || params[:id]) auth_proc = ->(project) { !project.pending_delete? } - @project = find_routable!(Project, path, extra_authorization_proc: auth_proc, not_found_or_authorized_proc: project_unauthorized_proc) + @project = find_routable!(Project, path, extra_authorization_proc: auth_proc) end def build_canonical_path(project) @@ -88,4 +87,10 @@ class Projects::ApplicationController < ApplicationController def check_issues_available! return render_404 unless @project.feature_available?(:issues, current_user) end + + def allow_gitaly_ref_name_caching + ::Gitlab::GitalyClient.allow_ref_name_caching do + yield + end + end end diff --git a/app/controllers/projects/autocomplete_sources_controller.rb b/app/controllers/projects/autocomplete_sources_controller.rb index 9c130af8394..0e3f13045ce 100644 --- a/app/controllers/projects/autocomplete_sources_controller.rb +++ b/app/controllers/projects/autocomplete_sources_controller.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class Projects::AutocompleteSourcesController < Projects::ApplicationController + before_action :authorize_read_milestone!, only: :milestones + def members render json: ::Projects::ParticipantsService.new(@project, current_user).execute(target) end diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index 77672e7d9fc..b04ffe80db4 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -9,6 +9,8 @@ class Projects::BlobController < Projects::ApplicationController include ActionView::Helpers::SanitizeHelper prepend_before_action :authenticate_user!, only: [:edit] + around_action :allow_gitaly_ref_name_caching, only: [:show] + before_action :require_non_empty_project, except: [:new, :create] before_action :authorize_download_code! @@ -29,7 +31,7 @@ class Projects::BlobController < Projects::ApplicationController end def create - create_commit(Files::CreateService, success_notice: "The file has been successfully created.", + create_commit(Files::CreateService, success_notice: _("The file has been successfully created."), success_path: -> { project_blob_path(@project, File.join(@branch_name, @file_path)) }, failure_view: :new, failure_path: project_new_blob_path(@project, @ref)) @@ -81,7 +83,7 @@ class Projects::BlobController < Projects::ApplicationController end def destroy - create_commit(Files::DeleteService, success_notice: "The file has been successfully deleted.", + create_commit(Files::DeleteService, success_notice: _("The file has been successfully deleted."), success_path: -> { after_delete_path }, failure_view: :show, failure_path: project_blob_path(@project, @id)) @@ -90,65 +92,21 @@ class Projects::BlobController < Projects::ApplicationController def diff apply_diff_view_cookie! - @blob.load_all_data! - @lines = @blob.present.highlight.lines - - @form = UnfoldForm.new(params.to_unsafe_h) - - @lines = @lines[@form.since - 1..@form.to - 1].map(&:html_safe) - - if @form.bottom? - @match_line = '' - else - lines_length = @lines.length - 1 - line = [@form.since, lines_length].join(',') - @match_line = "@@ -#{line}+#{line} @@" - end + @form = Blobs::UnfoldPresenter.new(blob, params.to_unsafe_h) - # We can keep only 'render_diff_lines' from this conditional when + # keep only json rendering when # https://gitlab.com/gitlab-org/gitlab-ce/issues/44988 is done if rendered_for_merge_request? - render_diff_lines + render json: DiffLineSerializer.new.represent(@form.diff_lines) else + @lines = @form.lines + @match_line = @form.match_line_text render layout: false end end private - # Converts a String array to Gitlab::Diff::Line array - def render_diff_lines - @lines.map! do |line| - # These are marked as context lines but are loaded from blobs. - # We also have context lines loaded from diffs in other places. - diff_line = Gitlab::Diff::Line.new(line, nil, nil, nil, nil) - diff_line.rich_text = line - diff_line - end - - add_match_line - - render json: DiffLineSerializer.new.represent(@lines) - end - - def add_match_line - return unless @form.unfold? - - if @form.bottom? && @form.to < @blob.lines.size - old_pos = @form.to - @form.offset - new_pos = @form.to - elsif @form.since != 1 - old_pos = new_pos = @form.since - end - - # Match line is not needed when it reaches the top limit or bottom limit of the file. - return unless new_pos - - @match_line = Gitlab::Diff::Line.new(@match_line, 'match', nil, old_pos, new_pos) - - @form.bottom? ? @lines.push(@match_line) : @lines.unshift(@match_line) - end - def blob @blob ||= @repository.blob_at(@commit.id, @path) @@ -216,8 +174,7 @@ class Projects::BlobController < Projects::ApplicationController end if params[:file].present? - params[:content] = Base64.encode64(params[:file].read) - params[:encoding] = 'base64' + params[:content] = params[:file] end @commit_params = { @@ -231,6 +188,8 @@ class Projects::BlobController < Projects::ApplicationController end def validate_diff_params + return if params[:full] + if [:since, :to, :offset].any? { |key| params[key].blank? } head :ok end diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb index 8189b5d182a..95897aaf980 100644 --- a/app/controllers/projects/boards_controller.rb +++ b/app/controllers/projects/boards_controller.rb @@ -1,34 +1,15 @@ # frozen_string_literal: true class Projects::BoardsController < Projects::ApplicationController - include BoardsResponses + include BoardsActions include IssuableCollections before_action :check_issues_available! before_action :authorize_read_board!, only: [:index, :show] - before_action :boards, only: :index before_action :assign_endpoint_vars - before_action :redirect_to_recent_board, only: :index - - def index - respond_with_boards - end - - def show - @board = boards.find(params[:id]) - - # add/update the board in the recent visited table - Boards::Visits::CreateService.new(@board.project, current_user).execute(@board) if request.format.html? - - respond_with_board - end private - def boards - @boards ||= Boards::ListService.new(project, current_user).execute - end - def assign_endpoint_vars @boards_endpoint = project_boards_path(project) @bulk_issues_path = bulk_update_project_issues_path(project) @@ -39,22 +20,4 @@ class Projects::BoardsController < Projects::ApplicationController def authorize_read_board! access_denied! unless can?(current_user, :read_board, project) end - - def serialize_as_json(resource) - resource.as_json(only: [:id]) - end - - def includes_board?(board_id) - boards.any? { |board| board.id == board_id } - end - - def redirect_to_recent_board - return if request.format.json? - - recently_visited = Boards::Visits::LatestService.new(project, current_user).execute - - if recently_visited && includes_board?(recently_visited.board_id) - redirect_to(namespace_project_board_path(id: recently_visited.board_id), status: :found) - end - end end diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index 32b7f3207ef..fc708400657 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -25,7 +25,7 @@ class Projects::BranchesController < Projects::ApplicationController @refs_pipelines = @project.ci_pipelines.latest_successful_for_refs(@branches.map(&:name)) @merged_branch_names = repository.merged_branch_names(@branches.map(&:name)) - # n+1: https://gitlab.com/gitlab-org/gitaly/issues/992 + # n+1: https://gitlab.com/gitlab-org/gitlab-ce/issues/48097 Gitlab::GitalyClient.allow_n_plus_1_calls do @max_commits = @branches.reduce(0) do |memo, branch| diverging_commit_counts = repository.diverging_commit_counts(branch) @@ -53,7 +53,7 @@ class Projects::BranchesController < Projects::ApplicationController # rubocop: disable CodeReuse/ActiveRecord def create - branch_name = sanitize(strip_tags(params[:branch_name])) + branch_name = strip_tags(sanitize(params[:branch_name])) branch_name = Addressable::URI.unescape(branch_name) redirect_to_autodeploy = project.empty_repo? && project.deployment_platform.present? @@ -100,14 +100,14 @@ class Projects::BranchesController < Projects::ApplicationController respond_to do |format| format.html do - flash_type = result[:status] == :error ? :alert : :notice - flash[flash_type] = result[:message] + flash_type = result.error? ? :alert : :notice + flash[flash_type] = result.message redirect_to project_branches_path(@project), status: :see_other end - format.js { head result[:return_code] } - format.json { render json: { message: result[:message] }, status: result[:return_code] } + format.js { head result.http_status } + format.json { render json: { message: result.message }, status: result.http_status } end end @@ -115,14 +115,14 @@ class Projects::BranchesController < Projects::ApplicationController DeleteMergedBranchesService.new(@project, current_user).async_execute redirect_to project_branches_path(@project), - notice: 'Merged branches are being deleted. This can take some time depending on the number of branches. Please refresh the page to see changes.' + notice: _('Merged branches are being deleted. This can take some time depending on the number of branches. Please refresh the page to see changes.') end private def ref if params[:ref] - ref_escaped = sanitize(strip_tags(params[:ref])) + ref_escaped = strip_tags(sanitize(params[:ref])) Addressable::URI.unescape(ref_escaped) else @project.default_branch || 'master' @@ -143,7 +143,7 @@ class Projects::BranchesController < Projects::ApplicationController def redirect_for_legacy_index_sort_or_search # Normalize a legacy URL with redirect if request.format != :json && !params[:state].presence && [:sort, :search, :page].any? { |key| params[key].presence } - redirect_to project_branches_filtered_path(@project, state: 'all'), notice: 'Update your bookmarked URLs as filtered/sorted branches URL has been changed.' + redirect_to project_branches_filtered_path(@project, state: 'all'), notice: _('Update your bookmarked URLs as filtered/sorted branches URL has been changed.') end end diff --git a/app/controllers/projects/clusters/applications_controller.rb b/app/controllers/projects/clusters/applications_controller.rb index c7b6218d007..2a04b007304 100644 --- a/app/controllers/projects/clusters/applications_controller.rb +++ b/app/controllers/projects/clusters/applications_controller.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true class Projects::Clusters::ApplicationsController < Clusters::ApplicationsController - include ProjectUnauthorized - prepend_before_action :project private @@ -12,6 +10,6 @@ class Projects::Clusters::ApplicationsController < Clusters::ApplicationsControl end def project - @project ||= find_routable!(Project, File.join(params[:namespace_id], params[:project_id]), not_found_or_authorized_proc: project_unauthorized_proc) + @project ||= find_routable!(Project, File.join(params[:namespace_id], params[:project_id])) end end diff --git a/app/controllers/projects/clusters_controller.rb b/app/controllers/projects/clusters_controller.rb index feda6deeaa6..98cd66cf6f9 100644 --- a/app/controllers/projects/clusters_controller.rb +++ b/app/controllers/projects/clusters_controller.rb @@ -1,11 +1,13 @@ # frozen_string_literal: true class Projects::ClustersController < Clusters::ClustersController - include ProjectUnauthorized - prepend_before_action :project before_action :repository + before_action do + push_frontend_feature_flag(:prometheus_computed_alerts) + end + layout 'project' private @@ -15,7 +17,7 @@ class Projects::ClustersController < Clusters::ClustersController end def project - @project ||= find_routable!(Project, File.join(params[:namespace_id], params[:project_id]), not_found_or_authorized_proc: project_unauthorized_proc) + @project ||= find_routable!(Project, File.join(params[:namespace_id], params[:project_id])) end def repository diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index b13c0ae3967..939a09d4fd2 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -65,7 +65,11 @@ class Projects::CommitController < Projects::ApplicationController # rubocop: enable CodeReuse/ActiveRecord def merge_requests - @merge_requests = @commit.merge_requests.map do |mr| + @merge_requests = MergeRequestsFinder.new( + current_user, + project_id: @project.id, + commit_sha: @commit.sha + ).execute.map do |mr| { iid: mr.iid, path: merge_request_path(mr), title: mr.title } end diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb index 2510a31c9b3..f540ccee386 100644 --- a/app/controllers/projects/commits_controller.rb +++ b/app/controllers/projects/commits_controller.rb @@ -7,6 +7,7 @@ class Projects::CommitsController < Projects::ApplicationController include RendersCommits prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) } + around_action :allow_gitaly_ref_name_caching before_action :whitelist_query_limiting, except: :commits_root before_action :require_non_empty_project before_action :assign_ref_vars, except: :commits_root diff --git a/app/controllers/projects/deploy_keys_controller.rb b/app/controllers/projects/deploy_keys_controller.rb index 6824a07dc76..514b03e23b5 100644 --- a/app/controllers/projects/deploy_keys_controller.rb +++ b/app/controllers/projects/deploy_keys_controller.rb @@ -38,7 +38,7 @@ class Projects::DeployKeysController < Projects::ApplicationController def update if deploy_key.update(update_params) - flash[:notice] = 'Deploy key was successfully updated.' + flash[:notice] = _('Deploy key was successfully updated.') redirect_to_repository_settings(@project, anchor: 'js-deploy-keys-settings') else render 'edit' diff --git a/app/controllers/projects/environments/prometheus_api_controller.rb b/app/controllers/projects/environments/prometheus_api_controller.rb new file mode 100644 index 00000000000..f8ef23cd83e --- /dev/null +++ b/app/controllers/projects/environments/prometheus_api_controller.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +class Projects::Environments::PrometheusApiController < Projects::ApplicationController + before_action :authorize_read_prometheus! + before_action :environment + + def proxy + result = Prometheus::ProxyService.new( + environment, + proxy_method, + proxy_path, + proxy_params + ).execute + + if result.nil? + return render status: :accepted, json: { + status: _('processing'), + message: _('Not ready yet. Try again later.') + } + end + + if result[:status] == :success + render status: result[:http_status], json: result[:body] + else + render( + status: result[:http_status] || :bad_request, + json: { status: result[:status], message: result[:message] } + ) + end + end + + private + + def query_context + Gitlab::Prometheus::QueryVariables.call(environment) + end + + def environment + @environment ||= project.environments.find(params[:id]) + end + + def proxy_method + request.method + end + + def proxy_path + params[:proxy_path] + end + + def proxy_params + substitute_query_variables(params).permit! + end + + def substitute_query_variables(params) + query = params[:query] + return params unless query + + params.merge(query: query % query_context) + end +end diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb index e9cd475a199..e002a4d349b 100644 --- a/app/controllers/projects/environments_controller.rb +++ b/app/controllers/projects/environments_controller.rb @@ -10,6 +10,12 @@ class Projects::EnvironmentsController < Projects::ApplicationController before_action :environment, only: [:show, :edit, :update, :stop, :terminal, :terminal_websocket_authorize, :metrics] before_action :verify_api_request!, only: :terminal_websocket_authorize before_action :expire_etag_cache, only: [:index] + before_action only: [:metrics, :additional_metrics, :metrics_dashboard] do + push_frontend_feature_flag(:environment_metrics_use_prometheus_endpoint) + push_frontend_feature_flag(:environment_metrics_show_multiple_dashboards) + push_frontend_feature_flag(:grafana_dashboard_link) + push_frontend_feature_flag(:prometheus_computed_alerts) + end def index @environments = project.environments @@ -114,7 +120,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController terminal = environment.terminals.try(:first) if terminal set_workhorse_internal_api_content_type - render json: Gitlab::Workhorse.terminal_websocket(terminal) + render json: Gitlab::Workhorse.channel_websocket(terminal) else render html: 'Not found', status: :not_found end @@ -131,13 +137,13 @@ class Projects::EnvironmentsController < Projects::ApplicationController end def metrics - # Currently, this acts as a hint to load the metrics details into the cache - # if they aren't there already - @metrics = environment.metrics || {} - respond_to do |format| format.html format.json do + # Currently, this acts as a hint to load the metrics details into the cache + # if they aren't there already + @metrics = environment.metrics || {} + render json: @metrics, status: @metrics.any? ? :ok : :no_content end end @@ -146,13 +152,40 @@ class Projects::EnvironmentsController < Projects::ApplicationController def additional_metrics respond_to do |format| format.json do - additional_metrics = environment.additional_metrics || {} + additional_metrics = environment.additional_metrics(*metrics_params) || {} render json: additional_metrics, status: additional_metrics.any? ? :ok : :no_content end end end + def metrics_dashboard + return render_403 unless Feature.enabled?(:environment_metrics_use_prometheus_endpoint, project) + + if Feature.enabled?(:environment_metrics_show_multiple_dashboards, project) + result = dashboard_finder.find(project, current_user, environment, params[:dashboard]) + + result[:all_dashboards] = project.repository.metrics_dashboard_paths + else + result = dashboard_finder.find(project, current_user, environment) + end + + respond_to do |format| + if result[:status] == :success + format.json do + render status: :ok, json: result.slice(:all_dashboards, :dashboard, :status) + end + else + format.json do + render( + status: result[:http_status], + json: result.slice(:all_dashboards, :message, :status) + ) + end + end + end + end + def search respond_to do |format| format.json do @@ -186,6 +219,14 @@ class Projects::EnvironmentsController < Projects::ApplicationController @environment ||= project.environments.find(params[:id]) end + def metrics_params + params.require([:start, :end]) + end + + def dashboard_finder + Gitlab::Metrics::Dashboard::Finder + end + def search_environment_names return [] unless params[:query] diff --git a/app/controllers/projects/git_http_client_controller.rb b/app/controllers/projects/git_http_client_controller.rb index d439db97252..956093b972b 100644 --- a/app/controllers/projects/git_http_client_controller.rb +++ b/app/controllers/projects/git_http_client_controller.rb @@ -15,6 +15,7 @@ class Projects::GitHttpClientController < Projects::ApplicationController alias_method :authenticated_user, :actor # Git clients will not know what authenticity token to send along + skip_around_action :set_session_storage skip_before_action :verify_authenticity_token skip_before_action :repository before_action :authenticate_user @@ -78,24 +79,28 @@ class Projects::GitHttpClientController < Projects::ApplicationController end def parse_repo_path - @project, @wiki, @redirected_path = Gitlab::RepoPath.parse("#{params[:namespace_id]}/#{params[:project_id]}") + @project, @repo_type, @redirected_path = Gitlab::RepoPath.parse("#{params[:namespace_id]}/#{params[:project_id]}") end def render_missing_personal_access_token render plain: "HTTP Basic: Access denied\n" \ - "You must use a personal access token with 'api' scope for Git over HTTP.\n" \ + "You must use a personal access token with 'read_repository' or 'write_repository' scope for Git over HTTP.\n" \ "You can generate one at #{profile_personal_access_tokens_url}", status: :unauthorized end def repository - wiki? ? project.wiki.repository : project.repository + repo_type.repository_for(project) end def wiki? - parse_repo_path unless defined?(@wiki) + repo_type.wiki? + end + + def repo_type + parse_repo_path unless defined?(@repo_type) - @wiki + @repo_type end def handle_basic_authentication(login, password) diff --git a/app/controllers/projects/git_http_controller.rb b/app/controllers/projects/git_http_controller.rb index 30e436365de..e519cc1f158 100644 --- a/app/controllers/projects/git_http_controller.rb +++ b/app/controllers/projects/git_http_controller.rb @@ -4,6 +4,7 @@ class Projects::GitHttpController < Projects::GitHttpClientController include WorkhorseRequest before_action :access_check + prepend_before_action :deny_head_requests, only: [:info_refs] rescue_from Gitlab::GitAccess::UnauthorizedError, with: :render_403 rescue_from Gitlab::GitAccess::NotFoundError, with: :render_404 @@ -20,6 +21,8 @@ class Projects::GitHttpController < Projects::GitHttpClientController # POST /foo/bar.git/git-upload-pack (git pull) def git_upload_pack + enqueue_fetch_statistics_update + render_ok end @@ -30,6 +33,10 @@ class Projects::GitHttpController < Projects::GitHttpClientController private + def deny_head_requests + head :forbidden if request.head? + end + def download_request? upload_pack? end @@ -48,7 +55,7 @@ class Projects::GitHttpController < Projects::GitHttpClientController def render_ok set_workhorse_internal_api_content_type - render json: Gitlab::Workhorse.git_http_ok(repository, wiki?, user, action_name) + render json: Gitlab::Workhorse.git_http_ok(repository, repo_type, user, action_name) end def render_403(exception) @@ -67,6 +74,13 @@ class Projects::GitHttpController < Projects::GitHttpClientController render plain: exception.message, status: :service_unavailable end + def enqueue_fetch_statistics_update + return if wiki? + return unless project.daily_statistics_enabled? + + ProjectDailyStatisticsWorker.perform_async(project.id) + end + def access @access ||= access_klass.new(access_actor, project, 'http', authentication_abilities: authentication_abilities, @@ -85,7 +99,7 @@ class Projects::GitHttpController < Projects::GitHttpClientController end def access_klass - @access_klass ||= wiki? ? Gitlab::GitAccessWiki : Gitlab::GitAccess + @access_klass ||= repo_type.access_checker_class end def project_path diff --git a/app/controllers/projects/graphs_controller.rb b/app/controllers/projects/graphs_controller.rb index c80fce513f6..67d3f49af18 100644 --- a/app/controllers/projects/graphs_controller.rb +++ b/app/controllers/projects/graphs_controller.rb @@ -46,12 +46,8 @@ class Projects::GraphsController < Projects::ApplicationController def get_languages @languages = - if @project.repository_languages.present? - @project.repository_languages.map do |lang| - { value: lang.share, label: lang.name, color: lang.color, highlight: lang.color } - end - else - @project.repository.languages + ::Projects::RepositoryLanguagesService.new(@project, current_user).execute.map do |lang| + { value: lang.share, label: lang.name, color: lang.color, highlight: lang.color } end end diff --git a/app/controllers/projects/group_links_controller.rb b/app/controllers/projects/group_links_controller.rb index 7c713c19762..dc65f9959db 100644 --- a/app/controllers/projects/group_links_controller.rb +++ b/app/controllers/projects/group_links_controller.rb @@ -13,11 +13,12 @@ class Projects::GroupLinksController < Projects::ApplicationController group = Group.find(params[:link_group_id]) if params[:link_group_id].present? if group - return render_404 unless can?(current_user, :read_group, group) + result = Projects::GroupLinks::CreateService.new(project, current_user, group_link_create_params).execute(group) + return render_404 if result[:http_status] == 404 - Projects::GroupLinks::CreateService.new(project, current_user, group_link_create_params).execute(group) + flash[:alert] = result[:message] if result[:http_status] == 409 else - flash[:alert] = 'Please select a group.' + flash[:alert] = _('Please select a group.') end redirect_to project_project_members_path(project) diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb index bc84418b79f..5fa0339f44d 100644 --- a/app/controllers/projects/hooks_controller.rb +++ b/app/controllers/projects/hooks_controller.rb @@ -32,7 +32,7 @@ class Projects::HooksController < Projects::ApplicationController def update if hook.update(hook_params) - flash[:notice] = 'Hook was successfully updated.' + flash[:notice] = _('Hook was successfully updated.') redirect_to project_settings_integrations_path(@project) else render 'edit' diff --git a/app/controllers/projects/imports_controller.rb b/app/controllers/projects/imports_controller.rb index 8b33fa85c1e..afbf9fd7720 100644 --- a/app/controllers/projects/imports_controller.rb +++ b/app/controllers/projects/imports_controller.rb @@ -2,6 +2,7 @@ class Projects::ImportsController < Projects::ApplicationController include ContinueParams + include ImportUrlParams # Authorize before_action :authorize_admin_project! @@ -14,7 +15,7 @@ class Projects::ImportsController < Projects::ApplicationController def create if @project.update(import_params) - @project.import_state.reload.schedule + @project.import_state.reset.schedule end redirect_to project_import_path(@project) @@ -42,9 +43,9 @@ class Projects::ImportsController < Projects::ApplicationController def finished_notice if @project.forked? - 'The project was successfully forked.' + _('The project was successfully forked.') else - 'The project was successfully imported.' + _('The project was successfully imported.') end end @@ -67,10 +68,12 @@ class Projects::ImportsController < Projects::ApplicationController end def import_params_attributes - [:import_url] + [] end def import_params - params.require(:project).permit(import_params_attributes) + params.require(:project) + .permit(import_params_attributes) + .merge(import_url_params) end end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index b9d02a62fc3..b4d89db20c5 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -10,11 +10,11 @@ class Projects::IssuesController < Projects::ApplicationController include SpammableActions include RecordUserLastActivity - def self.issue_except_actions + def issue_except_actions %i[index calendar new create bulk_update import_csv] end - def self.set_issuables_index_only_actions + def set_issuables_index_only_actions %i[index calendar] end @@ -25,9 +25,9 @@ class Projects::IssuesController < Projects::ApplicationController before_action :whitelist_query_limiting, only: [:create, :create_merge_request, :move, :bulk_update] before_action :check_issues_available! - before_action :issue, except: issue_except_actions + before_action :issue, unless: ->(c) { c.issue_except_actions.include?(c.action_name.to_sym) } - before_action :set_issuables_index, only: set_issuables_index_only_actions + before_action :set_issuables_index, if: ->(c) { c.set_issuables_index_only_actions.include?(c.action_name.to_sym) } # Allow write(create) issue before_action :authorize_create_issue!, only: [:new, :create] @@ -39,6 +39,7 @@ class Projects::IssuesController < Projects::ApplicationController before_action :authorize_create_merge_request_from!, only: [:create_merge_request] before_action :authorize_import_issues!, only: [:import_csv] + before_action :authorize_download_code!, only: [:related_branches] before_action :set_suggested_issues_feature_flags, only: [:new] @@ -95,9 +96,9 @@ class Projects::IssuesController < Projects::ApplicationController if service.discussions_to_resolve.count(&:resolved?) > 0 flash[:notice] = if service.discussion_to_resolve_id - "Resolved 1 discussion." + _("Resolved 1 discussion.") else - "Resolved all discussions." + _("Resolved all discussions.") end end @@ -131,18 +132,6 @@ class Projects::IssuesController < Projects::ApplicationController render_conflict_response end - def referenced_merge_requests - @merge_requests, @closed_by_merge_requests = ::Issues::ReferencedMergeRequestsService.new(project, current_user).execute(issue) - - respond_to do |format| - format.json do - render json: { - html: view_to_html_string('projects/issues/_merge_requests') - } - end - end - end - def related_branches @related_branches = Issues::RelatedBranchesService.new(project, current_user).execute(issue) diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb index d5ce790e2d9..2a4933e7bc2 100644 --- a/app/controllers/projects/jobs_controller.rb +++ b/app/controllers/projects/jobs_controller.rb @@ -122,7 +122,7 @@ class Projects::JobsController < Projects::ApplicationController def erase if @build.erase(erased_by: current_user) redirect_to project_job_path(project, @build), - notice: "Job has been successfully erased!" + notice: _("Job has been successfully erased!") else respond_422 end @@ -157,7 +157,7 @@ class Projects::JobsController < Projects::ApplicationController # GET .../terminal.ws : implemented in gitlab-workhorse def terminal_websocket_authorize set_workhorse_internal_api_content_type - render json: Gitlab::Workhorse.terminal_websocket(@build.terminal_specification) + render json: Gitlab::Workhorse.channel_websocket(@build.terminal_specification) end private diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb index 640038818f2..386a1f00bd2 100644 --- a/app/controllers/projects/labels_controller.rb +++ b/app/controllers/projects/labels_controller.rb @@ -132,7 +132,7 @@ class Projects::LabelsController < Projects::ApplicationController respond_to do |format| format.html do redirect_to(project_labels_path(@project), - notice: 'Failed to promote label due to internal error. Please contact administrators.') + notice: _('Failed to promote label due to internal error. Please contact administrators.')) end format.js end diff --git a/app/controllers/projects/lfs_api_controller.rb b/app/controllers/projects/lfs_api_controller.rb index be40077d389..42c415757f9 100644 --- a/app/controllers/projects/lfs_api_controller.rb +++ b/app/controllers/projects/lfs_api_controller.rb @@ -26,7 +26,7 @@ class Projects::LfsApiController < Projects::GitHttpClientController def deprecated render( json: { - message: 'Server supports batch API only, please update your Git LFS client to version 1.0.1 and up.', + message: _('Server supports batch API only, please update your Git LFS client to version 1.0.1 and up.'), documentation_url: "#{Gitlab.config.gitlab.url}/help" }, status: :not_implemented @@ -62,7 +62,7 @@ class Projects::LfsApiController < Projects::GitHttpClientController else object[:error] = { code: 404, - message: "Object does not exist on the server or you don't have permissions to access it" + message: _("Object does not exist on the server or you don't have permissions to access it") } end end diff --git a/app/controllers/projects/merge_requests/application_controller.rb b/app/controllers/projects/merge_requests/application_controller.rb index 6045ee4e171..f2a6268b3e9 100644 --- a/app/controllers/projects/merge_requests/application_controller.rb +++ b/app/controllers/projects/merge_requests/application_controller.rb @@ -7,11 +7,15 @@ class Projects::MergeRequests::ApplicationController < Projects::ApplicationCont private - # rubocop: disable CodeReuse/ActiveRecord def merge_request - @issuable = @merge_request ||= @project.merge_requests.includes(author: :status).find_by!(iid: params[:id]) + @issuable = + @merge_request ||= + merge_request_includes(@project.merge_requests).find_by_iid!(params[:id]) + end + + def merge_request_includes(association) + association.includes(:metrics, :assignees, author: :status) # rubocop:disable CodeReuse/ActiveRecord end - # rubocop: enable CodeReuse/ActiveRecord def merge_request_params params.require(:merge_request).permit(merge_request_params_attributes) @@ -20,7 +24,6 @@ class Projects::MergeRequests::ApplicationController < Projects::ApplicationCont def merge_request_params_attributes [ :allow_collaboration, - :assignee_id, :description, :force_remove_source_branch, :lock_version, @@ -35,6 +38,7 @@ class Projects::MergeRequests::ApplicationController < Projects::ApplicationCont :title, :discussion_locked, label_ids: [], + assignee_ids: [], update_task: [:index, :checked, :line_number, :line_source] ] end diff --git a/app/controllers/projects/merge_requests/conflicts_controller.rb b/app/controllers/projects/merge_requests/conflicts_controller.rb index 045a4e974fe..011ac9a42f8 100644 --- a/app/controllers/projects/merge_requests/conflicts_controller.rb +++ b/app/controllers/projects/merge_requests/conflicts_controller.rb @@ -16,12 +16,12 @@ class Projects::MergeRequests::ConflictsController < Projects::MergeRequests::Ap render json: @conflicts_list elsif @merge_request.can_be_merged? render json: { - message: 'The merge conflicts for this merge request have already been resolved. Please return to the merge request.', + message: _('The merge conflicts for this merge request have already been resolved. Please return to the merge request.'), type: 'error' } else render json: { - message: 'The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally.', + message: _('The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally.'), type: 'error' } end @@ -43,7 +43,7 @@ class Projects::MergeRequests::ConflictsController < Projects::MergeRequests::Ap return render_404 unless @conflicts_list.can_be_resolved_in_ui? if @merge_request.can_be_merged? - render status: :bad_request, json: { message: 'The merge conflicts for this merge request have already been resolved.' } + render status: :bad_request, json: { message: _('The merge conflicts for this merge request have already been resolved.') } return end @@ -52,7 +52,7 @@ class Projects::MergeRequests::ConflictsController < Projects::MergeRequests::Ap .new(merge_request) .execute(current_user, params) - flash[:notice] = 'All merge conflicts were resolved. The merge request can now be merged.' + flash[:notice] = _('All merge conflicts were resolved. The merge request can now be merged.') render json: { redirect_to: project_merge_request_url(@project, @merge_request, resolved_conflicts: true) } rescue Gitlab::Git::Conflict::Resolver::ResolutionError => e diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb index 518d41bd3fb..456d2c34768 100644 --- a/app/controllers/projects/merge_requests/diffs_controller.rb +++ b/app/controllers/projects/merge_requests/diffs_controller.rb @@ -46,8 +46,8 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic # rubocop: disable CodeReuse/ActiveRecord def commit - return nil unless commit_id = params[:commit_id].presence - return nil unless @merge_request.all_commits.exists?(sha: commit_id) + return unless commit_id = params[:commit_id].presence + return unless @merge_request.all_commits.exists?(sha: commit_id) @commit ||= @project.commit(commit_id) end diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 46a44841c31..135117926be 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -16,9 +16,7 @@ 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(:diff_tree_filtering, default_enabled: true) - end + around_action :allow_gitaly_ref_name_caching, only: [:index, :show] def index @merge_requests = @issuables @@ -35,7 +33,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo def show close_merge_request_if_no_source_project - mark_merge_request_mergeable + @merge_request.check_mergeability respond_to do |format| format.html do @@ -100,20 +98,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo end def test_reports - result = @merge_request.compare_test_reports - - case result[:status] - when :parsing - Gitlab::PollingInterval.set_header(response, interval: 3000) - - render json: '', status: :no_content - when :parsed - render json: result[:data].to_json, status: :ok - when :error - render json: { status_reason: result[:status_reason] }, status: :bad_request - else - render json: { status_reason: 'Unknown error' }, status: :internal_server_error - end + reports_response(@merge_request.compare_test_reports) end def edit @@ -160,14 +145,12 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo render partial: 'projects/merge_requests/widget/commit_change_content', layout: false end - def cancel_merge_when_pipeline_succeeds - unless @merge_request.can_cancel_merge_when_pipeline_succeeds?(current_user) + def cancel_auto_merge + unless @merge_request.can_cancel_auto_merge?(current_user) return access_denied! end - ::MergeRequests::MergeWhenPipelineSucceedsService - .new(@project, current_user) - .cancel(@merge_request) + AutoMergeService.new(project, current_user).cancel(@merge_request) render json: serialize_widget(@merge_request) end @@ -244,12 +227,12 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo end def merge_params_attributes - [:should_remove_source_branch, :commit_message, :squash_commit_message, :squash] + [:should_remove_source_branch, :commit_message, :squash_commit_message, :squash, :auto_merge_strategy] end - def merge_when_pipeline_succeeds_active? - params[:merge_when_pipeline_succeeds].present? && - @merge_request.head_pipeline && @merge_request.head_pipeline.active? + def auto_merge_requested? + # Support params[:merge_when_pipeline_succeeds] during the transition period + params[:auto_merge_strategy].present? || params[:merge_when_pipeline_succeeds].present? end def close_merge_request_if_no_source_project @@ -268,14 +251,10 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo @merge_request.has_no_commits? && !@merge_request.target_branch_exists? end - def mark_merge_request_mergeable - @merge_request.check_if_can_be_merged - end - def merge! - # Disable the CI check if merge_when_pipeline_succeeds is enabled since we have + # Disable the CI check if auto_merge_strategy is specified since we have # to wait until CI completes to know - unless @merge_request.mergeable?(skip_ci_check: merge_when_pipeline_succeeds_active?) + unless @merge_request.mergeable?(skip_ci_check: auto_merge_requested?) return :failed end @@ -289,24 +268,10 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo @merge_request.update(merge_error: nil, squash: merge_params.fetch(:squash, false)) - if params[:merge_when_pipeline_succeeds].present? - return :failed unless @merge_request.actual_head_pipeline - - if @merge_request.actual_head_pipeline.active? - ::MergeRequests::MergeWhenPipelineSucceedsService - .new(@project, current_user, merge_params) - .execute(@merge_request) - - :merge_when_pipeline_succeeds - elsif @merge_request.actual_head_pipeline.success? - # This can be triggered when a user clicks the auto merge button while - # the tests finish at about the same time - @merge_request.merge_async(current_user.id, merge_params) - - :success - else - :failed - end + if auto_merge_requested? + AutoMergeService.new(project, current_user, merge_params) + .execute(merge_request, + params[:auto_merge_strategy] || AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS) else @merge_request.merge_async(current_user.id, merge_params) @@ -355,4 +320,19 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo # Also see https://gitlab.com/gitlab-org/gitlab-ce/issues/42441 Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-ce/issues/42438') end + + def reports_response(report_comparison) + case report_comparison[:status] + when :parsing + ::Gitlab::PollingInterval.set_header(response, interval: 3000) + + render json: '', status: :no_content + when :parsed + render json: report_comparison[:data].to_json, status: :ok + when :error + render json: { status_reason: report_comparison[:status_reason] }, status: :bad_request + else + render json: { status_reason: 'Unknown error' }, status: :internal_server_error + end + end end diff --git a/app/controllers/projects/mirrors_controller.rb b/app/controllers/projects/mirrors_controller.rb index ab7ab13657a..6c6adc233b7 100644 --- a/app/controllers/projects/mirrors_controller.rb +++ b/app/controllers/projects/mirrors_controller.rb @@ -18,7 +18,7 @@ class Projects::MirrorsController < Projects::ApplicationController result = ::Projects::UpdateService.new(project, current_user, mirror_params).execute if result[:status] == :success - flash[:notice] = 'Mirroring settings were successfully updated.' + flash[:notice] = _('Mirroring settings were successfully updated.') else flash[:alert] = project.errors.full_messages.join(', ').html_safe end @@ -38,7 +38,7 @@ class Projects::MirrorsController < Projects::ApplicationController def update_now if params[:sync_remote] project.update_remote_mirrors - flash[:notice] = "The remote repository is being updated..." + flash[:notice] = _("The remote repository is being updated...") end redirect_to_repository_settings(project, anchor: 'js-push-remote-settings') @@ -81,6 +81,7 @@ class Projects::MirrorsController < Projects::ApplicationController password ssh_known_hosts regenerate_ssh_private_key + _destroy ] ] end diff --git a/app/controllers/projects/pages_domains_controller.rb b/app/controllers/projects/pages_domains_controller.rb index 58b1bc54181..89f21d8dadb 100644 --- a/app/controllers/projects/pages_domains_controller.rb +++ b/app/controllers/projects/pages_domains_controller.rb @@ -65,11 +65,11 @@ class Projects::PagesDomainsController < Projects::ApplicationController private def create_params - params.require(:pages_domain).permit(:key, :certificate, :domain) + params.require(:pages_domain).permit(:key, :certificate, :domain, :auto_ssl_enabled) end def update_params - params.require(:pages_domain).permit(:key, :certificate) + params.require(:pages_domain).permit(:key, :certificate, :auto_ssl_enabled) end # rubocop: disable CodeReuse/ActiveRecord diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb index acf56f0eb6a..72e939a3310 100644 --- a/app/controllers/projects/pipeline_schedules_controller.rb +++ b/app/controllers/projects/pipeline_schedules_controller.rb @@ -50,9 +50,11 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController job_id = RunPipelineScheduleWorker.perform_async(schedule.id, current_user.id) if job_id - flash[:notice] = "Successfully scheduled a pipeline to run. Go to the <a href=\"#{project_pipelines_path(@project)}\">Pipelines page</a> for details.".html_safe + pipelines_link_start = "<a href=\"#{project_pipelines_path(@project)}\">" + message = _("Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details.") % { pipelines_link_start: pipelines_link_start, pipelines_link_end: "</a>" } + flash[:notice] = message.html_safe else - flash[:alert] = 'Unable to schedule a pipeline to run immediately' + flash[:alert] = _('Unable to schedule a pipeline to run immediately') end redirect_to pipeline_schedules_path(@project) @@ -85,7 +87,7 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController return unless limiter.throttled?([current_user, schedule], 1) - flash[:alert] = 'You cannot play this scheduled pipeline at the moment. Please wait a minute.' + flash[:alert] = _('You cannot play this scheduled pipeline at the moment. Please wait a minute.') redirect_to pipeline_schedules_path(@project) end @@ -96,7 +98,7 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController def schedule_params params.require(:schedule) .permit(:description, :cron, :cron_timezone, :ref, :active, - variables_attributes: [:id, :key, :secret_value, :_destroy] ) + variables_attributes: [:id, :variable_type, :key, :secret_value, :_destroy] ) end def authorize_play_pipeline_schedule! diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 6a86f8ca729..db3b7c8b177 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -8,6 +8,8 @@ class Projects::PipelinesController < Projects::ApplicationController before_action :authorize_create_pipeline!, only: [:new, :create] before_action :authorize_update_pipeline!, only: [:retry, :cancel] + around_action :allow_gitaly_ref_name_caching, only: [:index, :show] + wrap_parameters Ci::Pipeline POLLING_INTERVAL = 10_000 @@ -31,10 +33,7 @@ class Projects::PipelinesController < Projects::ApplicationController Gitlab::PollingInterval.set_header(response, interval: POLLING_INTERVAL) render json: { - pipelines: PipelineSerializer - .new(project: @project, current_user: @current_user) - .with_pagination(request, response) - .represent(@pipelines, disable_coverage: true, preload: true), + pipelines: serialize_pipelines, count: { all: @pipelines_count, running: @running_count, @@ -150,6 +149,13 @@ class Projects::PipelinesController < Projects::ApplicationController private + def serialize_pipelines + PipelineSerializer + .new(project: @project, current_user: @current_user) + .with_pagination(request, response) + .represent(@pipelines, disable_coverage: true, preload: true) + end + def render_show respond_to do |format| format.html do @@ -163,7 +169,7 @@ class Projects::PipelinesController < Projects::ApplicationController end def create_params - params.require(:pipeline).permit(:ref, variables_attributes: %i[key secret_value]) + params.require(:pipeline).permit(:ref, variables_attributes: %i[key variable_type secret_value]) end # rubocop: disable CodeReuse/ActiveRecord diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb index b97fbe19bbf..b3447812ef2 100644 --- a/app/controllers/projects/refs_controller.rb +++ b/app/controllers/projects/refs_controller.rb @@ -4,6 +4,8 @@ class Projects::RefsController < Projects::ApplicationController include ExtractsPath include TreeHelper + around_action :allow_gitaly_ref_name_caching, only: [:logs_tree] + before_action :require_non_empty_project before_action :validate_ref_id before_action :assign_ref_vars diff --git a/app/controllers/projects/repositories_controller.rb b/app/controllers/projects/repositories_controller.rb index 4eeaeb860ee..3b4215b766e 100644 --- a/app/controllers/projects/repositories_controller.rb +++ b/app/controllers/projects/repositories_controller.rb @@ -23,7 +23,7 @@ class Projects::RepositoriesController < Projects::ApplicationController append_sha = false if @filename == shortname end - send_git_archive @repository, ref: @ref, format: params[:format], append_sha: append_sha + send_git_archive @repository, ref: @ref, path: params[:path], format: params[:format], append_sha: append_sha rescue => ex logger.error("#{self.class.name}: #{ex}") git_not_found! diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb index 91f40b90aa8..ca62f54813b 100644 --- a/app/controllers/projects/runners_controller.rb +++ b/app/controllers/projects/runners_controller.rb @@ -15,7 +15,7 @@ class Projects::RunnersController < Projects::ApplicationController def update if Ci::UpdateRunnerService.new(@runner).update(runner_params) - redirect_to project_runner_path(@project, @runner), notice: 'Runner was successfully updated.' + redirect_to project_runner_path(@project, @runner), notice: _('Runner was successfully updated.') else render 'edit' end @@ -31,17 +31,17 @@ class Projects::RunnersController < Projects::ApplicationController def resume if Ci::UpdateRunnerService.new(@runner).update(active: true) - redirect_to project_runners_path(@project), notice: 'Runner was successfully updated.' + redirect_to project_runners_path(@project), notice: _('Runner was successfully updated.') else - redirect_to project_runners_path(@project), alert: 'Runner was not updated.' + redirect_to project_runners_path(@project), alert: _('Runner was not updated.') end end def pause if Ci::UpdateRunnerService.new(@runner).update(active: false) - redirect_to project_runners_path(@project), notice: 'Runner was successfully updated.' + redirect_to project_runners_path(@project), notice: _('Runner was successfully updated.') else - redirect_to project_runners_path(@project), alert: 'Runner was not updated.' + redirect_to project_runners_path(@project), alert: _('Runner was not updated.') end end diff --git a/app/controllers/projects/serverless/functions_controller.rb b/app/controllers/projects/serverless/functions_controller.rb index 39eca10134f..4b0d001fca6 100644 --- a/app/controllers/projects/serverless/functions_controller.rb +++ b/app/controllers/projects/serverless/functions_controller.rb @@ -3,29 +3,20 @@ module Projects module Serverless class FunctionsController < Projects::ApplicationController - include ProjectUnauthorized - before_action :authorize_read_cluster! - INDEX_PRIMING_INTERVAL = 15_000 - INDEX_POLLING_INTERVAL = 60_000 - def index respond_to do |format| format.json do functions = finder.execute - if functions.any? - Gitlab::PollingInterval.set_header(response, interval: INDEX_POLLING_INTERVAL) - render json: serialize_function(functions) - else - Gitlab::PollingInterval.set_header(response, interval: INDEX_PRIMING_INTERVAL) - head :no_content - end + render json: { + knative_installed: finder.knative_installed, + functions: serialize_function(functions) + }.to_json end format.html do - @installed = finder.installed? render end end @@ -33,6 +24,8 @@ module Projects def show @service = serialize_function(finder.service(params[:environment_id], params[:id])) + @prometheus = finder.has_prometheus?(params[:environment_id]) + return not_found if @service.nil? respond_to do |format| @@ -44,10 +37,24 @@ module Projects end end + def metrics + respond_to do |format| + format.json do + metrics = finder.invocation_metrics(params[:environment_id], params[:id]) + + if metrics.nil? + head :no_content + else + render json: metrics + end + end + end + end + private def finder - Projects::Serverless::FunctionsFinder.new(project.clusters) + Projects::Serverless::FunctionsFinder.new(project) end def serialize_function(function) diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index f1c9d0d0f77..e0df51590ae 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -43,20 +43,20 @@ class Projects::ServicesController < Projects::ApplicationController if outcome[:success] {} else - { error: true, message: 'Test failed.', service_response: outcome[:result].to_s, test_failed: true } + { error: true, message: _('Test failed.'), service_response: outcome[:result].to_s, test_failed: true } end else - { error: true, message: 'Validations failed.', service_response: @service.errors.full_messages.join(','), test_failed: false } + { error: true, message: _('Validations failed.'), service_response: @service.errors.full_messages.join(','), test_failed: false } end rescue Gitlab::HTTP::BlockedUrlError => e - { error: true, message: 'Test failed.', service_response: e.message, test_failed: true } + { error: true, message: _('Test failed.'), service_response: e.message, test_failed: true } end def success_message if @service.active? - "#{@service.title} activated." + _("%{service_title} activated.") % { service_title: @service.title } else - "#{@service.title} settings saved, but not activated." + _("%{service_title} settings saved, but not activated.") % { service_title: @service.title } end end diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index f2f63e986bb..1b8d479209b 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -13,13 +13,13 @@ module Projects Projects::UpdateService.new(project, current_user, update_params).tap do |service| result = service.execute if result[:status] == :success - flash[:notice] = "Pipelines settings for '#{@project.name}' were successfully updated." + flash[:notice] = _("Pipelines settings for '%{project_name}' were successfully updated.") % { project_name: @project.name } run_autodevops_pipeline(service) redirect_to project_settings_ci_cd_path(@project) else - render 'show' + redirect_to project_settings_ci_cd_path(@project), alert: result[:message] end end end @@ -39,7 +39,7 @@ module Projects def reset_registration_token @project.reset_runners_token! - flash[:notice] = 'New runners registration token has been generated!' + flash[:notice] = _('New runners registration token has been generated!') redirect_to namespace_project_settings_ci_cd_path end @@ -50,7 +50,8 @@ module Projects :runners_token, :builds_enabled, :build_allow_git_fetch, :build_timeout_human_readable, :build_coverage_regex, :public_builds, :auto_cancel_pending_pipelines, :ci_config_path, - auto_devops_attributes: [:id, :domain, :enabled, :deploy_strategy] + auto_devops_attributes: [:id, :domain, :enabled, :deploy_strategy], + ci_cd_settings_attributes: [:default_git_depth] ) end @@ -58,7 +59,7 @@ module Projects return unless service.run_auto_devops_pipeline? if @project.empty_repo? - flash[:warning] = "This repository is currently empty. A new Auto DevOps pipeline will be created after a new file has been pushed to a branch." + flash[:warning] = _("This repository is currently empty. A new Auto DevOps pipeline will be created after a new file has been pushed to a branch.") return end diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb index 521ec2acebb..b5c77e5bbf4 100644 --- a/app/controllers/projects/settings/operations_controller.rb +++ b/app/controllers/projects/settings/operations_controller.rb @@ -3,9 +3,12 @@ module Projects module Settings class OperationsController < Projects::ApplicationController - before_action :check_license before_action :authorize_update_environment! + before_action do + push_frontend_feature_flag(:grafana_dashboard_link) + end + helper_method :error_tracking_setting def show @@ -14,16 +17,37 @@ module Projects def update result = ::Projects::Operations::UpdateService.new(project, current_user, update_params).execute + render_update_response(result) + end + + private + + # overridden in EE + def render_update_response(result) + respond_to do |format| + format.json do + render_update_json_response(result) + end + end + end + + def render_update_json_response(result) if result[:status] == :success flash[:notice] = _('Your changes have been saved') - redirect_to project_settings_operations_path(@project) + render json: { + status: result[:status] + } else - render 'show' + render( + status: result[:http_status] || :bad_request, + json: { + status: result[:status], + message: result[:message] + } + ) end end - private - def error_tracking_setting @error_tracking_setting ||= project.error_tracking_setting || project.build_error_tracking_setting @@ -35,11 +59,16 @@ module Projects # overridden in EE def permitted_project_params - { error_tracking_setting_attributes: [:enabled, :api_url, :token] } - end + { + metrics_setting_attributes: [:external_dashboard_url], - def check_license - render_404 unless helpers.settings_operations_available? + error_tracking_setting_attributes: [ + :enabled, + :api_host, + :token, + project: [:slug, :name, :organization_slug, :organization_name] + ] + } end end end diff --git a/app/controllers/projects/stages_controller.rb b/app/controllers/projects/stages_controller.rb new file mode 100644 index 00000000000..c8db5b1277f --- /dev/null +++ b/app/controllers/projects/stages_controller.rb @@ -0,0 +1,25 @@ +# 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/tags/releases_controller.rb b/app/controllers/projects/tags/releases_controller.rb index 334e1847cc8..5e4c601a693 100644 --- a/app/controllers/projects/tags/releases_controller.rb +++ b/app/controllers/projects/tags/releases_controller.rb @@ -12,16 +12,13 @@ class Projects::Tags::ReleasesController < Projects::ApplicationController end def update - # Release belongs to Tag which is not active record object, - # it exists only to save a description to each Tag. - # If description is empty we should destroy the existing record. if release_params[:description].present? release.update(release_params) else release.destroy end - redirect_to project_tag_path(@project, @tag.name) + redirect_to project_tag_path(@project, tag.name) end private @@ -30,11 +27,10 @@ class Projects::Tags::ReleasesController < Projects::ApplicationController @tag ||= @repository.find_tag(params[:tag_id]) end - # rubocop: disable CodeReuse/ActiveRecord def release - @release ||= @project.releases.find_or_initialize_by(tag: @tag.name) + @release ||= Releases::CreateService.new(project, current_user, tag: @tag.name) + .find_or_build_release end - # rubocop: enable CodeReuse/ActiveRecord def release_params params.require(:release).permit(:description) diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb index edebfc55c17..7509cc29a76 100644 --- a/app/controllers/projects/tree_controller.rb +++ b/app/controllers/projects/tree_controller.rb @@ -6,6 +6,8 @@ class Projects::TreeController < Projects::ApplicationController include CreatesCommit include ActionView::Helpers::SanitizeHelper + around_action :allow_gitaly_ref_name_caching, only: [:show] + before_action :require_non_empty_project, except: [:new, :create] before_action :assign_ref_vars before_action :assign_dir_vars, only: [:create_dir] @@ -37,7 +39,7 @@ class Projects::TreeController < Projects::ApplicationController def create_dir return render_404 unless @commit_params.values.all? - create_commit(Files::CreateDirService, success_notice: "The directory has been successfully created.", + create_commit(Files::CreateDirService, success_notice: _("The directory has been successfully created."), success_path: project_tree_path(@project, File.join(@branch_name, @dir_name)), failure_path: project_tree_path(@project, @ref)) end diff --git a/app/controllers/projects/triggers_controller.rb b/app/controllers/projects/triggers_controller.rb index c7b4ebb2b24..284e119ca06 100644 --- a/app/controllers/projects/triggers_controller.rb +++ b/app/controllers/projects/triggers_controller.rb @@ -16,9 +16,9 @@ class Projects::TriggersController < Projects::ApplicationController @trigger = project.triggers.create(trigger_params.merge(owner: current_user)) if @trigger.valid? - flash[:notice] = 'Trigger was created successfully.' + flash[:notice] = _('Trigger was created successfully.') else - flash[:alert] = 'You could not create a new trigger.' + flash[:alert] = _('You could not create a new trigger.') end redirect_to project_settings_ci_cd_path(@project, anchor: 'js-pipeline-triggers') @@ -26,9 +26,9 @@ class Projects::TriggersController < Projects::ApplicationController def take_ownership if trigger.update(owner: current_user) - flash[:notice] = 'Trigger was re-assigned.' + flash[:notice] = _('Trigger was re-assigned.') else - flash[:alert] = 'You could not take ownership of trigger.' + flash[:alert] = _('You could not take ownership of trigger.') end redirect_to project_settings_ci_cd_path(@project, anchor: 'js-pipeline-triggers') @@ -39,7 +39,7 @@ class Projects::TriggersController < Projects::ApplicationController def update if trigger.update(trigger_params) - redirect_to project_settings_ci_cd_path(@project, anchor: 'js-pipeline-triggers'), notice: 'Trigger was successfully updated.' + redirect_to project_settings_ci_cd_path(@project, anchor: 'js-pipeline-triggers'), notice: _('Trigger was successfully updated.') else render action: "edit" end @@ -47,9 +47,9 @@ class Projects::TriggersController < Projects::ApplicationController def destroy if trigger.destroy - flash[:notice] = "Trigger removed." + flash[:notice] = _("Trigger removed.") else - flash[:alert] = "Could not remove the trigger." + flash[:alert] = _("Could not remove the trigger.") end redirect_to project_settings_ci_cd_path(@project, anchor: 'js-pipeline-triggers'), status: :found diff --git a/app/controllers/projects/variables_controller.rb b/app/controllers/projects/variables_controller.rb index bb658bfcc19..646728e8167 100644 --- a/app/controllers/projects/variables_controller.rb +++ b/app/controllers/projects/variables_controller.rb @@ -38,6 +38,6 @@ class Projects::VariablesController < Projects::ApplicationController end def variable_params_attributes - %i[id key secret_value protected _destroy] + %i[id variable_type key secret_value protected masked _destroy] end end diff --git a/app/controllers/projects/wikis_controller.rb b/app/controllers/projects/wikis_controller.rb index 88dd111132b..fa5bdbc7d49 100644 --- a/app/controllers/projects/wikis_controller.rb +++ b/app/controllers/projects/wikis_controller.rb @@ -16,7 +16,10 @@ class Projects::WikisController < Projects::ApplicationController end def pages - @wiki_pages = Kaminari.paginate_array(@project_wiki.pages).page(params[:page]) + @wiki_pages = Kaminari.paginate_array( + @project_wiki.list_pages(sort: params[:sort], direction: params[:direction]) + ).page(params[:page]) + @wiki_entries = WikiPage.group_by_directory(@wiki_pages) end @@ -49,7 +52,7 @@ class Projects::WikisController < Projects::ApplicationController if @page.valid? redirect_to( project_wiki_path(@project, @page), - notice: 'Wiki was successfully updated.' + notice: _('Wiki was successfully updated.') ) else render 'edit' @@ -65,7 +68,7 @@ class Projects::WikisController < Projects::ApplicationController if @page.persisted? redirect_to( project_wiki_path(@project, @page), - notice: 'Wiki was successfully updated.' + notice: _('Wiki was successfully updated.') ) else render action: "edit" @@ -85,7 +88,7 @@ class Projects::WikisController < Projects::ApplicationController else redirect_to( project_wiki_path(@project, :home), - notice: "Page not found" + notice: _("Page not found") ) end end @@ -95,7 +98,7 @@ class Projects::WikisController < Projects::ApplicationController redirect_to project_wiki_path(@project, :home), status: 302, - notice: "Page was successfully deleted" + notice: _("Page was successfully deleted") rescue Gitlab::Git::Wiki::OperationError => e @error = e render 'edit' @@ -115,10 +118,10 @@ class Projects::WikisController < Projects::ApplicationController @sidebar_page = @project_wiki.find_sidebar(params[:version_id]) unless @sidebar_page # Fallback to default sidebar - @sidebar_wiki_entries = WikiPage.group_by_directory(@project_wiki.pages(limit: 15)) + @sidebar_wiki_entries = WikiPage.group_by_directory(@project_wiki.list_pages(limit: 15)) end rescue ProjectWiki::CouldNotCreateWikiError - flash[:notice] = "Could not create Wiki Repository at this time. Please try again later." + flash[:notice] = _("Could not create Wiki Repository at this time. Please try again later.") redirect_to project_path(@project) false end @@ -155,7 +158,7 @@ class Projects::WikisController < Projects::ApplicationController end def set_encoding_error - flash.now[:notice] = "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository." + flash.now[:notice] = _("The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository.") end def file_blob |