diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-07-26 15:10:08 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-07-26 15:10:08 +0300 |
commit | c4af99d56fdef59d1da557d88a334f52e7531eb3 (patch) | |
tree | 10425fe4cbe9ceff8f567c5e1ebb0eea125afdd4 | |
parent | ec3483bd1831dfca0c7baec0f8aad9079d28907d (diff) |
Add latest changes from gitlab-org/gitlab@master
85 files changed, 957 insertions, 587 deletions
diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml index 4f8358977e3..170c5264372 100644 --- a/.rubocop_manual_todo.yml +++ b/.rubocop_manual_todo.yml @@ -28,55 +28,6 @@ Graphql/OldTypes: Exclude: - 'spec/**/*.rb' - 'ee/spec/**/*.rb' - - 'app/graphql/types/access_level_type.rb' - - 'app/graphql/types/admin/analytics/usage_trends/measurement_type.rb' - - 'app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb' - - 'app/graphql/types/alert_management/alert_status_counts_type.rb' - - 'app/graphql/types/alert_management/alert_type.rb' - - 'app/graphql/types/alert_management/integration_type.rb' - - 'app/graphql/types/award_emojis/award_emoji_type.rb' - - 'app/graphql/types/blob_viewer_type.rb' - - 'app/graphql/types/board_list_type.rb' - - 'app/graphql/types/board_type.rb' - - 'app/graphql/types/boards/board_issuable_input_base_type.rb' - - 'app/graphql/types/boards/board_issue_input_base_type.rb' - - 'app/graphql/types/boards/board_issue_input_type.rb' - - 'app/graphql/types/branch_type.rb' - - 'app/graphql/types/ci/application_setting_type.rb' - - 'app/graphql/types/ci/build_need_type.rb' - - 'app/graphql/types/ci/ci_cd_setting_type.rb' - - 'app/graphql/types/ci/config/config_type.rb' - - 'app/graphql/types/ci/config/group_type.rb' - - 'app/graphql/types/ci/config/job_type.rb' - - 'app/graphql/types/ci/config/need_type.rb' - - 'app/graphql/types/ci/config/stage_type.rb' - - 'app/graphql/types/ci/detailed_status_type.rb' - - 'app/graphql/types/ci/group_type.rb' - - 'app/graphql/types/ci/job_artifact_type.rb' - - 'app/graphql/types/ci/job_type.rb' - - 'app/graphql/types/ci/pipeline_type.rb' - - 'app/graphql/types/ci/recent_failures_type.rb' - - 'app/graphql/types/ci/runner_architecture_type.rb' - - 'app/graphql/types/ci/runner_platform_type.rb' - - 'app/graphql/types/ci/runner_setup_type.rb' - - 'app/graphql/types/ci/runner_type.rb' - - 'app/graphql/types/ci/stage_type.rb' - - 'app/graphql/types/ci/status_action_type.rb' - - 'app/graphql/types/ci/template_type.rb' - - 'app/graphql/types/ci/test_case_type.rb' - - 'app/graphql/types/ci/test_report_total_type.rb' - - 'app/graphql/types/ci/test_suite_summary_type.rb' - - 'app/graphql/types/ci/test_suite_type.rb' - - 'app/graphql/types/ci_configuration/sast/analyzers_entity_input_type.rb' - - 'app/graphql/types/ci_configuration/sast/analyzers_entity_type.rb' - - 'app/graphql/types/ci_configuration/sast/entity_input_type.rb' - - 'app/graphql/types/ci_configuration/sast/entity_type.rb' - - 'app/graphql/types/ci_configuration/sast/options_entity_type.rb' - - 'app/graphql/types/container_expiration_policy_type.rb' - - 'app/graphql/types/container_repository_tag_type.rb' - - 'app/graphql/types/container_repository_type.rb' - - 'app/graphql/types/countable_connection_type.rb' - - 'app/graphql/types/custom_emoji_type.rb' - 'ee/app/graphql/ee/mutations/ci/ci_cd_settings_update.rb' - 'ee/app/graphql/ee/resolvers/issues_resolver.rb' - 'ee/app/graphql/ee/resolvers/namespace_projects_resolver.rb' diff --git a/app/assets/javascripts/lib/dompurify.js b/app/assets/javascripts/lib/dompurify.js index 4357918672d..a026f76e51b 100644 --- a/app/assets/javascripts/lib/dompurify.js +++ b/app/assets/javascripts/lib/dompurify.js @@ -1,14 +1,14 @@ import { sanitize as dompurifySanitize, addHook } from 'dompurify'; import { getBaseURL, relativePathToAbsolute } from '~/lib/utils/url_utility'; -// Safely allow SVG <use> tags - const defaultConfig = { + // Safely allow SVG <use> tags ADD_TAGS: ['use'], + // Prevent possible XSS attacks with data-* attributes used by @rails/ujs + // See https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1421 + FORBID_ATTR: ['data-remote', 'data-url', 'data-type', 'data-method'], }; -const forbiddenDataAttrs = ['data-remote', 'data-url', 'data-type', 'data-method']; - // Only icons urls from `gon` are allowed const getAllowedIconUrls = (gon = window.gon) => [gon.sprite_file_icons, gon.sprite_icons].filter(Boolean); @@ -46,19 +46,10 @@ const sanitizeSvgIcon = (node) => { removeUnsafeHref(node, 'xlink:href'); }; -const sanitizeHTMLAttributes = (node) => { - forbiddenDataAttrs.forEach((attr) => { - if (node.hasAttribute(attr)) { - node.removeAttribute(attr); - } - }); -}; - addHook('afterSanitizeAttributes', (node) => { if (node.tagName.toLowerCase() === 'use') { sanitizeSvgIcon(node); } - sanitizeHTMLAttributes(node); }); export const sanitize = (val, config = defaultConfig) => dompurifySanitize(val, config); diff --git a/app/assets/javascripts/security_configuration/components/upgrade_banner.vue b/app/assets/javascripts/security_configuration/components/upgrade_banner.vue index ca0f9e5c85a..79e6b9d7a23 100644 --- a/app/assets/javascripts/security_configuration/components/upgrade_banner.vue +++ b/app/assets/javascripts/security_configuration/components/upgrade_banner.vue @@ -8,20 +8,18 @@ export default { }, inject: ['upgradePath'], i18n: { - title: s__('SecurityConfiguration|Secure your project with Ultimate'), + title: s__('SecurityConfiguration|Secure your project'), bodyStart: s__( - `SecurityConfiguration|GitLab Ultimate checks your application for security vulnerabilities - that may lead to unauthorized access, data leaks, and denial of service - attacks. Its features include:`, + `SecurityConfiguration|Immediately begin risk analysis and remediation with application security features. Start with SAST and Secret Detection, available to all plans. Upgrade to Ultimate to get all features, including:`, ), bodyListItems: [ - s__('SecurityConfiguration|Vulnerability details and statistics in the merge request.'), - s__('SecurityConfiguration|High-level vulnerability statistics across projects and groups.'), - s__('SecurityConfiguration|Runtime security metrics for application environments.'), + s__('SecurityConfiguration|Vulnerability details and statistics in the merge request'), + s__('SecurityConfiguration|High-level vulnerability statistics across projects and groups'), + s__('SecurityConfiguration|Runtime security metrics for application environments'), + s__( + 'SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance', + ), ], - bodyEnd: s__( - 'SecurityConfiguration|With the information provided, you can immediately begin risk analysis and remediation within GitLab.', - ), buttonText: s__('SecurityConfiguration|Upgrade or start a free trial'), }, }; @@ -32,14 +30,14 @@ export default { :title="$options.i18n.title" :button-text="$options.i18n.buttonText" :button-link="upgradePath" + variant="introduction" v-on="$listeners" > <p>{{ $options.i18n.bodyStart }}</p> - <ul> + <ul class="gl-pl-6"> <li v-for="bodyListItem in $options.i18n.bodyListItems" :key="bodyListItem"> {{ bodyListItem }} </li> </ul> - <p>{{ $options.i18n.bodyEnd }}</p> </gl-banner> </template> diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb index 49687a50ff6..778623a05c6 100644 --- a/app/controllers/projects/jobs_controller.rb +++ b/app/controllers/projects/jobs_controller.rb @@ -9,7 +9,7 @@ class Projects::JobsController < Projects::ApplicationController before_action :authorize_read_build_trace!, only: [:trace, :raw] before_action :authorize_read_build! before_action :authorize_update_build!, - except: [:index, :show, :status, :raw, :trace, :erase] + except: [:index, :show, :status, :raw, :trace, :erase, :cancel, :unschedule] before_action :authorize_erase_build!, only: [:erase] before_action :authorize_use_build_terminal!, only: [:terminal, :terminal_websocket_authorize] before_action :verify_api_request!, only: :terminal_websocket_authorize @@ -93,22 +93,28 @@ class Projects::JobsController < Projects::ApplicationController end def cancel - return respond_422 unless @build.cancelable? + service_response = Ci::BuildCancelService.new(@build, current_user).execute - @build.cancel - - if continue_params[:to] - redirect_to continue_params[:to] + if service_response.success? + destination = continue_params[:to].presence || builds_project_pipeline_path(@project, @build.pipeline.id) + redirect_to destination + elsif service_response.http_status == :forbidden + access_denied! else - redirect_to builds_project_pipeline_path(@project, @build.pipeline.id) + head service_response.http_status end end def unschedule - return respond_422 unless @build.scheduled? + service_response = Ci::BuildUnscheduleService.new(@build, current_user).execute - @build.unschedule! - redirect_to build_path(@build) + if service_response.success? + redirect_to build_path(@build) + elsif service_response.http_status == :forbidden + access_denied! + else + head service_response.http_status + end end def status diff --git a/app/graphql/types/access_level_type.rb b/app/graphql/types/access_level_type.rb index 21c3669979c..2d97f6b30e8 100644 --- a/app/graphql/types/access_level_type.rb +++ b/app/graphql/types/access_level_type.rb @@ -6,7 +6,7 @@ module Types graphql_name 'AccessLevel' description 'Represents the access level of a relationship between a User and object that it is related to' - field :integer_value, GraphQL::INT_TYPE, null: true, + field :integer_value, GraphQL::Types::Int, null: true, description: 'Integer representation of access level.', method: :to_i diff --git a/app/graphql/types/admin/analytics/usage_trends/measurement_type.rb b/app/graphql/types/admin/analytics/usage_trends/measurement_type.rb index c8ca702706f..c54c938402d 100644 --- a/app/graphql/types/admin/analytics/usage_trends/measurement_type.rb +++ b/app/graphql/types/admin/analytics/usage_trends/measurement_type.rb @@ -14,7 +14,7 @@ module Types field :recorded_at, Types::TimeType, null: true, description: 'The time the measurement was recorded.' - field :count, GraphQL::INT_TYPE, null: false, + field :count, GraphQL::Types::Int, null: false, description: 'Object count.' field :identifier, Types::Admin::Analytics::UsageTrends::MeasurementIdentifierEnum, null: false, diff --git a/app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb b/app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb index 996300edad3..cc6e3db007b 100644 --- a/app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb +++ b/app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb @@ -10,17 +10,17 @@ module Types description 'The response from the AdminSidekiqQueuesDeleteJobs mutation' field :completed, - GraphQL::BOOLEAN_TYPE, + GraphQL::Types::Boolean, null: true, description: 'Whether or not the entire queue was processed in time; if not, retrying the same request is safe.' field :deleted_jobs, - GraphQL::INT_TYPE, + GraphQL::Types::Int, null: true, description: 'The number of matching jobs deleted.' field :queue_size, - GraphQL::INT_TYPE, + GraphQL::Types::Int, null: true, description: 'The queue size after processing.' end diff --git a/app/graphql/types/alert_management/alert_status_counts_type.rb b/app/graphql/types/alert_management/alert_status_counts_type.rb index 14a81735fa5..c4aedb09997 100644 --- a/app/graphql/types/alert_management/alert_status_counts_type.rb +++ b/app/graphql/types/alert_management/alert_status_counts_type.rb @@ -11,18 +11,18 @@ module Types ::AlertManagement::Alert.status_names.each do |status| field status, - GraphQL::INT_TYPE, + GraphQL::Types::Int, null: true, description: "Number of alerts with status #{status.to_s.upcase} for the project" end field :open, - GraphQL::INT_TYPE, + GraphQL::Types::Int, null: true, description: 'Number of alerts with status TRIGGERED or ACKNOWLEDGED for the project.' field :all, - GraphQL::INT_TYPE, + GraphQL::Types::Int, null: true, description: 'Total number of alerts for the project.' end diff --git a/app/graphql/types/alert_management/alert_type.rb b/app/graphql/types/alert_management/alert_type.rb index 0ff0775ca86..b8fefaee470 100644 --- a/app/graphql/types/alert_management/alert_type.rb +++ b/app/graphql/types/alert_management/alert_type.rb @@ -13,12 +13,12 @@ module Types authorize :read_alert_management_alert field :iid, - GraphQL::ID_TYPE, + GraphQL::Types::ID, null: false, description: 'Internal ID of the alert.' field :issue_iid, - GraphQL::ID_TYPE, + GraphQL::Types::ID, null: true, deprecated: { reason: 'Use issue field', milestone: '13.10' }, description: 'Internal ID of the GitLab issue attached to the alert.' @@ -29,12 +29,12 @@ module Types description: 'Issue attached to the alert.' field :title, - GraphQL::STRING_TYPE, + GraphQL::Types::String, null: true, description: 'Title of the alert.' field :description, - GraphQL::STRING_TYPE, + GraphQL::Types::String, null: true, description: 'Description of the alert.' @@ -50,17 +50,17 @@ module Types method: :status_name field :service, - GraphQL::STRING_TYPE, + GraphQL::Types::String, null: true, description: 'Service the alert came from.' field :monitoring_tool, - GraphQL::STRING_TYPE, + GraphQL::Types::String, null: true, description: 'Monitoring tool the alert came from.' field :hosts, - [GraphQL::STRING_TYPE], + [GraphQL::Types::String], null: true, description: 'List of hosts the alert came from.' @@ -80,7 +80,7 @@ module Types description: 'Environment for the alert.' field :event_count, - GraphQL::INT_TYPE, + GraphQL::Types::Int, null: true, description: 'Number of events of this alert.', method: :events @@ -106,12 +106,12 @@ module Types description: 'Assignees of the alert.' field :metrics_dashboard_url, - GraphQL::STRING_TYPE, + GraphQL::Types::String, null: true, description: 'URL for metrics embed for the alert.' field :runbook, - GraphQL::STRING_TYPE, + GraphQL::Types::String, null: true, description: 'Runbook for the alert as defined in alert details.' @@ -122,7 +122,7 @@ module Types resolver: Resolvers::TodoResolver field :details_url, - GraphQL::STRING_TYPE, + GraphQL::Types::String, null: false, description: 'The URL of the alert detail page.' diff --git a/app/graphql/types/alert_management/integration_type.rb b/app/graphql/types/alert_management/integration_type.rb index 6cbc17cdbfb..ca7ec99a480 100644 --- a/app/graphql/types/alert_management/integration_type.rb +++ b/app/graphql/types/alert_management/integration_type.rb @@ -7,7 +7,7 @@ module Types graphql_name 'AlertManagementIntegration' field :id, - GraphQL::ID_TYPE, + GraphQL::Types::ID, null: false, description: 'ID of the integration.' @@ -17,27 +17,27 @@ module Types description: 'Type of integration.' field :name, - GraphQL::STRING_TYPE, + GraphQL::Types::String, null: true, description: 'Name of the integration.' field :active, - GraphQL::BOOLEAN_TYPE, + GraphQL::Types::Boolean, null: true, description: 'Whether the endpoint is currently accepting alerts.' field :token, - GraphQL::STRING_TYPE, + GraphQL::Types::String, null: true, description: 'Token used to authenticate alert notification requests.' field :url, - GraphQL::STRING_TYPE, + GraphQL::Types::String, null: true, description: 'Endpoint which accepts alert notifications.' field :api_url, - GraphQL::STRING_TYPE, + GraphQL::Types::String, null: true, description: 'URL at which Prometheus metrics can be queried to populate the metrics dashboard.' diff --git a/app/graphql/types/award_emojis/award_emoji_type.rb b/app/graphql/types/award_emojis/award_emoji_type.rb index 9409304e28f..1f6f0badcac 100644 --- a/app/graphql/types/award_emojis/award_emoji_type.rb +++ b/app/graphql/types/award_emojis/award_emoji_type.rb @@ -11,27 +11,27 @@ module Types present_using AwardEmojiPresenter field :name, - GraphQL::STRING_TYPE, + GraphQL::Types::String, null: false, description: 'The emoji name.' field :description, - GraphQL::STRING_TYPE, + GraphQL::Types::String, null: false, description: 'The emoji description.' field :unicode, - GraphQL::STRING_TYPE, + GraphQL::Types::String, null: false, description: 'The emoji in Unicode.' field :emoji, - GraphQL::STRING_TYPE, + GraphQL::Types::String, null: false, description: 'The emoji as an icon.' field :unicode_version, - GraphQL::STRING_TYPE, + GraphQL::Types::String, null: false, description: 'The Unicode version for this emoji.' diff --git a/app/graphql/types/blob_viewer_type.rb b/app/graphql/types/blob_viewer_type.rb index 8d863c32bc7..8c565373cfd 100644 --- a/app/graphql/types/blob_viewer_type.rb +++ b/app/graphql/types/blob_viewer_type.rb @@ -9,30 +9,30 @@ module Types description: 'Type of blob viewer.', null: false - field :load_async, GraphQL::BOOLEAN_TYPE, + field :load_async, GraphQL::Types::Boolean, description: 'Shows whether the blob content is loaded asynchronously.', null: false - field :collapsed, GraphQL::BOOLEAN_TYPE, + field :collapsed, GraphQL::Types::Boolean, description: 'Shows whether the blob should be displayed collapsed.', method: :collapsed?, null: false - field :too_large, GraphQL::BOOLEAN_TYPE, + field :too_large, GraphQL::Types::Boolean, description: 'Shows whether the blob is too large to be displayed.', method: :too_large?, null: false - field :render_error, GraphQL::STRING_TYPE, + field :render_error, GraphQL::Types::String, description: 'Error rendering the blob content.', null: true - field :file_type, GraphQL::STRING_TYPE, + field :file_type, GraphQL::Types::String, description: 'Content file type.', method: :partial_name, null: false - field :loading_partial_name, GraphQL::STRING_TYPE, + field :loading_partial_name, GraphQL::Types::String, description: 'Loading partial name.', null: false diff --git a/app/graphql/types/board_list_type.rb b/app/graphql/types/board_list_type.rb index dc10716dcb0..762e03973d9 100644 --- a/app/graphql/types/board_list_type.rb +++ b/app/graphql/types/board_list_type.rb @@ -10,19 +10,19 @@ module Types alias_method :list, :object - field :id, GraphQL::ID_TYPE, null: false, + field :id, GraphQL::Types::ID, null: false, description: 'ID (global ID) of the list.' - field :title, GraphQL::STRING_TYPE, null: false, + field :title, GraphQL::Types::String, null: false, description: 'Title of the list.' - field :list_type, GraphQL::STRING_TYPE, null: false, + field :list_type, GraphQL::Types::String, null: false, description: 'Type of the list.' - field :position, GraphQL::INT_TYPE, null: true, + field :position, GraphQL::Types::Int, null: true, description: 'Position of list within the board.' field :label, Types::LabelType, null: true, description: 'Label of the list.' - field :collapsed, GraphQL::BOOLEAN_TYPE, null: true, + field :collapsed, GraphQL::Types::Boolean, null: true, description: 'Indicates if the list is collapsed for this user.' - field :issues_count, GraphQL::INT_TYPE, null: true, + field :issues_count, GraphQL::Types::Int, null: true, description: 'Count of issues in the list.' field :issues, ::Types::IssueType.connection_type, null: true, diff --git a/app/graphql/types/board_type.rb b/app/graphql/types/board_type.rb index 292809b0d64..4ec9a8a9c63 100644 --- a/app/graphql/types/board_type.rb +++ b/app/graphql/types/board_type.rb @@ -9,15 +9,15 @@ module Types present_using BoardPresenter - field :id, type: GraphQL::ID_TYPE, null: false, + field :id, type: GraphQL::Types::ID, null: false, description: 'ID (global ID) of the board.' - field :name, type: GraphQL::STRING_TYPE, null: true, + field :name, type: GraphQL::Types::String, null: true, description: 'Name of the board.' - field :hide_backlog_list, type: GraphQL::BOOLEAN_TYPE, null: true, + field :hide_backlog_list, type: GraphQL::Types::Boolean, null: true, description: 'Whether or not backlog list is hidden.' - field :hide_closed_list, type: GraphQL::BOOLEAN_TYPE, null: true, + field :hide_closed_list, type: GraphQL::Types::Boolean, null: true, description: 'Whether or not closed list is hidden.' field :created_at, Types::TimeType, null: false, @@ -33,10 +33,10 @@ module Types resolver: Resolvers::BoardListsResolver, extras: [:lookahead] - field :web_path, GraphQL::STRING_TYPE, null: false, + field :web_path, GraphQL::Types::String, null: false, description: 'Web path of the board.' - field :web_url, GraphQL::STRING_TYPE, null: false, + field :web_url, GraphQL::Types::String, null: false, description: 'Web URL of the board.' end end diff --git a/app/graphql/types/boards/board_issuable_input_base_type.rb b/app/graphql/types/boards/board_issuable_input_base_type.rb index 2cd057347d6..326f73846d0 100644 --- a/app/graphql/types/boards/board_issuable_input_base_type.rb +++ b/app/graphql/types/boards/board_issuable_input_base_type.rb @@ -4,15 +4,15 @@ module Types module Boards # Common arguments that we can be used to filter boards epics and issues class BoardIssuableInputBaseType < BaseInputObject - argument :label_name, [GraphQL::STRING_TYPE, null: true], + argument :label_name, [GraphQL::Types::String, null: true], required: false, description: 'Filter by label name.' - argument :author_username, GraphQL::STRING_TYPE, + argument :author_username, GraphQL::Types::String, required: false, description: 'Filter by author username.' - argument :my_reaction_emoji, GraphQL::STRING_TYPE, + argument :my_reaction_emoji, GraphQL::Types::String, required: false, description: 'Filter by reaction emoji applied by the current user.' end diff --git a/app/graphql/types/boards/board_issue_input_base_type.rb b/app/graphql/types/boards/board_issue_input_base_type.rb index 30f4efcd403..983cd072ad3 100644 --- a/app/graphql/types/boards/board_issue_input_base_type.rb +++ b/app/graphql/types/boards/board_issue_input_base_type.rb @@ -4,19 +4,19 @@ module Types module Boards # rubocop: disable Graphql/AuthorizeTypes class BoardIssueInputBaseType < BoardIssuableInputBaseType - argument :iids, [GraphQL::STRING_TYPE], + argument :iids, [GraphQL::Types::String], required: false, description: 'List of IIDs of issues. For example `["1", "2"]`.' - argument :milestone_title, GraphQL::STRING_TYPE, + argument :milestone_title, GraphQL::Types::String, required: false, description: 'Filter by milestone title.' - argument :assignee_username, [GraphQL::STRING_TYPE, null: true], + argument :assignee_username, [GraphQL::Types::String, null: true], required: false, description: 'Filter by assignee username.' - argument :release_tag, GraphQL::STRING_TYPE, + argument :release_tag, GraphQL::Types::String, required: false, description: 'Filter by release tag.' end diff --git a/app/graphql/types/boards/board_issue_input_type.rb b/app/graphql/types/boards/board_issue_input_type.rb index 7580b0378fe..b4dbe87e32d 100644 --- a/app/graphql/types/boards/board_issue_input_type.rb +++ b/app/graphql/types/boards/board_issue_input_type.rb @@ -10,7 +10,7 @@ module Types prepare: ->(negated_args, ctx) { negated_args.to_h }, description: 'List of negated arguments.' - argument :search, GraphQL::STRING_TYPE, + argument :search, GraphQL::Types::String, required: false, description: 'Search query for issue title or description.' diff --git a/app/graphql/types/branch_type.rb b/app/graphql/types/branch_type.rb index b788ba79769..a861bcc4bb4 100644 --- a/app/graphql/types/branch_type.rb +++ b/app/graphql/types/branch_type.rb @@ -6,7 +6,7 @@ module Types graphql_name 'Branch' field :name, - GraphQL::STRING_TYPE, + GraphQL::Types::String, null: false, description: 'Name of the branch.' diff --git a/app/graphql/types/ci/analytics_type.rb b/app/graphql/types/ci/analytics_type.rb index ba987b133bd..f52b9eae229 100644 --- a/app/graphql/types/ci/analytics_type.rb +++ b/app/graphql/types/ci/analytics_type.rb @@ -6,27 +6,27 @@ module Types class AnalyticsType < BaseObject graphql_name 'PipelineAnalytics' - field :week_pipelines_totals, [GraphQL::INT_TYPE], null: true, + field :week_pipelines_totals, [GraphQL::Types::Int], null: true, description: 'Total weekly pipeline count.' - field :week_pipelines_successful, [GraphQL::INT_TYPE], null: true, + field :week_pipelines_successful, [GraphQL::Types::Int], null: true, description: 'Total weekly successful pipeline count.' - field :week_pipelines_labels, [GraphQL::STRING_TYPE], null: true, + field :week_pipelines_labels, [GraphQL::Types::String], null: true, description: 'Labels for the weekly pipeline count.' - field :month_pipelines_totals, [GraphQL::INT_TYPE], null: true, + field :month_pipelines_totals, [GraphQL::Types::Int], null: true, description: 'Total monthly pipeline count.' - field :month_pipelines_successful, [GraphQL::INT_TYPE], null: true, + field :month_pipelines_successful, [GraphQL::Types::Int], null: true, description: 'Total monthly successful pipeline count.' - field :month_pipelines_labels, [GraphQL::STRING_TYPE], null: true, + field :month_pipelines_labels, [GraphQL::Types::String], null: true, description: 'Labels for the monthly pipeline count.' - field :year_pipelines_totals, [GraphQL::INT_TYPE], null: true, + field :year_pipelines_totals, [GraphQL::Types::Int], null: true, description: 'Total yearly pipeline count.' - field :year_pipelines_successful, [GraphQL::INT_TYPE], null: true, + field :year_pipelines_successful, [GraphQL::Types::Int], null: true, description: 'Total yearly successful pipeline count.' - field :year_pipelines_labels, [GraphQL::STRING_TYPE], null: true, + field :year_pipelines_labels, [GraphQL::Types::String], null: true, description: 'Labels for the yearly pipeline count.' - field :pipeline_times_values, [GraphQL::INT_TYPE], null: true, + field :pipeline_times_values, [GraphQL::Types::Int], null: true, description: 'Pipeline times.' - field :pipeline_times_labels, [GraphQL::STRING_TYPE], null: true, + field :pipeline_times_labels, [GraphQL::Types::String], null: true, description: 'Pipeline times labels.' end end diff --git a/app/graphql/types/ci/application_setting_type.rb b/app/graphql/types/ci/application_setting_type.rb index 8616280057c..2322778d159 100644 --- a/app/graphql/types/ci/application_setting_type.rb +++ b/app/graphql/types/ci/application_setting_type.rb @@ -7,7 +7,7 @@ module Types authorize :read_application_setting - field :keep_latest_artifact, GraphQL::BOOLEAN_TYPE, null: true, + field :keep_latest_artifact, GraphQL::Types::Boolean, null: true, description: 'Whether to keep the latest jobs artifacts.' end end diff --git a/app/graphql/types/ci/build_need_type.rb b/app/graphql/types/ci/build_need_type.rb index 19ff758ad1d..7bd12c99a08 100644 --- a/app/graphql/types/ci/build_need_type.rb +++ b/app/graphql/types/ci/build_need_type.rb @@ -7,9 +7,9 @@ module Types class BuildNeedType < BaseObject graphql_name 'CiBuildNeed' - field :id, GraphQL::ID_TYPE, null: false, + field :id, GraphQL::Types::ID, null: false, description: 'ID of the job we need to complete.' - field :name, GraphQL::STRING_TYPE, null: true, + field :name, GraphQL::Types::String, null: true, description: 'Name of the job we need to complete.' end end diff --git a/app/graphql/types/ci/ci_cd_setting_type.rb b/app/graphql/types/ci/ci_cd_setting_type.rb index f90c75454ba..790deab8f68 100644 --- a/app/graphql/types/ci/ci_cd_setting_type.rb +++ b/app/graphql/types/ci/ci_cd_setting_type.rb @@ -7,16 +7,16 @@ module Types authorize :admin_project - field :merge_pipelines_enabled, GraphQL::BOOLEAN_TYPE, null: true, + field :merge_pipelines_enabled, GraphQL::Types::Boolean, null: true, description: 'Whether merge pipelines are enabled.', method: :merge_pipelines_enabled? - field :merge_trains_enabled, GraphQL::BOOLEAN_TYPE, null: true, + field :merge_trains_enabled, GraphQL::Types::Boolean, null: true, description: 'Whether merge trains are enabled.', method: :merge_trains_enabled? - field :keep_latest_artifact, GraphQL::BOOLEAN_TYPE, null: true, + field :keep_latest_artifact, GraphQL::Types::Boolean, null: true, description: 'Whether to keep the latest builds artifacts.', method: :keep_latest_artifacts_available? - field :job_token_scope_enabled, GraphQL::BOOLEAN_TYPE, null: true, + field :job_token_scope_enabled, GraphQL::Types::Boolean, null: true, description: 'Indicates CI job tokens generated in this project have restricted access to resources.', method: :job_token_scope_enabled? field :project, Types::ProjectType, null: true, diff --git a/app/graphql/types/ci/config/config_type.rb b/app/graphql/types/ci/config/config_type.rb index 88caf21c376..6ac21968bd4 100644 --- a/app/graphql/types/ci/config/config_type.rb +++ b/app/graphql/types/ci/config/config_type.rb @@ -7,9 +7,9 @@ module Types class ConfigType < BaseObject graphql_name 'CiConfig' - field :errors, [GraphQL::STRING_TYPE], null: true, + field :errors, [GraphQL::Types::String], null: true, description: 'Linting errors.' - field :merged_yaml, GraphQL::STRING_TYPE, null: true, + field :merged_yaml, GraphQL::Types::String, null: true, description: 'Merged CI configuration YAML.' field :stages, Types::Ci::Config::StageType.connection_type, null: true, description: 'Stages of the pipeline.' diff --git a/app/graphql/types/ci/config/group_type.rb b/app/graphql/types/ci/config/group_type.rb index 11be701e73f..e5cb0d4e72f 100644 --- a/app/graphql/types/ci/config/group_type.rb +++ b/app/graphql/types/ci/config/group_type.rb @@ -7,11 +7,11 @@ module Types class GroupType < BaseObject graphql_name 'CiConfigGroup' - field :name, GraphQL::STRING_TYPE, null: true, + field :name, GraphQL::Types::String, null: true, description: 'Name of the job group.' field :jobs, Types::Ci::Config::JobType.connection_type, null: true, description: 'Jobs in group.' - field :size, GraphQL::INT_TYPE, null: true, + field :size, GraphQL::Types::Int, null: true, description: 'Size of the job group.' end end diff --git a/app/graphql/types/ci/config/job_restriction_type.rb b/app/graphql/types/ci/config/job_restriction_type.rb index 294e3c94571..891ba18dacc 100644 --- a/app/graphql/types/ci/config/job_restriction_type.rb +++ b/app/graphql/types/ci/config/job_restriction_type.rb @@ -7,7 +7,7 @@ module Types class JobRestrictionType < BaseObject graphql_name 'CiConfigJobRestriction' - field :refs, [GraphQL::STRING_TYPE], null: true, + field :refs, [GraphQL::Types::String], null: true, description: 'The Git refs the job restriction applies to.' end end diff --git a/app/graphql/types/ci/config/job_type.rb b/app/graphql/types/ci/config/job_type.rb index 65fdc4c2615..4cf6780ef60 100644 --- a/app/graphql/types/ci/config/job_type.rb +++ b/app/graphql/types/ci/config/job_type.rb @@ -7,32 +7,32 @@ module Types class JobType < BaseObject graphql_name 'CiConfigJob' - field :name, GraphQL::STRING_TYPE, null: true, + field :name, GraphQL::Types::String, null: true, description: 'Name of the job.' - field :group_name, GraphQL::STRING_TYPE, null: true, + field :group_name, GraphQL::Types::String, null: true, description: 'Name of the job group.' - field :stage, GraphQL::STRING_TYPE, null: true, + field :stage, GraphQL::Types::String, null: true, description: 'Name of the job stage.' field :needs, Types::Ci::Config::NeedType.connection_type, null: true, description: 'Builds that must complete before the jobs run.' - field :allow_failure, GraphQL::BOOLEAN_TYPE, null: true, + field :allow_failure, GraphQL::Types::Boolean, null: true, description: 'Allow job to fail.' - field :before_script, [GraphQL::STRING_TYPE], null: true, + field :before_script, [GraphQL::Types::String], null: true, description: 'Override a set of commands that are executed before the job.' - field :script, [GraphQL::STRING_TYPE], null: true, + field :script, [GraphQL::Types::String], null: true, description: 'Shell script that is executed by a runner.' - field :after_script, [GraphQL::STRING_TYPE], null: true, + field :after_script, [GraphQL::Types::String], null: true, description: 'Override a set of commands that are executed after the job.' - field :when, GraphQL::STRING_TYPE, null: true, + field :when, GraphQL::Types::String, null: true, description: 'When to run the job.', resolver_method: :restrict_when_to_run_jobs - field :environment, GraphQL::STRING_TYPE, null: true, + field :environment, GraphQL::Types::String, null: true, description: 'Name of an environment to which the job deploys.' field :except, Types::Ci::Config::JobRestrictionType, null: true, description: 'Limit when jobs are not created.' field :only, Types::Ci::Config::JobRestrictionType, null: true, description: 'Jobs are created when these conditions do not apply.' - field :tags, [GraphQL::STRING_TYPE], null: true, + field :tags, [GraphQL::Types::String], null: true, description: 'List of tags that are used to select a runner.' def restrict_when_to_run_jobs diff --git a/app/graphql/types/ci/config/need_type.rb b/app/graphql/types/ci/config/need_type.rb index 01f73100409..6e9aea8eb64 100644 --- a/app/graphql/types/ci/config/need_type.rb +++ b/app/graphql/types/ci/config/need_type.rb @@ -7,7 +7,7 @@ module Types class NeedType < BaseObject graphql_name 'CiConfigNeed' - field :name, GraphQL::STRING_TYPE, null: true, + field :name, GraphQL::Types::String, null: true, description: 'Name of the need.' end end diff --git a/app/graphql/types/ci/config/stage_type.rb b/app/graphql/types/ci/config/stage_type.rb index 060efb7d45c..7e2aa9470f2 100644 --- a/app/graphql/types/ci/config/stage_type.rb +++ b/app/graphql/types/ci/config/stage_type.rb @@ -7,7 +7,7 @@ module Types class StageType < BaseObject graphql_name 'CiConfigStage' - field :name, GraphQL::STRING_TYPE, null: true, + field :name, GraphQL::Types::String, null: true, description: 'Name of the stage.' field :groups, Types::Ci::Config::GroupType.connection_type, null: true, description: 'Groups of jobs for the stage.' diff --git a/app/graphql/types/ci/detailed_status_type.rb b/app/graphql/types/ci/detailed_status_type.rb index 6310a62a103..4433e921971 100644 --- a/app/graphql/types/ci/detailed_status_type.rb +++ b/app/graphql/types/ci/detailed_status_type.rb @@ -6,26 +6,26 @@ module Types class DetailedStatusType < BaseObject graphql_name 'DetailedStatus' - field :id, GraphQL::STRING_TYPE, null: false, + field :id, GraphQL::Types::String, null: false, description: 'ID for a detailed status.', extras: [:parent] - field :group, GraphQL::STRING_TYPE, null: true, + field :group, GraphQL::Types::String, null: true, description: 'Group of the status.' - field :icon, GraphQL::STRING_TYPE, null: true, + field :icon, GraphQL::Types::String, null: true, description: 'Icon of the status.' - field :favicon, GraphQL::STRING_TYPE, null: true, + field :favicon, GraphQL::Types::String, null: true, description: 'Favicon of the status.' - field :details_path, GraphQL::STRING_TYPE, null: true, + field :details_path, GraphQL::Types::String, null: true, description: 'Path of the details for the status.' - field :has_details, GraphQL::BOOLEAN_TYPE, null: true, + field :has_details, GraphQL::Types::Boolean, null: true, description: 'Indicates if the status has further details.', method: :has_details? - field :label, GraphQL::STRING_TYPE, null: true, + field :label, GraphQL::Types::String, null: true, calls_gitaly: true, description: 'Label of the status.' - field :text, GraphQL::STRING_TYPE, null: true, + field :text, GraphQL::Types::String, null: true, description: 'Text of the status.' - field :tooltip, GraphQL::STRING_TYPE, null: true, + field :tooltip, GraphQL::Types::String, null: true, description: 'Tooltip associated with the status.', method: :status_tooltip field :action, Types::Ci::StatusActionType, null: true, diff --git a/app/graphql/types/ci/group_type.rb b/app/graphql/types/ci/group_type.rb index 3da183cb842..3ae23ba9bd4 100644 --- a/app/graphql/types/ci/group_type.rb +++ b/app/graphql/types/ci/group_type.rb @@ -6,11 +6,11 @@ module Types class GroupType < BaseObject graphql_name 'CiGroup' - field :id, GraphQL::STRING_TYPE, null: false, + field :id, GraphQL::Types::String, null: false, description: 'ID for a group.' - field :name, GraphQL::STRING_TYPE, null: true, + field :name, GraphQL::Types::String, null: true, description: 'Name of the job group.' - field :size, GraphQL::INT_TYPE, null: true, + field :size, GraphQL::Types::Int, null: true, description: 'Size of the group.' field :jobs, Ci::JobType.connection_type, null: true, description: 'Jobs in group.' diff --git a/app/graphql/types/ci/job_artifact_type.rb b/app/graphql/types/ci/job_artifact_type.rb index 7dc93041b53..f80681bcf36 100644 --- a/app/graphql/types/ci/job_artifact_type.rb +++ b/app/graphql/types/ci/job_artifact_type.rb @@ -6,7 +6,7 @@ module Types class JobArtifactType < BaseObject graphql_name 'CiJobArtifact' - field :download_path, GraphQL::STRING_TYPE, null: true, + field :download_path, GraphQL::Types::String, null: true, description: "URL for downloading the artifact's file." field :file_type, ::Types::Ci::JobArtifactFileTypeEnum, null: true, diff --git a/app/graphql/types/ci/job_type.rb b/app/graphql/types/ci/job_type.rb index 360ea3ba7a9..4a3518e1865 100644 --- a/app/graphql/types/ci/job_type.rb +++ b/app/graphql/types/ci/job_type.rb @@ -14,7 +14,7 @@ module Types description: 'ID of the job.' field :pipeline, Types::Ci::PipelineType, null: true, description: 'Pipeline the job belongs to.' - field :name, GraphQL::STRING_TYPE, null: true, + field :name, GraphQL::Types::String, null: true, description: 'Name of the job.' field :needs, BuildNeedType.connection_type, null: true, description: 'References to builds that must complete before the jobs run.' @@ -24,11 +24,11 @@ module Types description: "Status of the job." field :stage, Types::Ci::StageType, null: true, description: 'Stage of the job.' - field :allow_failure, ::GraphQL::BOOLEAN_TYPE, null: false, + field :allow_failure, ::GraphQL::Types::Boolean, null: false, description: 'Whether the job is allowed to fail.' - field :duration, GraphQL::INT_TYPE, null: true, + field :duration, GraphQL::Types::Int, null: true, description: 'Duration of the job in seconds.' - field :tags, [GraphQL::STRING_TYPE], null: true, + field :tags, [GraphQL::Types::String], null: true, description: 'Tags for the current job.' # Life-cycle timestamps: @@ -53,33 +53,33 @@ module Types description: 'Detailed status of the job.' field :artifacts, Types::Ci::JobArtifactType.connection_type, null: true, description: 'Artifacts generated by the job.' - field :short_sha, type: GraphQL::STRING_TYPE, null: false, + field :short_sha, type: GraphQL::Types::String, null: false, description: 'Short SHA1 ID of the commit.' - field :scheduling_type, GraphQL::STRING_TYPE, null: true, + field :scheduling_type, GraphQL::Types::String, null: true, description: 'Type of job scheduling. Value is `dag` if the job uses the `needs` keyword, and `stage` otherwise.' - field :commit_path, GraphQL::STRING_TYPE, null: true, + field :commit_path, GraphQL::Types::String, null: true, description: 'Path to the commit that triggered the job.' - field :ref_name, GraphQL::STRING_TYPE, null: true, + field :ref_name, GraphQL::Types::String, null: true, description: 'Ref name of the job.' - field :ref_path, GraphQL::STRING_TYPE, null: true, + field :ref_path, GraphQL::Types::String, null: true, description: 'Path to the ref.' - field :playable, GraphQL::BOOLEAN_TYPE, null: false, method: :playable?, + field :playable, GraphQL::Types::Boolean, null: false, method: :playable?, description: 'Indicates the job can be played.' - field :retryable, GraphQL::BOOLEAN_TYPE, null: false, method: :retryable?, + field :retryable, GraphQL::Types::Boolean, null: false, method: :retryable?, description: 'Indicates the job can be retried.' - field :cancelable, GraphQL::BOOLEAN_TYPE, null: false, method: :cancelable?, + field :cancelable, GraphQL::Types::Boolean, null: false, method: :cancelable?, description: 'Indicates the job can be canceled.' - field :active, GraphQL::BOOLEAN_TYPE, null: false, method: :active?, + field :active, GraphQL::Types::Boolean, null: false, method: :active?, description: 'Indicates the job is active.' - field :stuck, GraphQL::BOOLEAN_TYPE, null: false, method: :stuck?, + field :stuck, GraphQL::Types::Boolean, null: false, method: :stuck?, description: 'Indicates the job is stuck.' field :coverage, GraphQL::FLOAT_TYPE, null: true, description: 'Coverage level of the job.' - field :created_by_tag, GraphQL::BOOLEAN_TYPE, null: false, + field :created_by_tag, GraphQL::Types::Boolean, null: false, description: 'Whether the job was created by a tag.' - field :manual_job, GraphQL::BOOLEAN_TYPE, null: true, + field :manual_job, GraphQL::Types::Boolean, null: true, description: 'Whether the job has a manual action.' - field :triggered, GraphQL::BOOLEAN_TYPE, null: true, + field :triggered, GraphQL::Types::Boolean, null: true, description: 'Whether the job was triggered.' def pipeline diff --git a/app/graphql/types/ci/pipeline_type.rb b/app/graphql/types/ci/pipeline_type.rb index f4a6c18f73e..0375257eb7b 100644 --- a/app/graphql/types/ci/pipeline_type.rb +++ b/app/graphql/types/ci/pipeline_type.rb @@ -12,25 +12,25 @@ module Types expose_permissions Types::PermissionTypes::Ci::Pipeline - field :id, GraphQL::ID_TYPE, null: false, + field :id, GraphQL::Types::ID, null: false, description: 'ID of the pipeline.' - field :iid, GraphQL::STRING_TYPE, null: false, + field :iid, GraphQL::Types::String, null: false, description: 'Internal ID of the pipeline.' - field :sha, GraphQL::STRING_TYPE, null: false, + field :sha, GraphQL::Types::String, null: false, description: "SHA of the pipeline's commit." - field :before_sha, GraphQL::STRING_TYPE, null: true, + field :before_sha, GraphQL::Types::String, null: true, description: 'Base SHA of the source branch.' - field :complete, GraphQL::BOOLEAN_TYPE, null: false, method: :complete?, + field :complete, GraphQL::Types::Boolean, null: false, method: :complete?, description: 'Indicates if a pipeline is complete.' field :status, PipelineStatusEnum, null: false, description: "Status of the pipeline (#{::Ci::Pipeline.all_state_names.compact.join(', ').upcase})" - field :warnings, GraphQL::BOOLEAN_TYPE, null: false, method: :has_warnings?, + field :warnings, GraphQL::Types::Boolean, null: false, method: :has_warnings?, description: "Indicates if a pipeline has warnings." field :detailed_status, Types::Ci::DetailedStatusType, null: false, @@ -39,7 +39,7 @@ module Types field :config_source, PipelineConfigSourceEnum, null: true, description: "Configuration source of the pipeline (#{::Enums::Ci::Pipeline.config_sources.keys.join(', ').upcase})" - field :duration, GraphQL::INT_TYPE, null: true, + field :duration, GraphQL::Types::Int, null: true, description: 'Duration of the pipeline in seconds.' field :queued_duration, Types::DurationType, null: true, @@ -76,12 +76,12 @@ module Types null: true, description: 'Pipeline user.' - field :retryable, GraphQL::BOOLEAN_TYPE, + field :retryable, GraphQL::Types::Boolean, description: 'Specifies if a pipeline can be retried.', method: :retryable?, null: false - field :cancelable, GraphQL::BOOLEAN_TYPE, + field :cancelable, GraphQL::Types::Boolean, description: 'Specifies if a pipeline can be canceled.', method: :cancelable?, null: false @@ -103,7 +103,7 @@ module Types required: false, description: 'ID of the job.' argument :name, - type: ::GraphQL::STRING_TYPE, + type: ::GraphQL::Types::String, required: false, description: 'Name of the job.' end @@ -122,19 +122,19 @@ module Types description: 'Pipeline that triggered the pipeline.', method: :triggered_by_pipeline - field :path, GraphQL::STRING_TYPE, null: true, + field :path, GraphQL::Types::String, null: true, description: "Relative path to the pipeline's page." - field :commit_path, GraphQL::STRING_TYPE, null: true, + field :commit_path, GraphQL::Types::String, null: true, description: 'Path to the commit that triggered the pipeline.' field :project, Types::ProjectType, null: true, description: 'Project the pipeline belongs to.' - field :active, GraphQL::BOOLEAN_TYPE, null: false, method: :active?, + field :active, GraphQL::Types::Boolean, null: false, method: :active?, description: 'Indicates if the pipeline is active.' - field :uses_needs, GraphQL::BOOLEAN_TYPE, null: true, + field :uses_needs, GraphQL::Types::Boolean, null: true, method: :uses_needs?, description: 'Indicates if the pipeline has jobs with `needs` dependencies.' @@ -150,7 +150,7 @@ module Types description: 'A specific test suite in a pipeline test report.', resolver: Resolvers::Ci::TestSuiteResolver - field :ref, GraphQL::STRING_TYPE, null: true, + field :ref, GraphQL::Types::String, null: true, description: 'Reference to the branch from which the pipeline was triggered.' def detailed_status diff --git a/app/graphql/types/ci/recent_failures_type.rb b/app/graphql/types/ci/recent_failures_type.rb index eeff7222762..f56b0939086 100644 --- a/app/graphql/types/ci/recent_failures_type.rb +++ b/app/graphql/types/ci/recent_failures_type.rb @@ -9,10 +9,10 @@ module Types connection_type_class(Types::CountableConnectionType) - field :count, GraphQL::INT_TYPE, null: true, + field :count, GraphQL::Types::Int, null: true, description: 'Number of times the test case has failed in the past 14 days.' - field :base_branch, GraphQL::STRING_TYPE, null: true, + field :base_branch, GraphQL::Types::String, null: true, description: 'Name of the base branch of the project.' end # rubocop: enable Graphql/AuthorizeTypes diff --git a/app/graphql/types/ci/runner_architecture_type.rb b/app/graphql/types/ci/runner_architecture_type.rb index 229974d4d13..08d3f98592b 100644 --- a/app/graphql/types/ci/runner_architecture_type.rb +++ b/app/graphql/types/ci/runner_architecture_type.rb @@ -6,9 +6,9 @@ module Types class RunnerArchitectureType < BaseObject graphql_name 'RunnerArchitecture' - field :name, GraphQL::STRING_TYPE, null: false, + field :name, GraphQL::Types::String, null: false, description: 'Name of the runner platform architecture.' - field :download_location, GraphQL::STRING_TYPE, null: false, + field :download_location, GraphQL::Types::String, null: false, description: 'Download location for the runner for the platform architecture.' end end diff --git a/app/graphql/types/ci/runner_platform_type.rb b/app/graphql/types/ci/runner_platform_type.rb index 5636f88835e..ffcf6364968 100644 --- a/app/graphql/types/ci/runner_platform_type.rb +++ b/app/graphql/types/ci/runner_platform_type.rb @@ -6,9 +6,9 @@ module Types class RunnerPlatformType < BaseObject graphql_name 'RunnerPlatform' - field :name, GraphQL::STRING_TYPE, null: false, + field :name, GraphQL::Types::String, null: false, description: 'Name slug of the runner platform.' - field :human_readable_name, GraphQL::STRING_TYPE, null: false, + field :human_readable_name, GraphQL::Types::String, null: false, description: 'Human readable name of the runner platform.' field :architectures, Types::Ci::RunnerArchitectureType.connection_type, null: true, description: 'Runner architectures supported for the platform.' diff --git a/app/graphql/types/ci/runner_setup_type.rb b/app/graphql/types/ci/runner_setup_type.rb index 61a2ea2a411..70f33cef8ad 100644 --- a/app/graphql/types/ci/runner_setup_type.rb +++ b/app/graphql/types/ci/runner_setup_type.rb @@ -6,9 +6,9 @@ module Types class RunnerSetupType < BaseObject graphql_name 'RunnerSetup' - field :install_instructions, GraphQL::STRING_TYPE, null: false, + field :install_instructions, GraphQL::Types::String, null: false, description: 'Instructions for installing the runner on the specified architecture.' - field :register_instructions, GraphQL::STRING_TYPE, null: true, + field :register_instructions, GraphQL::Types::String, null: true, description: 'Instructions for registering the runner.' end end diff --git a/app/graphql/types/ci/runner_type.rb b/app/graphql/types/ci/runner_type.rb index 9c5041b0860..7dc4d867713 100644 --- a/app/graphql/types/ci/runner_type.rb +++ b/app/graphql/types/ci/runner_type.rb @@ -12,38 +12,38 @@ module Types field :id, ::Types::GlobalIDType[::Ci::Runner], null: false, description: 'ID of the runner.' - field :description, GraphQL::STRING_TYPE, null: true, + field :description, GraphQL::Types::String, null: true, description: 'Description of the runner.' field :contacted_at, Types::TimeType, null: true, description: 'Last contact from the runner.', method: :contacted_at - field :maximum_timeout, GraphQL::INT_TYPE, null: true, + field :maximum_timeout, GraphQL::Types::Int, null: true, description: 'Maximum timeout (in seconds) for jobs processed by the runner.' field :access_level, ::Types::Ci::RunnerAccessLevelEnum, null: false, description: 'Access level of the runner.' - field :active, GraphQL::BOOLEAN_TYPE, null: false, + field :active, GraphQL::Types::Boolean, null: false, description: 'Indicates the runner is allowed to receive jobs.' field :status, ::Types::Ci::RunnerStatusEnum, null: false, description: 'Status of the runner.' - field :version, GraphQL::STRING_TYPE, null: true, + field :version, GraphQL::Types::String, null: true, description: 'Version of the runner.' - field :short_sha, GraphQL::STRING_TYPE, null: true, + field :short_sha, GraphQL::Types::String, null: true, description: %q(First eight characters of the runner's token used to authenticate new job requests. Used as the runner's unique ID.) - field :revision, GraphQL::STRING_TYPE, null: true, + field :revision, GraphQL::Types::String, null: true, description: 'Revision of the runner.' - field :locked, GraphQL::BOOLEAN_TYPE, null: true, + field :locked, GraphQL::Types::Boolean, null: true, description: 'Indicates the runner is locked.' - field :run_untagged, GraphQL::BOOLEAN_TYPE, null: false, + field :run_untagged, GraphQL::Types::Boolean, null: false, description: 'Indicates the runner is able to run untagged jobs.' - field :ip_address, GraphQL::STRING_TYPE, null: true, + field :ip_address, GraphQL::Types::String, null: true, description: 'IP address of the runner.' field :runner_type, ::Types::Ci::RunnerTypeEnum, null: false, description: 'Type of the runner.' - field :tag_list, [GraphQL::STRING_TYPE], null: true, + field :tag_list, [GraphQL::Types::String], null: true, description: 'Tags associated with the runner.' - field :project_count, GraphQL::INT_TYPE, null: true, + field :project_count, GraphQL::Types::Int, null: true, description: 'Number of projects that the runner is associated with.' - field :job_count, GraphQL::INT_TYPE, null: true, + field :job_count, GraphQL::Types::Int, null: true, description: "Number of jobs processed by the runner (limited to #{JOB_COUNT_LIMIT}, plus one to indicate that more items exist)." def job_count diff --git a/app/graphql/types/ci/stage_type.rb b/app/graphql/types/ci/stage_type.rb index ce3edb6c54f..ee8fd792bbf 100644 --- a/app/graphql/types/ci/stage_type.rb +++ b/app/graphql/types/ci/stage_type.rb @@ -6,9 +6,9 @@ module Types graphql_name 'CiStage' authorize :read_commit_status - field :id, GraphQL::ID_TYPE, null: false, + field :id, GraphQL::Types::ID, null: false, description: 'ID of the stage.' - field :name, type: GraphQL::STRING_TYPE, null: true, + field :name, type: GraphQL::Types::String, null: true, description: 'Name of the stage.' field :groups, type: Ci::GroupType.connection_type, null: true, extras: [:lookahead], @@ -18,7 +18,7 @@ module Types field :jobs, Ci::JobType.connection_type, null: true, description: 'Jobs for the stage.', method: 'latest_statuses' - field :status, GraphQL::STRING_TYPE, + field :status, GraphQL::Types::String, null: true, description: 'Status of the pipeline stage.' diff --git a/app/graphql/types/ci/status_action_type.rb b/app/graphql/types/ci/status_action_type.rb index a06b09735b3..15e5344e130 100644 --- a/app/graphql/types/ci/status_action_type.rb +++ b/app/graphql/types/ci/status_action_type.rb @@ -5,19 +5,19 @@ module Types class StatusActionType < BaseObject graphql_name 'StatusAction' - field :id, GraphQL::STRING_TYPE, null: false, + field :id, GraphQL::Types::String, null: false, description: 'ID for a status action.', extras: [:parent] - field :button_title, GraphQL::STRING_TYPE, null: true, + field :button_title, GraphQL::Types::String, null: true, description: 'Title for the button, for example: Retry this job.' - field :icon, GraphQL::STRING_TYPE, null: true, + field :icon, GraphQL::Types::String, null: true, description: 'Icon used in the action button.' - field :method, GraphQL::STRING_TYPE, null: true, + field :method, GraphQL::Types::String, null: true, description: 'Method for the action, for example: :post.', resolver_method: :action_method - field :path, GraphQL::STRING_TYPE, null: true, + field :path, GraphQL::Types::String, null: true, description: 'Path for the action.' - field :title, GraphQL::STRING_TYPE, null: true, + field :title, GraphQL::Types::String, null: true, description: 'Title for the action, for example: Retry.' def id(parent:) diff --git a/app/graphql/types/ci/template_type.rb b/app/graphql/types/ci/template_type.rb index 5f07fa16928..7e7ee44025f 100644 --- a/app/graphql/types/ci/template_type.rb +++ b/app/graphql/types/ci/template_type.rb @@ -7,9 +7,9 @@ module Types graphql_name 'CiTemplate' description 'GitLab CI/CD configuration template.' - field :name, GraphQL::STRING_TYPE, null: false, + field :name, GraphQL::Types::String, null: false, description: 'Name of the CI template.' - field :content, GraphQL::STRING_TYPE, null: false, + field :content, GraphQL::Types::String, null: false, description: 'Contents of the CI template.' end end diff --git a/app/graphql/types/ci/test_case_type.rb b/app/graphql/types/ci/test_case_type.rb index 9cc3f918125..9ec5daa44ea 100644 --- a/app/graphql/types/ci/test_case_type.rb +++ b/app/graphql/types/ci/test_case_type.rb @@ -12,25 +12,25 @@ module Types field :status, Types::Ci::TestCaseStatusEnum, null: true, description: "Status of the test case (#{::Gitlab::Ci::Reports::TestCase::STATUS_TYPES.join(', ')})." - field :name, GraphQL::STRING_TYPE, null: true, + field :name, GraphQL::Types::String, null: true, description: 'Name of the test case.' - field :classname, GraphQL::STRING_TYPE, null: true, + field :classname, GraphQL::Types::String, null: true, description: 'Classname of the test case.' field :execution_time, GraphQL::FLOAT_TYPE, null: true, description: 'Test case execution time in seconds.' - field :file, GraphQL::STRING_TYPE, null: true, + field :file, GraphQL::Types::String, null: true, description: 'Path to the file of the test case.' - field :attachment_url, GraphQL::STRING_TYPE, null: true, + field :attachment_url, GraphQL::Types::String, null: true, description: 'URL of the test case attachment file.' - field :system_output, GraphQL::STRING_TYPE, null: true, + field :system_output, GraphQL::Types::String, null: true, description: 'System output of the test case.' - field :stack_trace, GraphQL::STRING_TYPE, null: true, + field :stack_trace, GraphQL::Types::String, null: true, description: 'Stack trace of the test case.' field :recent_failures, Types::Ci::RecentFailuresType, null: true, diff --git a/app/graphql/types/ci/test_report_total_type.rb b/app/graphql/types/ci/test_report_total_type.rb index 1123734adc3..aa07a391519 100644 --- a/app/graphql/types/ci/test_report_total_type.rb +++ b/app/graphql/types/ci/test_report_total_type.rb @@ -10,22 +10,22 @@ module Types field :time, GraphQL::FLOAT_TYPE, null: true, description: 'Total duration of the tests.' - field :count, GraphQL::INT_TYPE, null: true, + field :count, GraphQL::Types::Int, null: true, description: 'Total number of the test cases.' - field :success, GraphQL::INT_TYPE, null: true, + field :success, GraphQL::Types::Int, null: true, description: 'Total number of test cases that succeeded.' - field :failed, GraphQL::INT_TYPE, null: true, + field :failed, GraphQL::Types::Int, null: true, description: 'Total number of test cases that failed.' - field :skipped, GraphQL::INT_TYPE, null: true, + field :skipped, GraphQL::Types::Int, null: true, description: 'Total number of test cases that were skipped.' - field :error, GraphQL::INT_TYPE, null: true, + field :error, GraphQL::Types::Int, null: true, description: 'Total number of test cases that had an error.' - field :suite_error, GraphQL::STRING_TYPE, null: true, + field :suite_error, GraphQL::Types::String, null: true, description: 'Test suite error message.' end # rubocop: enable Graphql/AuthorizeTypes diff --git a/app/graphql/types/ci/test_suite_summary_type.rb b/app/graphql/types/ci/test_suite_summary_type.rb index a80a9179cb4..3db2d80d591 100644 --- a/app/graphql/types/ci/test_suite_summary_type.rb +++ b/app/graphql/types/ci/test_suite_summary_type.rb @@ -9,31 +9,31 @@ module Types connection_type_class(Types::CountableConnectionType) - field :name, GraphQL::STRING_TYPE, null: true, + field :name, GraphQL::Types::String, null: true, description: 'Name of the test suite.' field :total_time, GraphQL::FLOAT_TYPE, null: true, description: 'Total duration of the tests in the test suite.' - field :total_count, GraphQL::INT_TYPE, null: true, + field :total_count, GraphQL::Types::Int, null: true, description: 'Total number of the test cases in the test suite.' - field :success_count, GraphQL::INT_TYPE, null: true, + field :success_count, GraphQL::Types::Int, null: true, description: 'Total number of test cases that succeeded in the test suite.' - field :failed_count, GraphQL::INT_TYPE, null: true, + field :failed_count, GraphQL::Types::Int, null: true, description: 'Total number of test cases that failed in the test suite.' - field :skipped_count, GraphQL::INT_TYPE, null: true, + field :skipped_count, GraphQL::Types::Int, null: true, description: 'Total number of test cases that were skipped in the test suite.' - field :error_count, GraphQL::INT_TYPE, null: true, + field :error_count, GraphQL::Types::Int, null: true, description: 'Total number of test cases that had an error.' - field :suite_error, GraphQL::STRING_TYPE, null: true, + field :suite_error, GraphQL::Types::String, null: true, description: 'Test suite error message.' - field :build_ids, [GraphQL::ID_TYPE], null: true, + field :build_ids, [GraphQL::Types::ID], null: true, description: 'IDs of the builds used to run the test suite.' end # rubocop: enable Graphql/AuthorizeTypes diff --git a/app/graphql/types/ci/test_suite_type.rb b/app/graphql/types/ci/test_suite_type.rb index 7d4c01da81b..f9f37d4045e 100644 --- a/app/graphql/types/ci/test_suite_type.rb +++ b/app/graphql/types/ci/test_suite_type.rb @@ -9,28 +9,28 @@ module Types connection_type_class(Types::CountableConnectionType) - field :name, GraphQL::STRING_TYPE, null: true, + field :name, GraphQL::Types::String, null: true, description: 'Name of the test suite.' field :total_time, GraphQL::FLOAT_TYPE, null: true, description: 'Total duration of the tests in the test suite.' - field :total_count, GraphQL::INT_TYPE, null: true, + field :total_count, GraphQL::Types::Int, null: true, description: 'Total number of the test cases in the test suite.' - field :success_count, GraphQL::INT_TYPE, null: true, + field :success_count, GraphQL::Types::Int, null: true, description: 'Total number of test cases that succeeded in the test suite.' - field :failed_count, GraphQL::INT_TYPE, null: true, + field :failed_count, GraphQL::Types::Int, null: true, description: 'Total number of test cases that failed in the test suite.' - field :skipped_count, GraphQL::INT_TYPE, null: true, + field :skipped_count, GraphQL::Types::Int, null: true, description: 'Total number of test cases that were skipped in the test suite.' - field :error_count, GraphQL::INT_TYPE, null: true, + field :error_count, GraphQL::Types::Int, null: true, description: 'Total number of test cases that had an error.' - field :suite_error, GraphQL::STRING_TYPE, null: true, + field :suite_error, GraphQL::Types::String, null: true, description: 'Test suite error message.' field :test_cases, Types::Ci::TestCaseType.connection_type, null: true, diff --git a/app/graphql/types/ci_configuration/sast/analyzers_entity_input_type.rb b/app/graphql/types/ci_configuration/sast/analyzers_entity_input_type.rb index ccb72283cf6..68b9a63d8dc 100644 --- a/app/graphql/types/ci_configuration/sast/analyzers_entity_input_type.rb +++ b/app/graphql/types/ci_configuration/sast/analyzers_entity_input_type.rb @@ -7,10 +7,10 @@ module Types graphql_name 'SastCiConfigurationAnalyzersEntityInput' description 'Represents the analyzers entity in SAST CI configuration' - argument :name, GraphQL::STRING_TYPE, required: true, + argument :name, GraphQL::Types::String, required: true, description: 'Name of analyzer.' - argument :enabled, GraphQL::BOOLEAN_TYPE, required: true, + argument :enabled, GraphQL::Types::Boolean, required: true, description: 'State of the analyzer.' argument :variables, [::Types::CiConfiguration::Sast::EntityInputType], diff --git a/app/graphql/types/ci_configuration/sast/analyzers_entity_type.rb b/app/graphql/types/ci_configuration/sast/analyzers_entity_type.rb index 3c6202ca7e0..9fdc7c1b000 100644 --- a/app/graphql/types/ci_configuration/sast/analyzers_entity_type.rb +++ b/app/graphql/types/ci_configuration/sast/analyzers_entity_type.rb @@ -8,16 +8,16 @@ module Types graphql_name 'SastCiConfigurationAnalyzersEntity' description 'Represents an analyzer entity in SAST CI configuration' - field :name, GraphQL::STRING_TYPE, null: true, + field :name, GraphQL::Types::String, null: true, description: 'Name of the analyzer.' - field :label, GraphQL::STRING_TYPE, null: true, + field :label, GraphQL::Types::String, null: true, description: 'Analyzer label used in the config UI.' - field :enabled, GraphQL::BOOLEAN_TYPE, null: true, + field :enabled, GraphQL::Types::Boolean, null: true, description: 'Indicates whether an analyzer is enabled.' - field :description, GraphQL::STRING_TYPE, null: true, + field :description, GraphQL::Types::String, null: true, description: 'Analyzer description that is displayed on the form.' field :variables, ::Types::CiConfiguration::Sast::EntityType.connection_type, null: true, diff --git a/app/graphql/types/ci_configuration/sast/entity_input_type.rb b/app/graphql/types/ci_configuration/sast/entity_input_type.rb index 9fce120889b..f0e3c07d71f 100644 --- a/app/graphql/types/ci_configuration/sast/entity_input_type.rb +++ b/app/graphql/types/ci_configuration/sast/entity_input_type.rb @@ -7,13 +7,13 @@ module Types graphql_name 'SastCiConfigurationEntityInput' description 'Represents an entity in SAST CI configuration' - argument :field, GraphQL::STRING_TYPE, required: true, + argument :field, GraphQL::Types::String, required: true, description: 'CI keyword of entity.' - argument :default_value, GraphQL::STRING_TYPE, required: true, + argument :default_value, GraphQL::Types::String, required: true, description: 'Default value that is used if value is empty.' - argument :value, GraphQL::STRING_TYPE, required: true, + argument :value, GraphQL::Types::String, required: true, description: 'Current value of the entity.' end end diff --git a/app/graphql/types/ci_configuration/sast/entity_type.rb b/app/graphql/types/ci_configuration/sast/entity_type.rb index eeb9025391f..41b8575d99a 100644 --- a/app/graphql/types/ci_configuration/sast/entity_type.rb +++ b/app/graphql/types/ci_configuration/sast/entity_type.rb @@ -8,25 +8,25 @@ module Types graphql_name 'SastCiConfigurationEntity' description 'Represents an entity in SAST CI configuration' - field :field, GraphQL::STRING_TYPE, null: true, + field :field, GraphQL::Types::String, null: true, description: 'CI keyword of entity.' - field :label, GraphQL::STRING_TYPE, null: true, + field :label, GraphQL::Types::String, null: true, description: 'Label for entity used in the form.' - field :type, GraphQL::STRING_TYPE, null: true, + field :type, GraphQL::Types::String, null: true, description: 'Type of the field value.' field :options, ::Types::CiConfiguration::Sast::OptionsEntityType.connection_type, null: true, description: 'Different possible values of the field.' - field :default_value, GraphQL::STRING_TYPE, null: true, + field :default_value, GraphQL::Types::String, null: true, description: 'Default value that is used if value is empty.' - field :description, GraphQL::STRING_TYPE, null: true, + field :description, GraphQL::Types::String, null: true, description: 'Entity description that is displayed on the form.' - field :value, GraphQL::STRING_TYPE, null: true, + field :value, GraphQL::Types::String, null: true, description: 'Current value of the entity.' field :size, ::Types::CiConfiguration::Sast::UiComponentSizeEnum, null: true, diff --git a/app/graphql/types/ci_configuration/sast/options_entity_type.rb b/app/graphql/types/ci_configuration/sast/options_entity_type.rb index 86d104a7fda..5f365807cfe 100644 --- a/app/graphql/types/ci_configuration/sast/options_entity_type.rb +++ b/app/graphql/types/ci_configuration/sast/options_entity_type.rb @@ -8,10 +8,10 @@ module Types graphql_name 'SastCiConfigurationOptionsEntity' description 'Represents an entity for options in SAST CI configuration' - field :label, GraphQL::STRING_TYPE, null: true, + field :label, GraphQL::Types::String, null: true, description: 'Label of option entity.' - field :value, GraphQL::STRING_TYPE, null: true, + field :value, GraphQL::Types::String, null: true, description: 'Value of option entity.' end end diff --git a/app/graphql/types/commit_action_type.rb b/app/graphql/types/commit_action_type.rb index cc1f45478e4..b170134b388 100644 --- a/app/graphql/types/commit_action_type.rb +++ b/app/graphql/types/commit_action_type.rb @@ -4,15 +4,15 @@ module Types class CommitActionType < BaseInputObject argument :action, type: Types::CommitActionModeEnum, required: true, description: 'The action to perform, create, delete, move, update, chmod.' - argument :file_path, type: GraphQL::STRING_TYPE, required: true, + argument :file_path, type: GraphQL::Types::String, required: true, description: 'Full path to the file.' - argument :content, type: GraphQL::STRING_TYPE, required: false, + argument :content, type: GraphQL::Types::String, required: false, description: 'Content of the file.' - argument :previous_path, type: GraphQL::STRING_TYPE, required: false, + argument :previous_path, type: GraphQL::Types::String, required: false, description: 'Original full path to the file being moved.' - argument :last_commit_id, type: GraphQL::STRING_TYPE, required: false, + argument :last_commit_id, type: GraphQL::Types::String, required: false, description: 'Last known file commit ID.' - argument :execute_filemode, type: GraphQL::BOOLEAN_TYPE, required: false, + argument :execute_filemode, type: GraphQL::Types::Boolean, required: false, description: 'Enables/disables the execute flag on the file.' argument :encoding, type: Types::CommitEncodingEnum, required: false, description: 'Encoding of the file. Default is text.' diff --git a/app/graphql/types/commit_type.rb b/app/graphql/types/commit_type.rb index d137901380b..dc1bf6a3101 100644 --- a/app/graphql/types/commit_type.rb +++ b/app/graphql/types/commit_type.rb @@ -8,31 +8,31 @@ module Types present_using CommitPresenter - field :id, type: GraphQL::ID_TYPE, null: false, + field :id, type: GraphQL::Types::ID, null: false, description: 'ID (global ID) of the commit.' - field :sha, type: GraphQL::STRING_TYPE, null: false, + field :sha, type: GraphQL::Types::String, null: false, description: 'SHA1 ID of the commit.' - field :short_id, type: GraphQL::STRING_TYPE, null: false, + field :short_id, type: GraphQL::Types::String, null: false, description: 'Short SHA1 ID of the commit.' - field :title, type: GraphQL::STRING_TYPE, null: true, calls_gitaly: true, + field :title, type: GraphQL::Types::String, null: true, calls_gitaly: true, description: 'Title of the commit message.' markdown_field :title_html, null: true - field :description, type: GraphQL::STRING_TYPE, null: true, + field :description, type: GraphQL::Types::String, null: true, description: 'Description of the commit message.' markdown_field :description_html, null: true - field :message, type: GraphQL::STRING_TYPE, null: true, + field :message, type: GraphQL::Types::String, null: true, description: 'Raw commit message.' field :authored_date, type: Types::TimeType, null: true, description: 'Timestamp of when the commit was authored.' - field :web_url, type: GraphQL::STRING_TYPE, null: false, + field :web_url, type: GraphQL::Types::String, null: false, description: 'Web URL of the commit.' - field :web_path, type: GraphQL::STRING_TYPE, null: false, + field :web_path, type: GraphQL::Types::String, null: false, description: 'Web path of the commit.' - field :signature_html, type: GraphQL::STRING_TYPE, null: true, calls_gitaly: true, + field :signature_html, type: GraphQL::Types::String, null: true, calls_gitaly: true, description: 'Rendered HTML of the commit signature.' - field :author_name, type: GraphQL::STRING_TYPE, null: true, + field :author_name, type: GraphQL::Types::String, null: true, description: 'Commit authors name.' - field :author_gravatar, type: GraphQL::STRING_TYPE, null: true, + field :author_gravatar, type: GraphQL::Types::String, null: true, description: 'Commit authors gravatar.' # models/commit lazy loads the author by email diff --git a/app/graphql/types/container_expiration_policy_type.rb b/app/graphql/types/container_expiration_policy_type.rb index 2b01474617a..6d6df21fe3f 100644 --- a/app/graphql/types/container_expiration_policy_type.rb +++ b/app/graphql/types/container_expiration_policy_type.rb @@ -10,7 +10,7 @@ module Types field :created_at, Types::TimeType, null: false, description: 'Timestamp of when the container expiration policy was created.' field :updated_at, Types::TimeType, null: false, description: 'Timestamp of when the container expiration policy was updated.' - field :enabled, GraphQL::BOOLEAN_TYPE, null: false, description: 'Indicates whether this container expiration policy is enabled.' + field :enabled, GraphQL::Types::Boolean, null: false, description: 'Indicates whether this container expiration policy is enabled.' field :older_than, Types::ContainerExpirationPolicyOlderThanEnum, null: true, description: 'Tags older that this will expire.' field :cadence, Types::ContainerExpirationPolicyCadenceEnum, null: false, description: 'This container expiration policy schedule.' field :keep_n, Types::ContainerExpirationPolicyKeepEnum, null: true, description: 'Number of tags to retain.' diff --git a/app/graphql/types/container_repository_tag_type.rb b/app/graphql/types/container_repository_tag_type.rb index 6de16416395..b6b65bce421 100644 --- a/app/graphql/types/container_repository_tag_type.rb +++ b/app/graphql/types/container_repository_tag_type.rb @@ -8,15 +8,15 @@ module Types authorize :read_container_image - field :name, GraphQL::STRING_TYPE, null: false, description: 'Name of the tag.' - field :path, GraphQL::STRING_TYPE, null: false, description: 'Path of the tag.' - field :location, GraphQL::STRING_TYPE, null: false, description: 'URL of the tag.' - field :digest, GraphQL::STRING_TYPE, null: true, description: 'Digest of the tag.' - field :revision, GraphQL::STRING_TYPE, null: true, description: 'Revision of the tag.' - field :short_revision, GraphQL::STRING_TYPE, null: true, description: 'Short revision of the tag.' + field :name, GraphQL::Types::String, null: false, description: 'Name of the tag.' + field :path, GraphQL::Types::String, null: false, description: 'Path of the tag.' + field :location, GraphQL::Types::String, null: false, description: 'URL of the tag.' + field :digest, GraphQL::Types::String, null: true, description: 'Digest of the tag.' + field :revision, GraphQL::Types::String, null: true, description: 'Revision of the tag.' + field :short_revision, GraphQL::Types::String, null: true, description: 'Short revision of the tag.' field :total_size, GraphQL::Types::BigInt, null: true, description: 'The size of the tag.' field :created_at, Types::TimeType, null: true, description: 'Timestamp when the tag was created.' - field :can_delete, GraphQL::BOOLEAN_TYPE, null: false, description: 'Can the current user delete this tag.' + field :can_delete, GraphQL::Types::Boolean, null: false, description: 'Can the current user delete this tag.' def can_delete Ability.allowed?(current_user, :destroy_container_image, object) diff --git a/app/graphql/types/container_repository_type.rb b/app/graphql/types/container_repository_type.rb index 48c2b9f460f..91a65053131 100644 --- a/app/graphql/types/container_repository_type.rb +++ b/app/graphql/types/container_repository_type.rb @@ -8,17 +8,17 @@ module Types authorize :read_container_image - field :id, GraphQL::ID_TYPE, null: false, description: 'ID of the container repository.' - field :name, GraphQL::STRING_TYPE, null: false, description: 'Name of the container repository.' - field :path, GraphQL::STRING_TYPE, null: false, description: 'Path of the container repository.' - field :location, GraphQL::STRING_TYPE, null: false, description: 'URL of the container repository.' + field :id, GraphQL::Types::ID, null: false, description: 'ID of the container repository.' + field :name, GraphQL::Types::String, null: false, description: 'Name of the container repository.' + field :path, GraphQL::Types::String, null: false, description: 'Path of the container repository.' + field :location, GraphQL::Types::String, null: false, description: 'URL of the container repository.' field :created_at, Types::TimeType, null: false, description: 'Timestamp when the container repository was created.' field :updated_at, Types::TimeType, null: false, description: 'Timestamp when the container repository was updated.' field :expiration_policy_started_at, Types::TimeType, null: true, description: 'Timestamp when the cleanup done by the expiration policy was started on the container repository.' field :expiration_policy_cleanup_status, Types::ContainerRepositoryCleanupStatusEnum, null: true, description: 'The tags cleanup status for the container repository.' field :status, Types::ContainerRepositoryStatusEnum, null: true, description: 'Status of the container repository.' - field :tags_count, GraphQL::INT_TYPE, null: false, description: 'Number of tags associated with this image.' - field :can_delete, GraphQL::BOOLEAN_TYPE, null: false, description: 'Can the current user delete the container repository.' + field :tags_count, GraphQL::Types::Int, null: false, description: 'Number of tags associated with this image.' + field :can_delete, GraphQL::Types::Boolean, null: false, description: 'Can the current user delete the container repository.' field :project, Types::ProjectType, null: false, description: 'Project of the container registry.' def can_delete diff --git a/app/graphql/types/countable_connection_type.rb b/app/graphql/types/countable_connection_type.rb index 0a9699a4570..0f24964daa6 100644 --- a/app/graphql/types/countable_connection_type.rb +++ b/app/graphql/types/countable_connection_type.rb @@ -3,7 +3,7 @@ module Types # rubocop: disable Graphql/AuthorizeTypes class CountableConnectionType < GraphQL::Types::Relay::BaseConnection - field :count, GraphQL::INT_TYPE, null: false, + field :count, GraphQL::Types::Int, null: false, description: 'Total count of collection.' def count diff --git a/app/graphql/types/custom_emoji_type.rb b/app/graphql/types/custom_emoji_type.rb index 246b60ce184..64381b3ee1e 100644 --- a/app/graphql/types/custom_emoji_type.rb +++ b/app/graphql/types/custom_emoji_type.rb @@ -11,16 +11,16 @@ module Types null: false, description: 'The ID of the emoji.' - field :name, GraphQL::STRING_TYPE, + field :name, GraphQL::Types::String, null: false, description: 'The name of the emoji.' - field :url, GraphQL::STRING_TYPE, + field :url, GraphQL::Types::String, null: false, method: :file, description: 'The link to file of the emoji.' - field :external, GraphQL::BOOLEAN_TYPE, + field :external, GraphQL::Types::Boolean, null: false, description: 'Whether the emoji is an external link.' end diff --git a/app/models/concerns/project_features_compatibility.rb b/app/models/concerns/project_features_compatibility.rb index 484c91e0833..121b696a659 100644 --- a/app/models/concerns/project_features_compatibility.rb +++ b/app/models/concerns/project_features_compatibility.rb @@ -90,6 +90,17 @@ module ProjectFeaturesCompatibility write_feature_attribute_string(:container_registry_access_level, value) end + # TODO: Remove this method after we drop support for project create/edit APIs to set the + # container_registry_enabled attribute. They can instead set the container_registry_access_level + # attribute. + def container_registry_enabled=(value) + write_feature_attribute_boolean(:container_registry_access_level, value) + + # TODO: Remove this when we remove the projects.container_registry_enabled + # column. https://gitlab.com/gitlab-org/gitlab/-/issues/335425 + super + end + private def write_feature_attribute_boolean(field, value) diff --git a/app/models/namespace.rb b/app/models/namespace.rb index d296f6a44d2..9914b443eba 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -465,10 +465,34 @@ class Namespace < ApplicationRecord end def refresh_access_of_projects_invited_groups - Group - .joins(project_group_links: :project) - .where(projects: { namespace_id: id }) - .find_each(&:refresh_members_authorized_projects) + if Feature.enabled?(:specialized_worker_for_group_lock_update_auth_recalculation) + Project + .where(namespace_id: id) + .joins(:project_group_links) + .distinct + .find_each do |project| + AuthorizedProjectUpdate::ProjectRecalculateWorker.perform_async(project.id) + end + + # Until we compare the inconsistency rates of the new specialized worker and + # the old approach, we still run AuthorizedProjectsWorker + # but with some delay and lower urgency as a safety net. + Group + .joins(project_group_links: :project) + .where(projects: { namespace_id: id }) + .distinct + .find_each do |group| + group.refresh_members_authorized_projects( + blocking: false, + priority: UserProjectAccessChangedService::LOW_PRIORITY + ) + end + else + Group + .joins(project_group_links: :project) + .where(projects: { namespace_id: id }) + .find_each(&:refresh_members_authorized_projects) + end end def nesting_level_allowed diff --git a/app/models/project.rb b/app/models/project.rb index 24ff0ed3b8c..6a90ae9038a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -76,7 +76,6 @@ class Project < ApplicationRecord default_value_for :packages_enabled, true default_value_for :archived, false default_value_for :resolve_outdated_diff_discussions, false - default_value_for :container_registry_enabled, gitlab_config_features.container_registry default_value_for(:repository_storage) do Repository.pick_storage_shard end @@ -98,9 +97,6 @@ class Project < ApplicationRecord before_save :ensure_runners_token - # https://api.rubyonrails.org/v6.0.3.4/classes/ActiveRecord/AttributeMethods/Dirty.html#method-i-will_save_change_to_attribute-3F - before_update :set_container_registry_access_level, if: :will_save_change_to_container_registry_enabled? - after_save :update_project_statistics, if: :saved_change_to_namespace_id? after_save :create_import_state, if: ->(project) { project.import? && project.import_state.nil? } @@ -1184,6 +1180,15 @@ class Project < ApplicationRecord import_type == 'gitea' end + def github_import? + import_type == 'github' + end + + def github_enterprise_import? + github_import? && + URI.parse(import_url).host != URI.parse(Octokit::Default::API_ENDPOINT).host + end + def has_remote_mirror? remote_mirror_available? && remote_mirrors.enabled.exists? end @@ -2659,20 +2664,6 @@ class Project < ApplicationRecord private - def set_container_registry_access_level - # changes_to_save = { 'container_registry_enabled' => [value_before_update, value_after_update] } - value = changes_to_save['container_registry_enabled'][1] - - access_level = - if value - ProjectFeature::ENABLED - else - ProjectFeature::DISABLED - end - - project_feature.update!(container_registry_access_level: access_level) - end - def find_integration(integrations, name) integrations.find { _1.to_param == name } end diff --git a/app/models/project_feature.rb b/app/models/project_feature.rb index f6e889396c6..94db683267d 100644 --- a/app/models/project_feature.rb +++ b/app/models/project_feature.rb @@ -2,6 +2,7 @@ class ProjectFeature < ApplicationRecord include Featurable + extend Gitlab::ConfigHelper # When updating this array, make sure to update rubocop/cop/gitlab/feature_available_usage.rb as well. FEATURES = %i[ @@ -48,8 +49,6 @@ class ProjectFeature < ApplicationRecord end end - before_create :set_container_registry_access_level - # Default scopes force us to unscope here since a service may need to check # permissions for a project in pending_delete # http://stackoverflow.com/questions/1540645/how-to-disable-default-scope-for-a-belongs-to @@ -80,6 +79,14 @@ class ProjectFeature < ApplicationRecord end end + default_value_for(:container_registry_access_level, allows_nil: false) do |feature| + if gitlab_config_features.container_registry + ENABLED + else + DISABLED + end + end + def public_pages? return true unless Gitlab.config.pages.access_control @@ -94,15 +101,6 @@ class ProjectFeature < ApplicationRecord private - def set_container_registry_access_level - self.container_registry_access_level = - if project&.read_attribute(:container_registry_enabled) - ENABLED - else - DISABLED - end - end - # Validates builds and merge requests access level # which cannot be higher than repository access level def repository_children_level diff --git a/app/services/ci/build_cancel_service.rb b/app/services/ci/build_cancel_service.rb new file mode 100644 index 00000000000..a23418ed738 --- /dev/null +++ b/app/services/ci/build_cancel_service.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module Ci + class BuildCancelService + def initialize(build, user) + @build = build + @user = user + end + + def execute + return forbidden unless allowed? + return unprocessable_entity unless build.cancelable? + + build.cancel + + ServiceResponse.success(payload: build) + end + + private + + attr_reader :build, :user + + def allowed? + user.can?(:update_build, build) + end + + def forbidden + ServiceResponse.error(message: 'Forbidden', http_status: :forbidden) + end + + def unprocessable_entity + ServiceResponse.error(message: 'Unprocessable entity', http_status: :unprocessable_entity) + end + end +end diff --git a/app/services/ci/build_unschedule_service.rb b/app/services/ci/build_unschedule_service.rb new file mode 100644 index 00000000000..3b367ecc4c4 --- /dev/null +++ b/app/services/ci/build_unschedule_service.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module Ci + class BuildUnscheduleService + def initialize(build, user) + @build = build + @user = user + end + + def execute + return forbidden unless allowed? + return unprocessable_entity unless build.scheduled? + + build.unschedule! + + ServiceResponse.success(payload: build) + end + + private + + attr_reader :build, :user + + def allowed? + user.can?(:update_build, build) + end + + def forbidden + ServiceResponse.error(message: 'Forbidden', http_status: :forbidden) + end + + def unprocessable_entity + ServiceResponse.error(message: 'Unprocessable entity', http_status: :unprocessable_entity) + end + end +end diff --git a/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb b/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb index 762f1f10bb6..de9bb4d5a93 100644 --- a/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb +++ b/app/workers/container_expiration_policies/cleanup_container_repository_worker.rb @@ -63,16 +63,23 @@ module ContainerExpirationPolicies def container_repository strong_memoize(:container_repository) do ContainerRepository.transaction do - # We need a lock to prevent two workers from picking up the same row - container_repository = next_container_repository + repository = next_container_repository - container_repository&.tap(&:cleanup_ongoing!) + repository&.tap do |repo| + log_info( + project_id: repo.project_id, + container_repository_id: repo.id + ) + + repo.cleanup_ongoing! + end end end end def next_container_repository # rubocop: disable CodeReuse/ActiveRecord + # We need a lock to prevent two workers from picking up the same row next_one_requiring = ContainerRepository.requiring_cleanup .order(:expiration_policy_cleanup_status, :expiration_policy_started_at) .limit(1) diff --git a/config/feature_flags/development/specialized_worker_for_group_lock_update_auth_recalculation.yml b/config/feature_flags/development/specialized_worker_for_group_lock_update_auth_recalculation.yml new file mode 100644 index 00000000000..820e6cafb41 --- /dev/null +++ b/config/feature_flags/development/specialized_worker_for_group_lock_update_auth_recalculation.yml @@ -0,0 +1,8 @@ +--- +name: specialized_worker_for_group_lock_update_auth_recalculation +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66525 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/336592 +milestone: '14.2' +type: development +group: group::access +default_enabled: false diff --git a/doc/administration/geo/replication/configuration.md b/doc/administration/geo/replication/configuration.md index 7331b032c52..3a116de32bd 100644 --- a/doc/administration/geo/replication/configuration.md +++ b/doc/administration/geo/replication/configuration.md @@ -7,35 +7,35 @@ type: howto # Geo configuration **(PREMIUM SELF)** -## Configuring a new **secondary** node +## Configuring a new **secondary** site NOTE: -This is the final step in setting up a **secondary** Geo node. Stages of the +This is the final step in setting up a **secondary** Geo site. Stages of the setup process must be completed in the documented order. Before attempting the steps in this stage, [complete all prior stages](../setup/index.md#using-omnibus-gitlab). -The basic steps of configuring a **secondary** node are to: +The basic steps of configuring a **secondary** site are to: -- Replicate required configurations between the **primary** node and the **secondary** nodes. -- Configure a tracking database on each **secondary** node. -- Start GitLab on each **secondary** node. +- Replicate required configurations between the **primary** site and the **secondary** sites. +- Configure a tracking database on each **secondary** site. +- Start GitLab on each **secondary** site. You are encouraged to first read through all the steps before executing them in your testing/production environment. NOTE: -**Do not** set up any custom authentication for the **secondary** nodes. This is handled by the **primary** node. +**Do not** set up any custom authentication for the **secondary** sites. This is handled by the **primary** site. Any change that requires access to the **Admin Area** needs to be done in the -**primary** node because the **secondary** node is a read-only replica. +**primary** site because the **secondary** site is a read-only replica. ### Step 1. Manually replicate secret GitLab values GitLab stores a number of secret values in the `/etc/gitlab/gitlab-secrets.json` -file which *must* be the same on all nodes. Until there is -a means of automatically replicating these between nodes (see [issue #3789](https://gitlab.com/gitlab-org/gitlab/-/issues/3789)), -they must be manually replicated to the **secondary** node. +file which *must* be the same on all of a site's nodes. Until there is +a means of automatically replicating these between sites (see [issue #3789](https://gitlab.com/gitlab-org/gitlab/-/issues/3789)), +they must be manually replicated to **all nodes of the secondary site**. -1. SSH into the **primary** node, and execute the command below: +1. SSH into a **Rails node on your primary** site, and execute the command below: ```shell sudo cat /etc/gitlab/gitlab-secrets.json @@ -43,7 +43,7 @@ they must be manually replicated to the **secondary** node. This displays the secrets that need to be replicated, in JSON format. -1. SSH into the **secondary** node and login as the `root` user: +1. SSH **into each node on your secondary Geo site** and login as the `root` user: ```shell sudo -i @@ -55,7 +55,7 @@ they must be manually replicated to the **secondary** node. mv /etc/gitlab/gitlab-secrets.json /etc/gitlab/gitlab-secrets.json.`date +%F` ``` -1. Copy `/etc/gitlab/gitlab-secrets.json` from the **primary** node to the **secondary** node, or +1. Copy `/etc/gitlab/gitlab-secrets.json` from the **Rails node on your primary** site to **each node on your secondary** site, or copy-and-paste the file contents between nodes: ```shell @@ -72,28 +72,28 @@ they must be manually replicated to the **secondary** node. chmod 0600 /etc/gitlab/gitlab-secrets.json ``` -1. Reconfigure the **secondary** node for the change to take effect: +1. Reconfigure **each Rails, Sidekiq and Gitaly nodes on your secondary** site for the change to take effect: ```shell gitlab-ctl reconfigure gitlab-ctl restart ``` -### Step 2. Manually replicate the **primary** node's SSH host keys +### Step 2. Manually replicate the **primary** site's SSH host keys GitLab integrates with the system-installed SSH daemon, designating a user (typically named `git`) through which all access requests are handled. In a [Disaster Recovery](../disaster_recovery/index.md) situation, GitLab system -administrators promote a **secondary** node to the **primary** node. DNS records for the -**primary** domain should also be updated to point to the new **primary** node -(previously a **secondary** node). Doing so avoids the need to update Git remotes and API URLs. +administrators promote a **secondary** site to the **primary** site. DNS records for the +**primary** domain should also be updated to point to the new **primary** site +(previously a **secondary** site). Doing so avoids the need to update Git remotes and API URLs. -This causes all SSH requests to the newly promoted **primary** node to +This causes all SSH requests to the newly promoted **primary** site to fail due to SSH host key mismatch. To prevent this, the primary SSH host -keys must be manually replicated to the **secondary** node. +keys must be manually replicated to the **secondary** site. -1. SSH into the **secondary** node and login as the `root` user: +1. SSH into **each node on your secondary** site and login as the `root` user: ```shell sudo -i @@ -105,34 +105,34 @@ keys must be manually replicated to the **secondary** node. find /etc/ssh -iname ssh_host_* -exec cp {} {}.backup.`date +%F` \; ``` -1. Copy OpenSSH host keys from the **primary** node: +1. Copy OpenSSH host keys from the **primary** site: - If you can access your **primary** node using the **root** user: + If you can access one of the **nodes on your primary** site serving SSH traffic (usually, the main GitLab Rails application nodes) using the **root** user: ```shell - # Run this from the secondary node, change `<primary_node_fqdn>` for the IP or FQDN of the server + # Run this from the secondary site, change `<primary_site_fqdn>` for the IP or FQDN of the server scp root@<primary_node_fqdn>:/etc/ssh/ssh_host_*_key* /etc/ssh ``` If you only have access through a user with `sudo` privileges: ```shell - # Run this from your primary node: + # Run this from the node on your primary site: sudo tar --transform 's/.*\///g' -zcvf ~/geo-host-key.tar.gz /etc/ssh/ssh_host_*_key* - # Run this from your secondary node: - scp <user_with_sudo>@<primary_node_fqdn>:geo-host-key.tar.gz . + # Run this on each node on your secondary site: + scp <user_with_sudo>@<primary_site_fqdn>:geo-host-key.tar.gz . tar zxvf ~/geo-host-key.tar.gz -C /etc/ssh ``` -1. On your **secondary** node, ensure the file permissions are correct: +1. On **each node on your secondary** site, ensure the file permissions are correct: ```shell chown root:root /etc/ssh/ssh_host_*_key* chmod 0600 /etc/ssh/ssh_host_*_key* ``` -1. To verify key fingerprint matches, execute the following command on both nodes: +1. To verify key fingerprint matches, execute the following command on both primary and secondary nodes on each site: ```shell for file in /etc/ssh/ssh_host_*_key; do ssh-keygen -lf $file; done @@ -160,7 +160,7 @@ keys must be manually replicated to the **secondary** node. NOTE: The output for private keys and public keys command should generate the same fingerprint. -1. Restart `sshd` on your **secondary** node: +1. Restart `sshd` on **each node on your secondary** site: ```shell # Debian or Ubuntu installations @@ -175,31 +175,31 @@ keys must be manually replicated to the **secondary** node. SSH into your GitLab **secondary** server in a new terminal. If you are unable to connect, verify the permissions are correct according to the previous steps. -### Step 3. Add the **secondary** node +### Step 3. Add the **secondary** site -1. SSH into your GitLab **secondary** server and login as root: +1. SSH into **each Rails and Sidekiq node on your secondary** site and login as root: ```shell sudo -i ``` -1. Edit `/etc/gitlab/gitlab.rb` and add a **unique** name for your node. You need this in the next steps: +1. Edit `/etc/gitlab/gitlab.rb` and add a **unique** name for your site. You need this in the next steps: ```ruby - # The unique identifier for the Geo node. - gitlab_rails['geo_node_name'] = '<node_name_here>' + # The unique identifier for the Geo site. + gitlab_rails['geo_node_name'] = '<site_name_here>' ``` -1. Reconfigure the **secondary** node for the change to take effect: +1. Reconfigure **each Rails and Sidekiq node on your secondary** site for the change to take effect: ```shell gitlab-ctl reconfigure ``` -1. On the top bar of the primary node, select **Menu >** **{admin}** **Admin**. -1. On the left sidebar, select **Geo > Nodes**. -1. Select **Add site**. - ![Add secondary node](img/adding_a_secondary_node_v13_3.png) +1. On the top bar, select **Menu >** **{admin}** **Admin**. +1. On the left sidebar, select **Geo > Sites**. +1. Select **New site**. + ![Add secondary site](img/adding_a_secondary_node_v13_3.png) 1. Fill in **Name** with the `gitlab_rails['geo_node_name']` in `/etc/gitlab/gitlab.rb`. These values must always match *exactly*, character for character. @@ -207,10 +207,10 @@ keys must be manually replicated to the **secondary** node. values must always match, but it doesn't matter if one ends with a `/` and the other doesn't. 1. Optionally, choose which groups or storage shards should be replicated by the - **secondary** node. Leave blank to replicate all. Read more in + **secondary** site. Leave blank to replicate all. Read more in [selective synchronization](#selective-synchronization). -1. Select **Add node** to add the **secondary** node. -1. SSH into your GitLab **secondary** server and restart the services: +1. Select **Add site** to add the **secondary** site. +1. SSH into **each Rails, and Sidekiq node on your secondary** site and restart the services: ```shell gitlab-ctl restart @@ -222,56 +222,56 @@ keys must be manually replicated to the **secondary** node. gitlab-rake gitlab:geo:check ``` -1. SSH into your **primary** server and login as root to verify the - **secondary** node is reachable or there are any common issue with your Geo setup: +1. SSH into a **Rails or Sidekiq server on your primary** site and login as root to verify the + **secondary** site is reachable or there are any common issue with your Geo setup: ```shell gitlab-rake gitlab:geo:check ``` -Once added to the Geo administration page and restarted, the **secondary** node automatically starts -replicating missing data from the **primary** node in a process known as **backfill**. -Meanwhile, the **primary** node starts to notify each **secondary** node of any changes, so -that the **secondary** node can act on those notifications immediately. +Once added to the Geo administration page and restarted, the **secondary** site automatically starts +replicating missing data from the **primary** site in a process known as **backfill**. +Meanwhile, the **primary** site starts to notify each **secondary** site of any changes, so +that the **secondary** site can act on those notifications immediately. -Be sure the _secondary_ node is running and accessible. You can sign in to the -_secondary_ node with the same credentials as were used with the _primary_ node. +Be sure the _secondary_ site is running and accessible. You can sign in to the +_secondary_ site with the same credentials as were used with the _primary_ site. -### Step 4. (Optional) Configuring the **secondary** node to trust the **primary** node +### Step 4. (Optional) Configuring the **secondary** site to trust the **primary** site -You can safely skip this step if your **primary** node uses a CA-issued HTTPS certificate. +You can safely skip this step if your **primary** site uses a CA-issued HTTPS certificate. -If your **primary** node is using a self-signed certificate for *HTTPS* support, you -need to add that certificate to the **secondary** node's trust store. Retrieve the -certificate from the **primary** node and follow +If your **primary** site is using a self-signed certificate for *HTTPS* support, you +need to add that certificate to the **secondary** site's trust store. Retrieve the +certificate from the **primary** site and follow [these instructions](https://docs.gitlab.com/omnibus/settings/ssl.html) -on the **secondary** node. +on the **secondary** site. ### Step 5. Enable Git access over HTTP/HTTPS Geo synchronizes repositories over HTTP/HTTPS, and therefore requires this clone -method to be enabled. This is enabled by default, but if converting an existing node to Geo it should be checked: +method to be enabled. This is enabled by default, but if converting an existing site to Geo it should be checked: -On the **primary** node: +On the **primary** site: 1. On the top bar, select **Menu >** **{admin}** **Admin**. 1. On the left sidebar, select **Settings > General**. 1. Expand **Visibility and access controls**. 1. Ensure "Enabled Git access protocols" is set to either "Both SSH and HTTP(S)" or "Only HTTP(S)". -### Step 6. Verify proper functioning of the **secondary** node +### Step 6. Verify proper functioning of the **secondary** site -You can sign in to the **secondary** node with the same credentials you used with -the **primary** node. After you sign in: +You can sign in to the **secondary** site with the same credentials you used with +the **primary** site. After you sign in: 1. On the top bar, select **Menu >** **{admin}** **Admin**. -1. On the left sidebar, select **Geo > Nodes**. -1. Verify that it's correctly identified as a **secondary** Geo node, and that +1. On the left sidebar, select **Geo > Sites**. +1. Verify that it's correctly identified as a **secondary** Geo site, and that Geo is enabled. The initial replication, or 'backfill', is probably still in progress. You -can monitor the synchronization process on each Geo node from the **primary** -node's **Geo Nodes** dashboard in your browser. +can monitor the synchronization process on each Geo site from the **primary** +site's **Geo Sites** dashboard in your browser. ![Geo dashboard](img/geo_node_dashboard_v14_0.png) @@ -286,10 +286,10 @@ The two most obvious issues that can become apparent in the dashboard are: - You are using a custom certificate or custom CA (see the [troubleshooting document](troubleshooting.md)). - The instance is firewalled (check your firewall rules). -Disabling a **secondary** node stops the synchronization process. +Please note that disabling a **secondary** site stops the synchronization process. -If `git_data_dirs` is customized on the **primary** node for multiple -repository shards you must duplicate the same configuration on each **secondary** node. +Please note that if `git_data_dirs` is customized on the **primary** site for multiple +repository shards you must duplicate the same configuration on each **secondary** site. Point your users to the [Using a Geo Site guide](usage.md). @@ -304,7 +304,7 @@ Currently, this is what is synced: ## Selective synchronization Geo supports selective synchronization, which allows administrators to choose -which projects should be synchronized by **secondary** nodes. +which projects should be synchronized by **secondary** sites. A subset of projects can be chosen, either by group or by storage shard. The former is ideal for replicating data belonging to a subset of users, while the latter is more suited to progressively rolling out Geo to a large GitLab @@ -312,22 +312,22 @@ instance. It is important to note that selective synchronization: -1. Does not restrict permissions from **secondary** nodes. -1. Does not hide project metadata from **secondary** nodes. +1. Does not restrict permissions from **secondary** sites. +1. Does not hide project metadata from **secondary** sites. - Since Geo currently relies on PostgreSQL replication, all project metadata - gets replicated to **secondary** nodes, but repositories that have not been + gets replicated to **secondary** sites, but repositories that have not been selected are empty. 1. Does not reduce the number of events generated for the Geo event log. - - The **primary** node generates events as long as any **secondary** nodes are present. - Selective synchronization restrictions are implemented on the **secondary** nodes, - not the **primary** node. + - The **primary** site generates events as long as any **secondary** sites are present. + Selective synchronization restrictions are implemented on the **secondary** sites, + not the **primary** site. ### Git operations on unreplicated repositories > [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2562) in GitLab 12.10 for HTTP(S) and in GitLab 13.0 for SSH. Git clone, pull, and push operations over HTTP(S) and SSH are supported for repositories that -exist on the **primary** node but not on **secondary** nodes. This situation can occur +exist on the **primary** site but not on **secondary** sites. This situation can occur when: - Selective synchronization does not include the project attached to the repository. @@ -335,7 +335,7 @@ when: ## Upgrading Geo -See the [updating the Geo nodes document](updating_the_geo_nodes.md). +See the [updating the Geo sites document](updating_the_geo_nodes.md). ## Troubleshooting diff --git a/doc/development/fe_guide/haml.md b/doc/development/fe_guide/haml.md index eaf475a35b6..8f501007755 100644 --- a/doc/development/fe_guide/haml.md +++ b/doc/development/fe_guide/haml.md @@ -31,7 +31,7 @@ For example: - Before: ```haml - = gitlab_ui_form_for @group do |f| + = form_for @group do |f| .form-group.gl-mb-3 .gl-form-checkbox.custom-control.custom-checkbox = f.check_box :prevent_sharing_groups_outside_hierarchy, disabled: !can_change_prevent_sharing_groups_outside_hierarchy?(@group), class: 'custom-control-input' diff --git a/doc/development/github_importer.md b/doc/development/github_importer.md index 91df33e6d95..14fd8f6bf72 100644 --- a/doc/development/github_importer.md +++ b/doc/development/github_importer.md @@ -183,6 +183,9 @@ perform: tries to find the user based on the GitHub user ID, while the second query is used to find the user using their GitHub Email address. +To avoid mismatching users, the search by GitHub user ID is not done when importing from GitHub +Enterprise. + Because this process is quite expensive we cache the result of these lookups in Redis. For every user looked up we store three keys: diff --git a/doc/user/project/working_with_projects.md b/doc/user/project/working_with_projects.md index 08b63bfed5f..15a3087cabc 100644 --- a/doc/user/project/working_with_projects.md +++ b/doc/user/project/working_with_projects.md @@ -148,39 +148,44 @@ To use a custom project template on the **New project** page: > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/26388) in GitLab 10.5. -When you create a new repository locally, instead of manually creating a new project in GitLab -and then [cloning the repository](../../gitlab-basics/start-using-git.md#clone-a-repository) -locally, you can directly push it to GitLab to create the new project, all without leaving -your terminal. If you have access rights to the associated namespace, GitLab -automatically creates a new project under that GitLab namespace with its visibility -set to Private by default (you can later change it in the [project's settings](../../public_access/public_access.md#change-project-visibility)). - -This can be done by using either SSH or HTTPS: - -```shell -## Git push using SSH -git push --set-upstream git@gitlab.example.com:namespace/nonexistent-project.git master - -## Git push using HTTPS -git push --set-upstream https://gitlab.example.com/namespace/nonexistent-project.git master -``` - -You can pass the flag `--tags` to the `git push` command to export existing repository tags. - -Once the push finishes successfully, a remote message indicates -the command to set the remote and the URL to the new project: - -```plaintext -remote: -remote: The private project namespace/nonexistent-project was created. -remote: -remote: To configure the remote, run: -remote: git remote add origin https://gitlab.example.com/namespace/nonexistent-project.git -remote: -remote: To view the project, visit: -remote: https://gitlab.example.com/namespace/nonexistent-project -remote: -``` +When you create a new repository locally, you don't have to sign in to the GitLab +interface to create a project and +[clone its repository](../../gitlab-basics/start-using-git.md#clone-a-repository). +You can directly push your new repository to GitLab, which creates your new project +without leaving your terminal. + +To push a new project: + +1. Identify the [namespace](../group/index.md#namespaces) you want to add the new + project to, as you need this information in a future step. To determine if you have + permission to create new projects in a namespace, view the group's page in a + web browser and confirm the page displays a **New project** button. + + NOTE: + As project creation permissions can have many factors, contact your + GitLab administrator if you're unsure. + +1. If you want to push using SSH, ensure you have [created a SSH key](../../ssh/README.md) and + [added it to your GitLab account](../../ssh/index.md#add-an-ssh-key-to-your-gitlab-account). +1. Push with one of the following methods. Replace `gitlab.example.com` with the + domain name of the machine that hosts your Git repository, `namespace` with the name of + your namespace, and `myproject` with the name of your new project: + - To push with SSH: `git push --set-upstream git@gitlab.example.com:namespace/myproject.git master` + - To push with HTTPS: `git push --set-upstream https://gitlab.example.com/namespace/myproject.git master` + Optional: to export existing repository tags, append the `--tags` flag to your `git push` command. +1. When the push completes, GitLab displays a message: + + ```plaintext + remote: The private project namespace/myproject was created. + ``` + +1. (Optional) To configure the remote, alter the command + `git remote add origin https://gitlab.example.com/namespace/myproject.git` + to match your namespace and project names. + +You can view your new project at `https://gitlab.example.com/namespace/myproject`. +Your project's visibility is set to **Private** by default, but you can change it +in your [project's settings](../../public_access/public_access.md#change-project-visibility)). ## Fork a project diff --git a/lib/gitlab/github_import/user_finder.rb b/lib/gitlab/github_import/user_finder.rb index 058cd1ebd57..f583ef39d13 100644 --- a/lib/gitlab/github_import/user_finder.rb +++ b/lib/gitlab/github_import/user_finder.rb @@ -120,10 +120,18 @@ module Gitlab read_id_from_cache(ID_FOR_EMAIL_CACHE_KEY % email) end - # Queries and caches the GitLab user ID for a GitHub user ID, if one was - # found. + # If importing from github.com, queries and caches the GitLab user ID for + # a GitHub user ID, if one was found. + # + # When importing from Github Enterprise, do not query user by Github ID + # since we only have users' Github ID from github.com. def id_for_github_id(id) - gitlab_id = query_id_for_github_id(id) || nil + gitlab_id = + if project.github_enterprise_import? + nil + else + query_id_for_github_id(id) + end Gitlab::Cache::Import::Caching.write(ID_CACHE_KEY % id, gitlab_id) end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 68c8a5efbdc..f44a91e9cca 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -28964,10 +28964,10 @@ msgstr "" msgid "SecurityConfiguration|Feature documentation for %{featureName}" msgstr "" -msgid "SecurityConfiguration|GitLab Ultimate checks your application for security vulnerabilities that may lead to unauthorized access, data leaks, and denial of service attacks. Its features include:" +msgid "SecurityConfiguration|High-level vulnerability statistics across projects and groups" msgstr "" -msgid "SecurityConfiguration|High-level vulnerability statistics across projects and groups." +msgid "SecurityConfiguration|Immediately begin risk analysis and remediation with application security features. Start with SAST and Secret Detection, available to all plans. Upgrade to Ultimate to get all features, including:" msgstr "" msgid "SecurityConfiguration|Manage" @@ -28982,6 +28982,9 @@ msgstr "" msgid "SecurityConfiguration|More information" msgstr "" +msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance" +msgstr "" + msgid "SecurityConfiguration|Not enabled" msgstr "" @@ -28991,7 +28994,7 @@ msgstr "" msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}" msgstr "" -msgid "SecurityConfiguration|Runtime security metrics for application environments." +msgid "SecurityConfiguration|Runtime security metrics for application environments" msgstr "" msgid "SecurityConfiguration|SAST Analyzers" @@ -29000,7 +29003,7 @@ msgstr "" msgid "SecurityConfiguration|SAST Configuration" msgstr "" -msgid "SecurityConfiguration|Secure your project with Ultimate" +msgid "SecurityConfiguration|Secure your project" msgstr "" msgid "SecurityConfiguration|Security Control" @@ -29027,10 +29030,7 @@ msgstr "" msgid "SecurityConfiguration|View history" msgstr "" -msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request." -msgstr "" - -msgid "SecurityConfiguration|With the information provided, you can immediately begin risk analysis and remediation within GitLab." +msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request" msgstr "" msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}." diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb index a7a36d3a074..e9e7c3c3bb3 100644 --- a/spec/controllers/projects/jobs_controller_spec.rb +++ b/spec/controllers/projects/jobs_controller_spec.rb @@ -868,64 +868,85 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do end describe 'POST cancel' do - before do - project.add_developer(user) - sign_in(user) - end + context 'when user is authorized to cancel the build' do + before do + project.add_developer(user) + sign_in(user) + end - context 'when continue url is present' do - let(:job) { create(:ci_build, :cancelable, pipeline: pipeline) } + context 'when continue url is present' do + let(:job) { create(:ci_build, :cancelable, pipeline: pipeline) } - context 'when continue to is a safe url' do - let(:url) { '/test' } + context 'when continue to is a safe url' do + let(:url) { '/test' } - before do - post_cancel(continue: { to: url }) - end + before do + post_cancel(continue: { to: url }) + end - it 'redirects to the continue url' do - expect(response).to have_gitlab_http_status(:found) - expect(response).to redirect_to(url) + it 'redirects to the continue url' do + expect(response).to have_gitlab_http_status(:found) + expect(response).to redirect_to(url) + end + + it 'transits to canceled' do + expect(job.reload).to be_canceled + end end - it 'transits to canceled' do - expect(job.reload).to be_canceled + context 'when continue to is not a safe url' do + let(:url) { 'http://example.com' } + + it 'raises an error' do + expect { cancel_with_redirect(url) }.to raise_error + end end end - context 'when continue to is not a safe url' do - let(:url) { 'http://example.com' } + context 'when continue url is not present' do + before do + post_cancel + end + + context 'when job is cancelable' do + let(:job) { create(:ci_build, :cancelable, pipeline: pipeline) } + + it 'redirects to the builds page' do + expect(response).to have_gitlab_http_status(:found) + expect(response).to redirect_to(builds_namespace_project_pipeline_path(id: pipeline.id)) + end + + it 'transits to canceled' do + expect(job.reload).to be_canceled + end + end + + context 'when job is not cancelable' do + let(:job) { create(:ci_build, :canceled, pipeline: pipeline) } - it 'raises an error' do - expect { cancel_with_redirect(url) }.to raise_error + it 'returns unprocessable_entity' do + expect(response).to have_gitlab_http_status(:unprocessable_entity) + end end end end - context 'when continue url is not present' do + context 'when user is not authorized to cancel the build' do + let!(:job) { create(:ci_build, :cancelable, pipeline: pipeline) } + before do + project.add_reporter(user) + sign_in(user) + post_cancel end - context 'when job is cancelable' do - let(:job) { create(:ci_build, :cancelable, pipeline: pipeline) } - - it 'redirects to the builds page' do - expect(response).to have_gitlab_http_status(:found) - expect(response).to redirect_to(builds_namespace_project_pipeline_path(id: pipeline.id)) - end - - it 'transits to canceled' do - expect(job.reload).to be_canceled - end + it 'responds with not_found' do + expect(response).to have_gitlab_http_status(:not_found) end - context 'when job is not cancelable' do - let(:job) { create(:ci_build, :canceled, pipeline: pipeline) } - - it 'returns unprocessable_entity' do - expect(response).to have_gitlab_http_status(:unprocessable_entity) - end + it 'does not transit to canceled' do + expect(job.reload).not_to be_canceled end end @@ -938,43 +959,60 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do describe 'POST unschedule' do before do - project.add_developer(user) + create(:protected_branch, :developers_can_merge, name: 'master', project: project) + end - create(:protected_branch, :developers_can_merge, - name: 'master', project: project) + context 'when user is authorized to unschedule the build' do + before do + project.add_developer(user) + sign_in(user) - sign_in(user) + post_unschedule + end - post_unschedule - end + context 'when job is scheduled' do + let(:job) { create(:ci_build, :scheduled, pipeline: pipeline) } - context 'when job is scheduled' do - let(:job) { create(:ci_build, :scheduled, pipeline: pipeline) } + it 'redirects to the unscheduled job page' do + expect(response).to have_gitlab_http_status(:found) + expect(response).to redirect_to(namespace_project_job_path(id: job.id)) + end - it 'redirects to the unscheduled job page' do - expect(response).to have_gitlab_http_status(:found) - expect(response).to redirect_to(namespace_project_job_path(id: job.id)) + it 'transits to manual' do + expect(job.reload).to be_manual + end end - it 'transits to manual' do - expect(job.reload).to be_manual + context 'when job is not scheduled' do + let(:job) { create(:ci_build, pipeline: pipeline) } + + it 'renders unprocessable_entity' do + expect(response).to have_gitlab_http_status(:unprocessable_entity) + end end end - context 'when job is not scheduled' do - let(:job) { create(:ci_build, pipeline: pipeline) } + context 'when user is not authorized to unschedule the build' do + let(:job) { create(:ci_build, :scheduled, pipeline: pipeline) } - it 'renders unprocessable_entity' do - expect(response).to have_gitlab_http_status(:unprocessable_entity) + before do + project.add_reporter(user) + sign_in(user) + + post_unschedule + end + + it 'responds with not_found' do + expect(response).to have_gitlab_http_status(:not_found) + end + + it 'does not transit to scheduled' do + expect(job.reload).not_to be_manual end end def post_unschedule - post :unschedule, params: { - namespace_id: project.namespace, - project_id: project, - id: job.id - } + post :unschedule, params: { namespace_id: project.namespace, project_id: project, id: job.id } end end diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index 84686c58a8e..d18369b8023 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -34,6 +34,7 @@ FactoryBot.define do end metrics_dashboard_access_level { ProjectFeature::PRIVATE } operations_access_level { ProjectFeature::ENABLED } + container_registry_access_level { ProjectFeature::ENABLED } # we can't assign the delegated `#ci_cd_settings` attributes directly, as the # `#ci_cd_settings` relation needs to be created first @@ -70,6 +71,17 @@ FactoryBot.define do } project.build_project_feature(hash) + + # This is not included in the `hash` above because the default_value_for in + # the ProjectFeature model overrides the value set by `build_project_feature` when + # evaluator.container_registry_access_level == ProjectFeature::DISABLED. + # + # This is because the default_value_for gem uses the <column>_changed? method + # to determine if the default value should be applied. For new records, + # <column>_changed? returns false if the value of the column is the same as + # the database default. + # See https://github.com/FooBarWidget/default_value_for/blob/release-3.4.0/lib/default_value_for.rb#L158. + project.project_feature.container_registry_access_level = evaluator.container_registry_access_level end after(:create) do |project, evaluator| @@ -344,6 +356,9 @@ FactoryBot.define do trait(:analytics_enabled) { analytics_access_level { ProjectFeature::ENABLED } } trait(:analytics_disabled) { analytics_access_level { ProjectFeature::DISABLED } } trait(:analytics_private) { analytics_access_level { ProjectFeature::PRIVATE } } + trait(:container_registry_enabled) { container_registry_access_level { ProjectFeature::ENABLED } } + trait(:container_registry_disabled) { container_registry_access_level { ProjectFeature::DISABLED } } + trait(:container_registry_private) { container_registry_access_level { ProjectFeature::PRIVATE } } trait :auto_devops do association :auto_devops, factory: :project_auto_devops diff --git a/spec/frontend/security_configuration/components/upgrade_banner_spec.js b/spec/frontend/security_configuration/components/upgrade_banner_spec.js index cf7945343af..a35fded72fb 100644 --- a/spec/frontend/security_configuration/components/upgrade_banner_spec.js +++ b/spec/frontend/security_configuration/components/upgrade_banner_spec.js @@ -43,11 +43,11 @@ describe('UpgradeBanner component', () => { it('renders the list of benefits', () => { const wrapperText = wrapper.text(); - expect(wrapperText).toContain('GitLab Ultimate checks your application'); + expect(wrapperText).toContain('Immediately begin risk analysis and remediation'); expect(wrapperText).toContain('statistics in the merge request'); expect(wrapperText).toContain('statistics across projects'); expect(wrapperText).toContain('Runtime security metrics'); - expect(wrapperText).toContain('risk analysis and remediation'); + expect(wrapperText).toContain('More scan types, including Container Scanning,'); }); it(`re-emits GlBanner's close event`, () => { diff --git a/spec/graphql/types/base_field_spec.rb b/spec/graphql/types/base_field_spec.rb index c34fbf42dd8..82efd618e38 100644 --- a/spec/graphql/types/base_field_spec.rb +++ b/spec/graphql/types/base_field_spec.rb @@ -17,7 +17,7 @@ RSpec.describe Types::BaseField do end it 'defaults to 1' do - field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, null: true) + field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true) expect(field.to_graphql.complexity).to eq 1 end @@ -25,7 +25,7 @@ RSpec.describe Types::BaseField do describe '#base_complexity' do context 'with no gitaly calls' do it 'defaults to 1' do - field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, null: true) + field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true) expect(field.base_complexity).to eq 1 end @@ -33,7 +33,7 @@ RSpec.describe Types::BaseField do context 'with a gitaly call' do it 'adds 1 to the default value' do - field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, null: true, calls_gitaly: true) + field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true, calls_gitaly: true) expect(field.base_complexity).to eq 2 end @@ -41,14 +41,14 @@ RSpec.describe Types::BaseField do end it 'has specified value' do - field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, null: true, complexity: 12) + field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true, complexity: 12) expect(field.to_graphql.complexity).to eq 12 end context 'when field has a resolver' do context 'when a valid complexity is already set' do - let(:field) { described_class.new(name: 'test', type: GraphQL::STRING_TYPE.connection_type, resolver_class: resolver, complexity: 2, max_page_size: 100, null: true) } + let(:field) { described_class.new(name: 'test', type: GraphQL::Types::String.connection_type, resolver_class: resolver, complexity: 2, max_page_size: 100, null: true) } it 'uses this complexity' do expect(field.to_graphql.complexity).to eq 2 @@ -56,7 +56,7 @@ RSpec.describe Types::BaseField do end context 'and is a connection' do - let(:field) { described_class.new(name: 'test', type: GraphQL::STRING_TYPE.connection_type, resolver_class: resolver, max_page_size: 100, null: true) } + let(:field) { described_class.new(name: 'test', type: GraphQL::Types::String.connection_type, resolver_class: resolver, max_page_size: 100, null: true) } it 'sets complexity depending on arguments for resolvers' do expect(field.to_graphql.complexity.call({}, {}, 2)).to eq 4 @@ -71,7 +71,7 @@ RSpec.describe Types::BaseField do context 'and is not a connection' do it 'sets complexity as normal' do - field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, resolver_class: resolver, max_page_size: 100, null: true) + field = described_class.new(name: 'test', type: GraphQL::Types::String, resolver_class: resolver, max_page_size: 100, null: true) expect(field.to_graphql.complexity.call({}, {}, 2)).to eq 2 expect(field.to_graphql.complexity.call({}, { first: 50 }, 2)).to eq 2 @@ -82,8 +82,8 @@ RSpec.describe Types::BaseField do context 'calls_gitaly' do context 'for fields with a resolver' do it 'adds 1 if true' do - with_gitaly_field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, resolver_class: resolver, null: true, calls_gitaly: true) - without_gitaly_field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, resolver_class: resolver, null: true) + with_gitaly_field = described_class.new(name: 'test', type: GraphQL::Types::String, resolver_class: resolver, null: true, calls_gitaly: true) + without_gitaly_field = described_class.new(name: 'test', type: GraphQL::Types::String, resolver_class: resolver, null: true) base_result = without_gitaly_field.to_graphql.complexity.call({}, {}, 2) expect(with_gitaly_field.to_graphql.complexity.call({}, {}, 2)).to eq base_result + 1 @@ -92,28 +92,28 @@ RSpec.describe Types::BaseField do context 'for fields without a resolver' do it 'adds 1 if true' do - field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, null: true, calls_gitaly: true) + field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true, calls_gitaly: true) expect(field.to_graphql.complexity).to eq 2 end end it 'defaults to false' do - field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, null: true) + field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true) expect(field.base_complexity).to eq Types::BaseField::DEFAULT_COMPLEXITY end context 'with declared constant complexity value' do it 'has complexity set to that constant' do - field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, null: true, complexity: 12) + field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true, complexity: 12) expect(field.to_graphql.complexity).to eq 12 end it 'does not raise an error even with Gitaly calls' do allow(Gitlab::GitalyClient).to receive(:get_request_count).and_return([0, 1]) - field = described_class.new(name: 'test', type: GraphQL::STRING_TYPE, null: true, complexity: 12) + field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true, complexity: 12) expect(field.to_graphql.complexity).to eq 12 end @@ -123,7 +123,7 @@ RSpec.describe Types::BaseField do describe '#visible?' do context 'and has a feature_flag' do let(:flag) { :test_feature } - let(:field) { described_class.new(name: 'test', type: GraphQL::STRING_TYPE, feature_flag: flag, null: false) } + let(:field) { described_class.new(name: 'test', type: GraphQL::Types::String, feature_flag: flag, null: false) } let(:context) { {} } before do @@ -156,7 +156,7 @@ RSpec.describe Types::BaseField do describe '#description' do context 'feature flag given' do - let(:field) { described_class.new(name: 'test', type: GraphQL::STRING_TYPE, feature_flag: flag, null: false, description: 'Test description.') } + let(:field) { described_class.new(name: 'test', type: GraphQL::Types::String, feature_flag: flag, null: false, description: 'Test description.') } let(:flag) { :test_flag } it 'prepends the description' do @@ -211,7 +211,7 @@ RSpec.describe Types::BaseField do include_examples 'Gitlab-style deprecations' do def subject(args = {}) - base_args = { name: 'test', type: GraphQL::STRING_TYPE, null: true } + base_args = { name: 'test', type: GraphQL::Types::String, null: true } described_class.new(**base_args.merge(args)) end diff --git a/spec/lib/gitlab/github_import/user_finder_spec.rb b/spec/lib/gitlab/github_import/user_finder_spec.rb index 20e67a784e1..f81fa3b1e2e 100644 --- a/spec/lib/gitlab/github_import/user_finder_spec.rb +++ b/spec/lib/gitlab/github_import/user_finder_spec.rb @@ -3,7 +3,14 @@ require 'spec_helper' RSpec.describe Gitlab::GithubImport::UserFinder, :clean_gitlab_redis_cache do - let(:project) { create(:project) } + let(:project) do + create( + :project, + import_type: 'github', + import_url: 'https://api.github.com/user/repo' + ) + end + let(:client) { double(:client) } let(:finder) { described_class.new(project, client) } @@ -263,6 +270,26 @@ RSpec.describe Gitlab::GithubImport::UserFinder, :clean_gitlab_redis_cache do finder.id_for_github_id(id) end + + context 'when importing from github enterprise' do + let(:project) do + create( + :project, + import_type: 'github', + import_url: 'https://othergithub.net/user/repo' + ) + end + + it 'does not look up the user by external id' do + expect(finder).not_to receive(:query_id_for_github_id) + + expect(Gitlab::Cache::Import::Caching) + .to receive(:write) + .with(described_class::ID_CACHE_KEY % id, nil) + + finder.id_for_github_id(id) + end + end end describe '#id_for_github_email' do diff --git a/spec/lib/gitlab/subscription_portal_spec.rb b/spec/lib/gitlab/subscription_portal_spec.rb index ed551521b1d..628eb380396 100644 --- a/spec/lib/gitlab/subscription_portal_spec.rb +++ b/spec/lib/gitlab/subscription_portal_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe ::Gitlab::SubscriptionPortal, skip: Gitlab.jh? do +RSpec.describe ::Gitlab::SubscriptionPortal do using RSpec::Parameterized::TableSyntax where(:method_name, :test, :development, :result) do diff --git a/spec/models/container_repository_spec.rb b/spec/models/container_repository_spec.rb index a53db07cc59..846dfb30928 100644 --- a/spec/models/container_repository_spec.rb +++ b/spec/models/container_repository_spec.rb @@ -323,7 +323,7 @@ RSpec.describe ContainerRepository do context 'with a subgroup' do let_it_be(:test_group) { create(:group) } let_it_be(:another_project) { create(:project, path: 'test', group: test_group) } - let_it_be(:project3) { create(:project, path: 'test3', group: test_group, container_registry_enabled: false) } + let_it_be(:project3) { create(:project, :container_registry_disabled, path: 'test3', group: test_group) } let_it_be(:another_repository) do create(:container_repository, name: 'my_image', project: another_project) diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb index ea1ce067e4d..57882b6f1b3 100644 --- a/spec/models/namespace_spec.rb +++ b/spec/models/namespace_spec.rb @@ -1152,6 +1152,68 @@ RSpec.describe Namespace do end end + context 'refreshing project access on updating share_with_group_lock' do + let(:group) { create(:group, share_with_group_lock: false) } + let(:project) { create(:project, :private, group: group) } + + let_it_be(:shared_with_group_one) { create(:group) } + let_it_be(:shared_with_group_two) { create(:group) } + let_it_be(:group_one_user) { create(:user) } + let_it_be(:group_two_user) { create(:user) } + + subject(:execute_update) { group.update!(share_with_group_lock: true) } + + before do + shared_with_group_one.add_developer(group_one_user) + shared_with_group_two.add_developer(group_two_user) + create(:project_group_link, group: shared_with_group_one, project: project) + create(:project_group_link, group: shared_with_group_two, project: project) + end + + it 'calls AuthorizedProjectUpdate::ProjectRecalculateWorker to update project authorizations' do + expect(AuthorizedProjectUpdate::ProjectRecalculateWorker) + .to receive(:perform_async).with(project.id).once + + execute_update + end + + it 'updates authorizations leading to users from shared groups losing access', :sidekiq_inline do + expect { execute_update } + .to change { group_one_user.authorized_projects.include?(project) }.from(true).to(false) + .and change { group_two_user.authorized_projects.include?(project) }.from(true).to(false) + end + + it 'calls AuthorizedProjectUpdate::UserRefreshFromReplicaWorker with a delay to update project authorizations' do + expect(AuthorizedProjectUpdate::UserRefreshFromReplicaWorker).to( + receive(:bulk_perform_in) + .with(1.hour, + [[group_one_user.id]], + batch_delay: 30.seconds, batch_size: 100) + ) + + expect(AuthorizedProjectUpdate::UserRefreshFromReplicaWorker).to( + receive(:bulk_perform_in) + .with(1.hour, + [[group_two_user.id]], + batch_delay: 30.seconds, batch_size: 100) + ) + + execute_update + end + + context 'when the feature flag `specialized_worker_for_group_lock_update_auth_recalculation` is disabled' do + before do + stub_feature_flags(specialized_worker_for_group_lock_update_auth_recalculation: false) + end + + it 'refreshes the permissions of the members of the old and new namespace' do + expect { execute_update } + .to change { group_one_user.authorized_projects.include?(project) }.from(true).to(false) + .and change { group_two_user.authorized_projects.include?(project) }.from(true).to(false) + end + end + end + describe '#share_with_group_lock with subgroups' do context 'when creating a subgroup' do let(:subgroup) { create(:group, parent: root_group )} diff --git a/spec/models/project_feature_spec.rb b/spec/models/project_feature_spec.rb index 3fd7e57a5db..0ef5a2046ba 100644 --- a/spec/models/project_feature_spec.rb +++ b/spec/models/project_feature_spec.rb @@ -189,27 +189,33 @@ RSpec.describe ProjectFeature do end describe 'container_registry_access_level' do - context 'when the project is created with container_registry_enabled false' do - it 'creates project with DISABLED container_registry_access_level' do - project = create(:project, container_registry_enabled: false) + context 'with default value' do + let(:project) { Project.new } - expect(project.project_feature.container_registry_access_level).to eq(described_class::DISABLED) + context 'when the default is false' do + it 'creates project_feature with `disabled` container_registry_access_level' do + stub_config_setting(default_projects_features: { container_registry: false }) + + expect(project.project_feature.container_registry_access_level).to eq(described_class::DISABLED) + end end - end - context 'when the project is created with container_registry_enabled true' do - it 'creates project with ENABLED container_registry_access_level' do - project = create(:project, container_registry_enabled: true) + context 'when the default is true' do + before do + stub_config_setting(default_projects_features: { container_registry: true }) + end - expect(project.project_feature.container_registry_access_level).to eq(described_class::ENABLED) + it 'creates project_feature with `enabled` container_registry_access_level' do + expect(project.project_feature.container_registry_access_level).to eq(described_class::ENABLED) + end end - end - context 'when the project is created with container_registry_enabled nil' do - it 'creates project with DISABLED container_registry_access_level' do - project = create(:project, container_registry_enabled: nil) + context 'when the default is nil' do + it 'creates project_feature with `disabled` container_registry_access_level' do + stub_config_setting(default_projects_features: { container_registry: nil }) - expect(project.project_feature.container_registry_access_level).to eq(described_class::DISABLED) + expect(project.project_feature.container_registry_access_level).to eq(described_class::DISABLED) + end end end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index ec99e094a03..6aade778724 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -2407,7 +2407,7 @@ RSpec.describe Project, factory_default: :keep do end end - describe '#set_container_registry_access_level' do + describe '#container_registry_enabled=' do let_it_be_with_reload(:project) { create(:project) } it 'updates project_feature', :aggregate_failures do @@ -2872,6 +2872,36 @@ RSpec.describe Project, factory_default: :keep do it { expect(project.import?).to be true } end + describe '#github_import?' do + let_it_be(:project) { build(:project, import_type: 'github') } + + it { expect(project.github_import?).to be true } + end + + describe '#github_enterprise_import?' do + let_it_be(:github_com_project) do + build( + :project, + import_type: 'github', + import_url: 'https://api.github.com/user/repo' + ) + end + + let_it_be(:github_enterprise_project) do + build( + :project, + import_type: 'github', + import_url: 'https://othergithub.net/user/repo' + ) + end + + it { expect(github_com_project.github_import?).to be true } + it { expect(github_com_project.github_enterprise_import?).to be false } + + it { expect(github_enterprise_project.github_import?).to be true } + it { expect(github_enterprise_project.github_enterprise_import?).to be true } + end + describe '#remove_import_data' do let(:import_data) { ProjectImportData.new(data: { 'test' => 'some data' }) } diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb index ce75e68de32..8cc70a30794 100644 --- a/spec/models/project_team_spec.rb +++ b/spec/models/project_team_spec.rb @@ -307,7 +307,7 @@ RSpec.describe ProjectTeam do it { expect(project.team.max_member_access(nonmember.id)).to eq(Gitlab::Access::NO_ACCESS) } it { expect(project.team.max_member_access(requester.id)).to eq(Gitlab::Access::NO_ACCESS) } - context 'but share_with_group_lock is true' do + context 'but share_with_group_lock is true', :sidekiq_inline do before do project.namespace.update!(share_with_group_lock: true) end diff --git a/spec/services/ci/build_cancel_service_spec.rb b/spec/services/ci/build_cancel_service_spec.rb new file mode 100644 index 00000000000..fe036dc1368 --- /dev/null +++ b/spec/services/ci/build_cancel_service_spec.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Ci::BuildCancelService do + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project) } + let_it_be(:pipeline) { create(:ci_pipeline, project: project) } + + describe '#execute' do + subject(:execute) { described_class.new(build, user).execute } + + context 'when user is authorized to cancel the build' do + before do + project.add_maintainer(user) + end + + context 'when build is cancelable' do + let!(:build) { create(:ci_build, :cancelable, pipeline: pipeline) } + + it 'transits build to canceled', :aggregate_failures do + response = execute + + expect(response).to be_success + expect(response.payload.reload).to be_canceled + end + end + + context 'when build is not cancelable' do + let!(:build) { create(:ci_build, :canceled, pipeline: pipeline) } + + it 'responds with unprocessable entity', :aggregate_failures do + response = execute + + expect(response).to be_error + expect(response.http_status).to eq(:unprocessable_entity) + end + end + end + + context 'when user is not authorized to cancel the build' do + let!(:build) { create(:ci_build, :cancelable, pipeline: pipeline) } + + it 'responds with forbidden', :aggregate_failures do + response = execute + + expect(response).to be_error + expect(response.http_status).to eq(:forbidden) + end + end + end +end diff --git a/spec/services/ci/build_unschedule_service_spec.rb b/spec/services/ci/build_unschedule_service_spec.rb new file mode 100644 index 00000000000..d784d9a2754 --- /dev/null +++ b/spec/services/ci/build_unschedule_service_spec.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Ci::BuildUnscheduleService do + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project) } + let_it_be(:pipeline) { create(:ci_pipeline, project: project) } + + describe '#execute' do + subject(:execute) { described_class.new(build, user).execute } + + context 'when user is authorized to unschedule the build' do + before do + project.add_maintainer(user) + end + + context 'when build is scheduled' do + let!(:build) { create(:ci_build, :scheduled, pipeline: pipeline) } + + it 'transits build to manual' do + response = execute + + expect(response).to be_success + expect(response.payload.reload).to be_manual + end + end + + context 'when build is not scheduled' do + let!(:build) { create(:ci_build, pipeline: pipeline) } + + it 'responds with unprocessable entity', :aggregate_failures do + response = execute + + expect(response).to be_error + expect(response.http_status).to eq(:unprocessable_entity) + end + end + end + + context 'when user is not authorized to unschedule the build' do + let!(:build) { create(:ci_build, :scheduled, pipeline: pipeline) } + + it 'responds with forbidden', :aggregate_failures do + response = execute + + expect(response).to be_error + expect(response.http_status).to eq(:forbidden) + end + end + end +end diff --git a/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb b/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb index 506124216af..fdba67638c1 100644 --- a/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb +++ b/spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb @@ -25,6 +25,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do expect(ContainerExpirationPolicies::CleanupService) .to receive(:new).with(repository).and_return(double(execute: service_response)) expect_log_extra_metadata(service_response: service_response) + expect_log_info(project_id: project.id, container_repository_id: repository.id) subject end @@ -35,6 +36,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do expect(ContainerExpirationPolicies::CleanupService) .to receive(:new).with(repository).and_return(double(execute: service_response)) expect_log_extra_metadata(service_response: service_response, cleanup_status: :unfinished) + expect_log_info(project_id: project.id, container_repository_id: repository.id) subject end @@ -45,6 +47,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do expect(ContainerExpirationPolicies::CleanupService) .to receive(:new).with(repository).and_return(double(execute: service_response)) expect_log_extra_metadata(service_response: service_response, cleanup_status: :unfinished, truncated: true) + expect_log_info(project_id: project.id, container_repository_id: repository.id) subject end @@ -65,6 +68,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do expect(ContainerExpirationPolicies::CleanupService) .to receive(:new).with(repository).and_return(double(execute: service_response)) expect_log_extra_metadata(service_response: service_response, cleanup_status: :unfinished, truncated: truncated) + expect_log_info(project_id: project.id, container_repository_id: repository.id) subject end @@ -78,6 +82,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do expect(ContainerExpirationPolicies::CleanupService) .to receive(:new).with(repository).and_return(double(execute: service_response)) expect_log_extra_metadata(service_response: service_response, cleanup_status: :error) + expect_log_info(project_id: project.id, container_repository_id: repository.id) subject end @@ -361,6 +366,7 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do expect(ContainerExpirationPolicies::CleanupService) .to receive(:new).with(repository).and_return(double(execute: service_response)) expect_log_extra_metadata(service_response: service_response) + expect_log_info(project_id: project.id, container_repository_id: repository.id) subject end @@ -396,6 +402,11 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do expect(worker).to receive(:log_extra_metadata_on_done).with(:cleanup_error_message, service_response.message) end end + + def expect_log_info(structure) + expect(worker.logger) + .to receive(:info).with(worker.structured_payload(structure)) + end end describe '#remaining_work_count' do @@ -446,6 +457,12 @@ RSpec.describe ContainerExpirationPolicies::CleanupContainerRepositoryWorker do end it { is_expected.to eq(0) } + + it 'does not log a selected container' do + expect(worker).not_to receive(:log_info) + + subject + end end end |