Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
66db8363ac
commit
80aae84337
|
|
@ -213,7 +213,6 @@ variables:
|
|||
RSPEC_CHANGED_FILES_PATH: rspec/changed_files.txt
|
||||
RSPEC_FAIL_FAST_THRESHOLD: 20
|
||||
RSPEC_FAST_QUARANTINE_PATH: rspec/fast_quarantine-gitlab.txt
|
||||
RSPEC_FOSS_IMPACT_PIPELINE_TEMPLATE_YML: .gitlab/ci/rails/rspec-foss-impact.gitlab-ci.yml.erb
|
||||
RSPEC_LAST_RUN_RESULTS_FILE: rspec/rspec_last_run_results.txt
|
||||
RSPEC_MATCHING_JS_FILES_PATH: rspec/js_matching_files.txt
|
||||
RSPEC_MATCHING_TESTS_EE_PATH: rspec/matching_tests-ee.txt
|
||||
|
|
|
|||
|
|
@ -95,6 +95,10 @@ start-as-if-foss:
|
|||
ENABLE_GRAPHQL_SCHEMA_DUMP: $ENABLE_GRAPHQL_SCHEMA_DUMP
|
||||
ENABLE_JEST: $ENABLE_JEST
|
||||
ENABLE_JEST_INTEGRATION: $ENABLE_JEST_INTEGRATION
|
||||
ENABLE_RSPEC_PREDICTIVE_PIPELINE_GENERATE: $ENABLE_RSPEC_PREDICTIVE_PIPELINE_GENERATE
|
||||
ENABLE_RSPEC_PREDICTIVE_TRIGGER: $ENABLE_RSPEC_PREDICTIVE_TRIGGER
|
||||
ENABLE_RSPEC_PREDICTIVE_TRIGGER_SINGLE_DB: $ENABLE_RSPEC_PREDICTIVE_TRIGGER_SINGLE_DB
|
||||
ENABLE_RSPEC_PREDICTIVE_TRIGGER_SINGLE_DB_CI_CONNECTION: $ENABLE_RSPEC_PREDICTIVE_TRIGGER_SINGLE_DB_CI_CONNECTION
|
||||
ENABLE_RUBOCOP: $ENABLE_RUBOCOP
|
||||
ENABLE_QA_INTERNAL: $ENABLE_QA_INTERNAL
|
||||
ENABLE_QA_SELECTORS: $ENABLE_QA_SELECTORS
|
||||
|
|
|
|||
|
|
@ -1290,44 +1290,6 @@ rspec-ee fail-fast:
|
|||
variables:
|
||||
MATCHING_TESTS_PATH: "${RSPEC_MATCHING_TESTS_EE_PATH}"
|
||||
|
||||
rspec-foss-impact:pipeline-generate:
|
||||
extends:
|
||||
- .rails:rules:rspec-foss-impact
|
||||
stage: prepare
|
||||
needs: ["detect-tests", "retrieve-tests-metadata"]
|
||||
script:
|
||||
- scripts/generate_rspec_pipeline.rb -f "${RSPEC_MATCHING_TESTS_FOSS_PATH}" -t "${RSPEC_FOSS_IMPACT_PIPELINE_TEMPLATE_YML}" -k "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}"
|
||||
- cat "${RSPEC_FOSS_IMPACT_PIPELINE_TEMPLATE_YML}.yml"
|
||||
artifacts:
|
||||
expire_in: 1 day
|
||||
paths:
|
||||
- "${RSPEC_FOSS_IMPACT_PIPELINE_TEMPLATE_YML}.yml"
|
||||
|
||||
rspec-foss-impact:trigger:
|
||||
extends:
|
||||
- .rails:rules:rspec-foss-impact
|
||||
stage: test
|
||||
needs:
|
||||
- job: "setup-test-env"
|
||||
artifacts: false
|
||||
- job: "retrieve-tests-metadata"
|
||||
artifacts: false
|
||||
- job: "compile-test-assets as-if-foss"
|
||||
artifacts: false
|
||||
- job: "rspec-foss-impact:pipeline-generate"
|
||||
artifacts: true
|
||||
variables:
|
||||
PARENT_PIPELINE_ID: $CI_PIPELINE_ID
|
||||
GIT_STRATEGY: $GIT_STRATEGY
|
||||
trigger:
|
||||
strategy: depend
|
||||
forward:
|
||||
yaml_variables: true
|
||||
pipeline_variables: true
|
||||
include:
|
||||
- artifact: "${RSPEC_FOSS_IMPACT_PIPELINE_TEMPLATE_YML}.yml"
|
||||
job: rspec-foss-impact:pipeline-generate
|
||||
|
||||
fail-pipeline-early:
|
||||
extends:
|
||||
- .rails:rules:fail-pipeline-early
|
||||
|
|
|
|||
|
|
@ -1,89 +0,0 @@
|
|||
# RSpec FOSS impact pipeline loaded dynamically by script: scripts/generate_rspec_pipeline.rb
|
||||
|
||||
include:
|
||||
- local: .gitlab/ci/rails/shared.gitlab-ci.yml
|
||||
|
||||
default:
|
||||
image: $DEFAULT_CI_IMAGE
|
||||
tags:
|
||||
- gitlab-org
|
||||
# Default job timeout set to 90m https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/10520
|
||||
timeout: 90m
|
||||
interruptible: true
|
||||
|
||||
stages:
|
||||
- test
|
||||
|
||||
dont-interrupt-me:
|
||||
extends: .rules:dont-interrupt
|
||||
stage: .pre
|
||||
interruptible: false
|
||||
script:
|
||||
- echo "This jobs makes sure this pipeline won't be interrupted! See https://docs.gitlab.com/ee/ci/yaml/#interruptible."
|
||||
|
||||
.base-rspec-foss-impact:
|
||||
extends: .rspec-base-pg14-as-if-foss
|
||||
needs:
|
||||
<% if repo_from_artifacts %>
|
||||
- pipeline: $PARENT_PIPELINE_ID
|
||||
job: clone-gitlab-repo
|
||||
<% end %>
|
||||
- pipeline: $PARENT_PIPELINE_ID
|
||||
job: detect-tests
|
||||
- pipeline: $PARENT_PIPELINE_ID
|
||||
job: setup-test-env
|
||||
- pipeline: $PARENT_PIPELINE_ID
|
||||
job: retrieve-tests-metadata
|
||||
- pipeline: $PARENT_PIPELINE_ID
|
||||
job: compile-test-assets as-if-foss
|
||||
rules:
|
||||
- when: always
|
||||
variables:
|
||||
RSPEC_TESTS_FILTER_FILE: "${RSPEC_MATCHING_TESTS_FOSS_PATH}"
|
||||
RSPEC_TESTS_MAPPING_ENABLED: "true"
|
||||
script:
|
||||
- !reference [.base-script, script]
|
||||
- rspec_parallelized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~level:background_migration --tag ~zoekt --tag ~click_house"
|
||||
|
||||
<% if rspec_files_per_test_level[:migration][:files].size > 0 %>
|
||||
rspec migration foss-impact:
|
||||
extends: .base-rspec-foss-impact
|
||||
<% if rspec_files_per_test_level[:migration][:parallelization] > 1 %>
|
||||
parallel: <%= rspec_files_per_test_level[:migration][:parallelization] %>
|
||||
<% end %>
|
||||
script:
|
||||
- !reference [.base-script, script]
|
||||
- rspec_parallelized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~zoekt --tag ~click_house"
|
||||
<% end %>
|
||||
|
||||
<% if rspec_files_per_test_level[:background_migration][:files].size > 0 %>
|
||||
rspec background_migration foss-impact:
|
||||
extends: .base-rspec-foss-impact
|
||||
<% if rspec_files_per_test_level[:background_migration][:parallelization] > 1 %>
|
||||
parallel: <%= rspec_files_per_test_level[:background_migration][:parallelization] %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% if rspec_files_per_test_level[:unit][:files].size > 0 %>
|
||||
rspec unit foss-impact:
|
||||
extends: .base-rspec-foss-impact
|
||||
<% if rspec_files_per_test_level[:unit][:parallelization] > 1 %>
|
||||
parallel: <%= rspec_files_per_test_level[:unit][:parallelization] %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% if rspec_files_per_test_level[:integration][:files].size > 0 %>
|
||||
rspec integration foss-impact:
|
||||
extends: .base-rspec-foss-impact
|
||||
<% if rspec_files_per_test_level[:integration][:parallelization] > 1 %>
|
||||
parallel: <%= rspec_files_per_test_level[:integration][:parallelization] %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% if rspec_files_per_test_level[:system][:files].size > 0 %>
|
||||
rspec system foss-impact:
|
||||
extends: .base-rspec-foss-impact
|
||||
<% if rspec_files_per_test_level[:system][:parallelization] > 1 %>
|
||||
parallel: <%= rspec_files_per_test_level[:system][:parallelization] %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
@ -2056,6 +2056,7 @@
|
|||
changes: *code-backstage-patterns
|
||||
- <<: *if-merge-request-labels-pipeline-expedite
|
||||
when: never
|
||||
- if: '$ENABLE_RSPEC_PREDICTIVE_PIPELINE_GENERATE == "true"'
|
||||
- <<: *if-merge-request
|
||||
changes: *db-patterns
|
||||
- <<: *if-merge-request
|
||||
|
|
@ -2085,6 +2086,7 @@
|
|||
changes: *code-backstage-patterns
|
||||
- <<: *if-merge-request-labels-pipeline-expedite
|
||||
when: never
|
||||
- if: '$ENABLE_RSPEC_PREDICTIVE_TRIGGER == "true"'
|
||||
- <<: *if-merge-request-labels-run-all-rspec
|
||||
when: never
|
||||
- <<: *if-merge-request
|
||||
|
|
@ -2112,6 +2114,7 @@
|
|||
when: never
|
||||
- <<: *if-merge-request-labels-pipeline-expedite
|
||||
when: never
|
||||
- if: '$ENABLE_RSPEC_PREDICTIVE_TRIGGER_SINGLE_DB == "true"'
|
||||
- <<: *if-merge-request-approved
|
||||
when: never
|
||||
- <<: *if-merge-request
|
||||
|
|
@ -2130,6 +2133,7 @@
|
|||
when: never
|
||||
- <<: *if-merge-request-labels-pipeline-expedite
|
||||
when: never
|
||||
- if: '$ENABLE_RSPEC_PREDICTIVE_TRIGGER_SINGLE_DB_CI_CONNECTION == "true"'
|
||||
- <<: *if-merge-request-approved
|
||||
when: never
|
||||
- <<: *if-merge-request
|
||||
|
|
@ -2371,19 +2375,6 @@
|
|||
rules:
|
||||
- !reference [".rails:rules:previous-failed-tests-default-rules", rules]
|
||||
|
||||
.rails:rules:rspec-foss-impact:
|
||||
rules:
|
||||
- <<: *if-not-ee
|
||||
when: never
|
||||
- <<: *if-merge-request-labels-as-if-foss
|
||||
when: never
|
||||
- <<: *if-merge-request-labels-pipeline-expedite
|
||||
when: never
|
||||
- <<: *if-security-merge-request
|
||||
changes: *code-backstage-patterns
|
||||
- <<: *if-dot-com-gitlab-org-merge-request
|
||||
changes: *code-backstage-patterns
|
||||
|
||||
.rails:rules:rspec fail-fast:
|
||||
rules:
|
||||
- <<: *if-not-ee
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ rubocop:
|
|||
script:
|
||||
- |
|
||||
# For non-merge request, or when RUN_ALL_RUBOCOP is 'true', run all RuboCop rules
|
||||
if [ -z "${CI_MERGE_REQUEST_IID}" ] || [ "${RUN_ALL_RUBOCOP}" == "true" ]; then
|
||||
if [ -z "${CI_MERGE_REQUEST_IID:-$FIND_CHANGES_MERGE_REQUEST_IID}" ] || [ "${RUN_ALL_RUBOCOP}" == "true" ]; then
|
||||
# Silence cop offenses for rules with "grace period".
|
||||
# We won't notify Slack if offenses were silenced to avoid frequent messages.
|
||||
# Job `update-static-analysis-cache` takes care of Slack notifications every 2 hours.
|
||||
|
|
|
|||
|
|
@ -345,22 +345,6 @@ Layout/ArgumentAlignment:
|
|||
- 'app/graphql/types/release_type.rb'
|
||||
- 'app/graphql/types/repository/blob_type.rb'
|
||||
- 'app/graphql/types/repository_type.rb'
|
||||
- 'app/graphql/types/resolvable_interface.rb'
|
||||
- 'app/graphql/types/saved_reply_type.rb'
|
||||
- 'app/graphql/types/security/report_type_enum.rb'
|
||||
- 'app/graphql/types/sha_format_enum.rb'
|
||||
- 'app/graphql/types/snippet_type.rb'
|
||||
- 'app/graphql/types/snippets/blob_action_input_type.rb'
|
||||
- 'app/graphql/types/snippets/blob_connection_type.rb'
|
||||
- 'app/graphql/types/snippets/blob_type.rb'
|
||||
- 'app/graphql/types/sort_enum.rb'
|
||||
- 'app/graphql/types/task_completion_status.rb'
|
||||
- 'app/graphql/types/terraform/state_type.rb'
|
||||
- 'app/graphql/types/terraform/state_version_type.rb'
|
||||
- 'app/graphql/types/time_tracking/timelog_category_type.rb'
|
||||
- 'app/graphql/types/time_tracking/timelog_connection_type.rb'
|
||||
- 'app/graphql/types/timelog_type.rb'
|
||||
- 'app/graphql/types/todo_type.rb'
|
||||
- 'app/graphql/types/tree/blob_type.rb'
|
||||
- 'app/graphql/types/tree/entry_type.rb'
|
||||
- 'app/graphql/types/tree/submodule_type.rb'
|
||||
|
|
|
|||
|
|
@ -121,8 +121,11 @@ function handleAttributeFilter(filterValue, filterOperator, searchParams, namePa
|
|||
function addDateRangeFilterToQueryParams(dateRangeFilter, params) {
|
||||
if (!dateRangeFilter || !params) return;
|
||||
|
||||
const { value, endDate, startDate } = dateRangeFilter;
|
||||
if (value === CUSTOM_DATE_RANGE_OPTION) {
|
||||
const { value, endDate, startDate, timestamp } = dateRangeFilter;
|
||||
if (timestamp) {
|
||||
params.append('start_time', timestamp);
|
||||
params.append('end_time', timestamp);
|
||||
} else if (value === CUSTOM_DATE_RANGE_OPTION) {
|
||||
if (isValidDate(startDate) && isValidDate(endDate)) {
|
||||
params.append('start_time', startDate.toISOString());
|
||||
params.append('end_time', endDate.toISOString());
|
||||
|
|
|
|||
|
|
@ -49,5 +49,6 @@ export const CUSTOM_DATE_RANGE_OPTION = 'custom';
|
|||
export const DATE_RANGE_QUERY_KEY = 'date_range';
|
||||
export const DATE_RANGE_START_QUERY_KEY = 'date_start';
|
||||
export const DATE_RANGE_END_QUERY_KEY = 'date_end';
|
||||
export const TIMESTAMP_QUERY_KEY = 'timestamp';
|
||||
|
||||
export const FILTERED_SEARCH_TERM_QUERY_KEY = 'search';
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import {
|
|||
DATE_RANGE_QUERY_KEY,
|
||||
DATE_RANGE_START_QUERY_KEY,
|
||||
DATE_RANGE_END_QUERY_KEY,
|
||||
TIMESTAMP_QUERY_KEY,
|
||||
} from './constants';
|
||||
|
||||
/**
|
||||
|
|
@ -83,8 +84,18 @@ export function queryToDateFilterObj(queryObj) {
|
|||
[DATE_RANGE_QUERY_KEY]: dateRangeValue,
|
||||
[DATE_RANGE_START_QUERY_KEY]: dateRangeStart,
|
||||
[DATE_RANGE_END_QUERY_KEY]: dateRangeEnd,
|
||||
[TIMESTAMP_QUERY_KEY]: timestamp,
|
||||
} = queryObj;
|
||||
|
||||
if (timestamp) {
|
||||
return {
|
||||
value: CUSTOM_DATE_RANGE_OPTION,
|
||||
startDate: new Date(timestamp),
|
||||
endDate: new Date(timestamp),
|
||||
timestamp,
|
||||
};
|
||||
}
|
||||
|
||||
return validatedDateRangeQuery(dateRangeValue, dateRangeStart, dateRangeEnd);
|
||||
}
|
||||
|
||||
|
|
@ -109,5 +120,6 @@ export function dateFilterObjToQuery(dateFilter = {}) {
|
|||
[DATE_RANGE_START_QUERY_KEY]: undefined,
|
||||
[DATE_RANGE_END_QUERY_KEY]: undefined,
|
||||
}),
|
||||
[TIMESTAMP_QUERY_KEY]: dateFilter.timestamp,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ module Types
|
|||
include Types::BaseInterface
|
||||
|
||||
field :resolved_by, Types::UserType,
|
||||
null: true,
|
||||
description: 'User who resolved the object.'
|
||||
null: true,
|
||||
description: 'User who resolved the object.'
|
||||
|
||||
def resolved_by
|
||||
return unless object.resolved_by_id
|
||||
|
|
@ -17,12 +17,12 @@ module Types
|
|||
end
|
||||
|
||||
field :resolved, GraphQL::Types::Boolean, null: false,
|
||||
description: 'Indicates if the object is resolved.',
|
||||
method: :resolved?
|
||||
description: 'Indicates if the object is resolved.',
|
||||
method: :resolved?
|
||||
field :resolvable, GraphQL::Types::Boolean, null: false,
|
||||
description: 'Indicates if the object can be resolved.',
|
||||
method: :resolvable?
|
||||
description: 'Indicates if the object can be resolved.',
|
||||
method: :resolvable?
|
||||
field :resolved_at, Types::TimeType, null: true,
|
||||
description: 'Timestamp of when the object was resolved.'
|
||||
description: 'Timestamp of when the object was resolved.'
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ module Types
|
|||
authorize :read_saved_replies
|
||||
|
||||
field :content, GraphQL::Types::String,
|
||||
null: false,
|
||||
description: 'Content of the saved reply.'
|
||||
null: false,
|
||||
description: 'Content of the saved reply.'
|
||||
|
||||
field :name, GraphQL::Types::String,
|
||||
null: false,
|
||||
description: 'Name of the saved reply.'
|
||||
null: false,
|
||||
description: 'Name of the saved reply.'
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ module Types
|
|||
|
||||
::Security::SecurityJobsFinder.allowed_job_types.each do |report_type|
|
||||
value report_type.upcase,
|
||||
value: report_type,
|
||||
description: "#{report_type.upcase.to_s.tr('_', ' ')} scan report"
|
||||
value: report_type,
|
||||
description: "#{report_type.upcase.to_s.tr('_', ' ')} scan report"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ module Types
|
|||
|
||||
FORMATS_DESCRIPTION.each do |format, description|
|
||||
value format.to_s.upcase,
|
||||
description: description,
|
||||
value: format.to_s
|
||||
description: description,
|
||||
value: format.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -14,73 +14,73 @@ module Types
|
|||
expose_permissions Types::PermissionTypes::Snippet
|
||||
|
||||
field :id, Types::GlobalIDType[::Snippet],
|
||||
description: 'ID of the snippet.',
|
||||
null: false
|
||||
description: 'ID of the snippet.',
|
||||
null: false
|
||||
|
||||
field :title, GraphQL::Types::String,
|
||||
description: 'Title of the snippet.',
|
||||
null: false
|
||||
description: 'Title of the snippet.',
|
||||
null: false
|
||||
|
||||
field :project, Types::ProjectType,
|
||||
description: 'Project the snippet is associated with.',
|
||||
null: true,
|
||||
authorize: :read_project
|
||||
description: 'Project the snippet is associated with.',
|
||||
null: true,
|
||||
authorize: :read_project
|
||||
|
||||
# Author can be nil in some scenarios. For example,
|
||||
# when the admin setting restricted visibility
|
||||
# level is set to public
|
||||
field :author, Types::UserType,
|
||||
description: 'Owner of the snippet.',
|
||||
null: true
|
||||
description: 'Owner of the snippet.',
|
||||
null: true
|
||||
|
||||
field :file_name, GraphQL::Types::String,
|
||||
description: 'File Name of the snippet.',
|
||||
null: true
|
||||
description: 'File Name of the snippet.',
|
||||
null: true
|
||||
|
||||
field :description, GraphQL::Types::String,
|
||||
description: 'Description of the snippet.',
|
||||
null: true
|
||||
description: 'Description of the snippet.',
|
||||
null: true
|
||||
|
||||
field :visibility_level, Types::VisibilityLevelsEnum,
|
||||
description: 'Visibility Level of the snippet.',
|
||||
null: false
|
||||
description: 'Visibility Level of the snippet.',
|
||||
null: false
|
||||
|
||||
field :hidden, GraphQL::Types::Boolean,
|
||||
description: 'Indicates the snippet is hidden because the author has been banned.',
|
||||
null: false,
|
||||
method: :hidden_due_to_author_ban?
|
||||
description: 'Indicates the snippet is hidden because the author has been banned.',
|
||||
null: false,
|
||||
method: :hidden_due_to_author_ban?
|
||||
|
||||
field :created_at, Types::TimeType,
|
||||
description: 'Timestamp this snippet was created.',
|
||||
null: false
|
||||
description: 'Timestamp this snippet was created.',
|
||||
null: false
|
||||
|
||||
field :updated_at, Types::TimeType,
|
||||
description: 'Timestamp this snippet was updated.',
|
||||
null: false
|
||||
description: 'Timestamp this snippet was updated.',
|
||||
null: false
|
||||
|
||||
field :web_url, type: GraphQL::Types::String,
|
||||
description: 'Web URL of the snippet.',
|
||||
null: false
|
||||
description: 'Web URL of the snippet.',
|
||||
null: false
|
||||
|
||||
field :raw_url, type: GraphQL::Types::String,
|
||||
description: 'Raw URL of the snippet.',
|
||||
null: false
|
||||
description: 'Raw URL of the snippet.',
|
||||
null: false
|
||||
|
||||
field :blobs, type: Types::Snippets::BlobType.connection_type,
|
||||
description: 'Snippet blobs.',
|
||||
calls_gitaly: true,
|
||||
null: true,
|
||||
resolver: Resolvers::Snippets::BlobsResolver
|
||||
description: 'Snippet blobs.',
|
||||
calls_gitaly: true,
|
||||
null: true,
|
||||
resolver: Resolvers::Snippets::BlobsResolver
|
||||
|
||||
field :ssh_url_to_repo, type: GraphQL::Types::String,
|
||||
description: 'SSH URL to the snippet repository.',
|
||||
calls_gitaly: true,
|
||||
null: true
|
||||
description: 'SSH URL to the snippet repository.',
|
||||
calls_gitaly: true,
|
||||
null: true
|
||||
|
||||
field :http_url_to_repo, type: GraphQL::Types::String,
|
||||
description: 'HTTP URL to the snippet repository.',
|
||||
calls_gitaly: true,
|
||||
null: true
|
||||
description: 'HTTP URL to the snippet repository.',
|
||||
calls_gitaly: true,
|
||||
null: true
|
||||
|
||||
markdown_field :description_html, null: true, method: :description
|
||||
|
||||
|
|
|
|||
|
|
@ -7,20 +7,20 @@ module Types
|
|||
description 'Represents an action to perform over a snippet file'
|
||||
|
||||
argument :action, Types::Snippets::BlobActionEnum,
|
||||
description: 'Type of input action.',
|
||||
required: true
|
||||
description: 'Type of input action.',
|
||||
required: true
|
||||
|
||||
argument :previous_path, GraphQL::Types::String,
|
||||
description: 'Previous path of the snippet file.',
|
||||
required: false
|
||||
description: 'Previous path of the snippet file.',
|
||||
required: false
|
||||
|
||||
argument :file_path, GraphQL::Types::String,
|
||||
description: 'Path of the snippet file.',
|
||||
required: true
|
||||
description: 'Path of the snippet file.',
|
||||
required: true
|
||||
|
||||
argument :content, GraphQL::Types::String,
|
||||
description: 'Snippet file content.',
|
||||
required: false
|
||||
description: 'Snippet file content.',
|
||||
required: false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ module Types
|
|||
# rubocop: disable Graphql/AuthorizeTypes
|
||||
class BlobConnectionType < GraphQL::Types::Relay::BaseConnection
|
||||
field :has_unretrievable_blobs,
|
||||
GraphQL::Types::Boolean,
|
||||
null: false,
|
||||
description: 'Indicates if the snippet has unretrievable blobs.',
|
||||
resolver_method: :unretrievable_blobs?
|
||||
GraphQL::Types::Boolean,
|
||||
null: false,
|
||||
description: 'Indicates if the snippet has unretrievable blobs.',
|
||||
resolver_method: :unretrievable_blobs?
|
||||
|
||||
def unretrievable_blobs?
|
||||
!!context[:unretrievable_blobs?]
|
||||
|
|
|
|||
|
|
@ -11,58 +11,58 @@ module Types
|
|||
connection_type_class Types::Snippets::BlobConnectionType
|
||||
|
||||
field :rich_data, GraphQL::Types::String,
|
||||
description: 'Blob highlighted data.',
|
||||
null: true
|
||||
description: 'Blob highlighted data.',
|
||||
null: true
|
||||
|
||||
field :plain_data, GraphQL::Types::String,
|
||||
description: 'Blob plain highlighted data.',
|
||||
null: true
|
||||
description: 'Blob plain highlighted data.',
|
||||
null: true
|
||||
|
||||
field :raw_plain_data, GraphQL::Types::String,
|
||||
description: 'Raw content of the blob, if the blob is text data.',
|
||||
null: true
|
||||
description: 'Raw content of the blob, if the blob is text data.',
|
||||
null: true
|
||||
|
||||
field :raw_path, GraphQL::Types::String,
|
||||
description: 'Blob raw content endpoint path.',
|
||||
null: false
|
||||
description: 'Blob raw content endpoint path.',
|
||||
null: false
|
||||
|
||||
field :size, GraphQL::Types::Int,
|
||||
description: 'Blob size.',
|
||||
null: false
|
||||
description: 'Blob size.',
|
||||
null: false
|
||||
|
||||
field :binary, GraphQL::Types::Boolean,
|
||||
description: 'Shows whether the blob is binary.',
|
||||
method: :binary?,
|
||||
null: false
|
||||
description: 'Shows whether the blob is binary.',
|
||||
method: :binary?,
|
||||
null: false
|
||||
|
||||
field :name, GraphQL::Types::String,
|
||||
description: 'Blob name.',
|
||||
null: true
|
||||
description: 'Blob name.',
|
||||
null: true
|
||||
|
||||
field :path, GraphQL::Types::String,
|
||||
description: 'Blob path.',
|
||||
null: true
|
||||
description: 'Blob path.',
|
||||
null: true
|
||||
|
||||
field :simple_viewer, type: Types::Snippets::BlobViewerType,
|
||||
description: 'Blob content simple viewer.',
|
||||
null: false
|
||||
description: 'Blob content simple viewer.',
|
||||
null: false
|
||||
|
||||
field :rich_viewer, type: Types::Snippets::BlobViewerType,
|
||||
description: 'Blob content rich viewer.',
|
||||
null: true
|
||||
description: 'Blob content rich viewer.',
|
||||
null: true
|
||||
|
||||
field :mode, type: GraphQL::Types::String,
|
||||
description: 'Blob mode.',
|
||||
null: true
|
||||
description: 'Blob mode.',
|
||||
null: true
|
||||
|
||||
field :external_storage, type: GraphQL::Types::String,
|
||||
description: 'Blob external storage.',
|
||||
null: true
|
||||
description: 'Blob external storage.',
|
||||
null: true
|
||||
|
||||
field :rendered_as_text, type: GraphQL::Types::Boolean,
|
||||
description: 'Shows whether the blob is rendered as text.',
|
||||
method: :rendered_as_text?,
|
||||
null: false
|
||||
description: 'Shows whether the blob is rendered as text.',
|
||||
method: :rendered_as_text?,
|
||||
null: false
|
||||
end
|
||||
# rubocop: enable Graphql/AuthorizeTypes
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,33 +8,33 @@ module Types
|
|||
# Deprecated, as we prefer uppercase enums
|
||||
# https://gitlab.com/groups/gitlab-org/-/epics/1838
|
||||
value 'updated_desc', 'Updated at descending order.',
|
||||
value: :updated_desc,
|
||||
deprecated: {
|
||||
reason: :renamed,
|
||||
replacement: 'UPDATED_DESC',
|
||||
milestone: '13.5'
|
||||
}
|
||||
value: :updated_desc,
|
||||
deprecated: {
|
||||
reason: :renamed,
|
||||
replacement: 'UPDATED_DESC',
|
||||
milestone: '13.5'
|
||||
}
|
||||
value 'updated_asc', 'Updated at ascending order.',
|
||||
value: :updated_asc,
|
||||
deprecated: {
|
||||
reason: :renamed,
|
||||
replacement: 'UPDATED_ASC',
|
||||
milestone: '13.5'
|
||||
}
|
||||
value: :updated_asc,
|
||||
deprecated: {
|
||||
reason: :renamed,
|
||||
replacement: 'UPDATED_ASC',
|
||||
milestone: '13.5'
|
||||
}
|
||||
value 'created_desc', 'Created at descending order.',
|
||||
value: :created_desc,
|
||||
deprecated: {
|
||||
reason: :renamed,
|
||||
replacement: 'CREATED_DESC',
|
||||
milestone: '13.5'
|
||||
}
|
||||
value: :created_desc,
|
||||
deprecated: {
|
||||
reason: :renamed,
|
||||
replacement: 'CREATED_DESC',
|
||||
milestone: '13.5'
|
||||
}
|
||||
value 'created_asc', 'Created at ascending order.',
|
||||
value: :created_asc,
|
||||
deprecated: {
|
||||
reason: :renamed,
|
||||
replacement: 'CREATED_ASC',
|
||||
milestone: '13.5'
|
||||
}
|
||||
value: :created_asc,
|
||||
deprecated: {
|
||||
reason: :renamed,
|
||||
replacement: 'CREATED_ASC',
|
||||
milestone: '13.5'
|
||||
}
|
||||
|
||||
value 'UPDATED_DESC', 'Updated at descending order.', value: :updated_desc
|
||||
value 'UPDATED_ASC', 'Updated at ascending order.', value: :updated_asc
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ module Types
|
|||
description 'Completion status of tasks'
|
||||
|
||||
field :completed_count, GraphQL::Types::Int, null: false,
|
||||
description: 'Number of completed tasks.'
|
||||
description: 'Number of completed tasks.'
|
||||
field :count, GraphQL::Types::Int, null: false,
|
||||
description: 'Number of total tasks.'
|
||||
description: 'Number of total tasks.'
|
||||
end
|
||||
# rubocop: enable Graphql/AuthorizeTypes
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,37 +10,37 @@ module Types
|
|||
connection_type_class Types::CountableConnectionType
|
||||
|
||||
field :id, GraphQL::Types::ID,
|
||||
null: false,
|
||||
description: 'ID of the Terraform state.'
|
||||
null: false,
|
||||
description: 'ID of the Terraform state.'
|
||||
|
||||
field :name, GraphQL::Types::String,
|
||||
null: false,
|
||||
description: 'Name of the Terraform state.'
|
||||
null: false,
|
||||
description: 'Name of the Terraform state.'
|
||||
|
||||
field :locked_by_user, Types::UserType,
|
||||
null: true,
|
||||
description: 'User currently holding a lock on the Terraform state.'
|
||||
null: true,
|
||||
description: 'User currently holding a lock on the Terraform state.'
|
||||
|
||||
field :locked_at, Types::TimeType,
|
||||
null: true,
|
||||
description: 'Timestamp the Terraform state was locked.'
|
||||
null: true,
|
||||
description: 'Timestamp the Terraform state was locked.'
|
||||
|
||||
field :latest_version, Types::Terraform::StateVersionType,
|
||||
complexity: 3,
|
||||
null: true,
|
||||
description: 'Latest version of the Terraform state.'
|
||||
complexity: 3,
|
||||
null: true,
|
||||
description: 'Latest version of the Terraform state.'
|
||||
|
||||
field :created_at, Types::TimeType,
|
||||
null: false,
|
||||
description: 'Timestamp the Terraform state was created.'
|
||||
null: false,
|
||||
description: 'Timestamp the Terraform state was created.'
|
||||
|
||||
field :updated_at, Types::TimeType,
|
||||
null: false,
|
||||
description: 'Timestamp the Terraform state was updated.'
|
||||
null: false,
|
||||
description: 'Timestamp the Terraform state was updated.'
|
||||
|
||||
field :deleted_at, Types::TimeType,
|
||||
null: true,
|
||||
description: 'Timestamp the Terraform state was deleted.'
|
||||
null: true,
|
||||
description: 'Timestamp the Terraform state was deleted.'
|
||||
|
||||
def locked_by_user
|
||||
Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.locked_by_user_id).find
|
||||
|
|
|
|||
|
|
@ -10,34 +10,34 @@ module Types
|
|||
authorize :read_terraform_state
|
||||
|
||||
field :id, GraphQL::Types::ID,
|
||||
null: false,
|
||||
description: 'ID of the Terraform state version.'
|
||||
null: false,
|
||||
description: 'ID of the Terraform state version.'
|
||||
|
||||
field :created_by_user, Types::UserType,
|
||||
null: true,
|
||||
description: 'User that created this version.'
|
||||
null: true,
|
||||
description: 'User that created this version.'
|
||||
|
||||
field :download_path, GraphQL::Types::String,
|
||||
null: true,
|
||||
description: "URL for downloading the version's JSON file."
|
||||
null: true,
|
||||
description: "URL for downloading the version's JSON file."
|
||||
|
||||
field :job, Types::Ci::JobType,
|
||||
null: true,
|
||||
description: 'Job that created this version.',
|
||||
authorize: :read_commit_status
|
||||
null: true,
|
||||
description: 'Job that created this version.',
|
||||
authorize: :read_commit_status
|
||||
|
||||
field :serial, GraphQL::Types::Int,
|
||||
null: true,
|
||||
description: 'Serial number of the version.',
|
||||
method: :version
|
||||
null: true,
|
||||
description: 'Serial number of the version.',
|
||||
method: :version
|
||||
|
||||
field :created_at, Types::TimeType,
|
||||
null: false,
|
||||
description: 'Timestamp the version was created.'
|
||||
null: false,
|
||||
description: 'Timestamp the version was created.'
|
||||
|
||||
field :updated_at, Types::TimeType,
|
||||
null: false,
|
||||
description: 'Timestamp the version was updated.'
|
||||
null: false,
|
||||
description: 'Timestamp the version was updated.'
|
||||
|
||||
def created_by_user
|
||||
Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.created_by_user_id).find
|
||||
|
|
|
|||
|
|
@ -8,44 +8,44 @@ module Types
|
|||
authorize :read_timelog_category
|
||||
|
||||
field :id,
|
||||
GraphQL::Types::ID,
|
||||
null: false,
|
||||
description: 'Internal ID of the timelog category.'
|
||||
GraphQL::Types::ID,
|
||||
null: false,
|
||||
description: 'Internal ID of the timelog category.'
|
||||
|
||||
field :name,
|
||||
GraphQL::Types::String,
|
||||
null: false,
|
||||
description: 'Name of the category.'
|
||||
GraphQL::Types::String,
|
||||
null: false,
|
||||
description: 'Name of the category.'
|
||||
|
||||
field :description,
|
||||
GraphQL::Types::String,
|
||||
null: true,
|
||||
description: 'Description of the category.'
|
||||
GraphQL::Types::String,
|
||||
null: true,
|
||||
description: 'Description of the category.'
|
||||
|
||||
field :color,
|
||||
Types::ColorType,
|
||||
null: true,
|
||||
description: 'Color assigned to the category.'
|
||||
Types::ColorType,
|
||||
null: true,
|
||||
description: 'Color assigned to the category.'
|
||||
|
||||
field :billable,
|
||||
GraphQL::Types::Boolean,
|
||||
null: true,
|
||||
description: 'Whether the category is billable or not.'
|
||||
GraphQL::Types::Boolean,
|
||||
null: true,
|
||||
description: 'Whether the category is billable or not.'
|
||||
|
||||
field :billing_rate,
|
||||
GraphQL::Types::Float,
|
||||
null: true,
|
||||
description: 'Billing rate for the category.'
|
||||
GraphQL::Types::Float,
|
||||
null: true,
|
||||
description: 'Billing rate for the category.'
|
||||
|
||||
field :created_at,
|
||||
Types::TimeType,
|
||||
null: false,
|
||||
description: 'When the category was created.'
|
||||
Types::TimeType,
|
||||
null: false,
|
||||
description: 'When the category was created.'
|
||||
|
||||
field :updated_at,
|
||||
Types::TimeType,
|
||||
null: false,
|
||||
description: 'When the category was last updated.'
|
||||
Types::TimeType,
|
||||
null: false,
|
||||
description: 'When the category was last updated.'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ module Types
|
|||
# rubocop: disable Graphql/AuthorizeTypes
|
||||
class TimelogConnectionType < CountableConnectionType
|
||||
field :total_spent_time,
|
||||
GraphQL::Types::BigInt,
|
||||
null: false,
|
||||
description: 'Total time spent in seconds.'
|
||||
GraphQL::Types::BigInt,
|
||||
null: false,
|
||||
description: 'Total time spent in seconds.'
|
||||
|
||||
def total_spent_time
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
|
|
|
|||
|
|
@ -11,47 +11,47 @@ module Types
|
|||
expose_permissions Types::PermissionTypes::Timelog
|
||||
|
||||
field :id,
|
||||
GraphQL::Types::ID,
|
||||
null: false,
|
||||
description: 'Internal ID of the timelog.'
|
||||
GraphQL::Types::ID,
|
||||
null: false,
|
||||
description: 'Internal ID of the timelog.'
|
||||
|
||||
field :spent_at,
|
||||
Types::TimeType,
|
||||
null: true,
|
||||
description: 'Timestamp of when the time tracked was spent at.'
|
||||
Types::TimeType,
|
||||
null: true,
|
||||
description: 'Timestamp of when the time tracked was spent at.'
|
||||
|
||||
field :time_spent,
|
||||
GraphQL::Types::Int,
|
||||
null: false,
|
||||
description: 'Time spent displayed in seconds.'
|
||||
GraphQL::Types::Int,
|
||||
null: false,
|
||||
description: 'Time spent displayed in seconds.'
|
||||
|
||||
field :user,
|
||||
Types::UserType,
|
||||
null: false,
|
||||
description: 'User that logged the time.'
|
||||
Types::UserType,
|
||||
null: false,
|
||||
description: 'User that logged the time.'
|
||||
|
||||
field :issue,
|
||||
Types::IssueType,
|
||||
null: true,
|
||||
description: 'Issue that logged time was added to.'
|
||||
Types::IssueType,
|
||||
null: true,
|
||||
description: 'Issue that logged time was added to.'
|
||||
|
||||
field :merge_request,
|
||||
Types::MergeRequestType,
|
||||
null: true,
|
||||
description: 'Merge request that logged time was added to.'
|
||||
Types::MergeRequestType,
|
||||
null: true,
|
||||
description: 'Merge request that logged time was added to.'
|
||||
|
||||
field :note,
|
||||
Types::Notes::NoteType,
|
||||
null: true,
|
||||
description: 'Note where the quick action was executed to add the logged time.'
|
||||
Types::Notes::NoteType,
|
||||
null: true,
|
||||
description: 'Note where the quick action was executed to add the logged time.'
|
||||
|
||||
field :summary, GraphQL::Types::String,
|
||||
null: true,
|
||||
description: 'Summary of how the time was spent.'
|
||||
null: true,
|
||||
description: 'Summary of how the time was spent.'
|
||||
|
||||
field :project, Types::ProjectType,
|
||||
null: false,
|
||||
description: 'Target project of the timelog merge request or issue.'
|
||||
null: false,
|
||||
description: 'Target project of the timelog merge request or issue.'
|
||||
|
||||
def user
|
||||
Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.user_id).find
|
||||
|
|
|
|||
|
|
@ -10,50 +10,50 @@ module Types
|
|||
authorize :read_todo
|
||||
|
||||
field :id, GraphQL::Types::ID,
|
||||
description: 'ID of the to-do item.',
|
||||
null: false
|
||||
description: 'ID of the to-do item.',
|
||||
null: false
|
||||
|
||||
field :project, Types::ProjectType,
|
||||
description: 'Project this to-do item is associated with.',
|
||||
null: true
|
||||
description: 'Project this to-do item is associated with.',
|
||||
null: true
|
||||
|
||||
field :group, 'Types::GroupType',
|
||||
description: 'Group this to-do item is associated with.',
|
||||
null: true
|
||||
description: 'Group this to-do item is associated with.',
|
||||
null: true
|
||||
|
||||
field :author, Types::UserType,
|
||||
description: 'Author of this to-do item.',
|
||||
null: false
|
||||
description: 'Author of this to-do item.',
|
||||
null: false
|
||||
|
||||
field :action, Types::TodoActionEnum,
|
||||
description: 'Action of the to-do item.',
|
||||
null: false
|
||||
description: 'Action of the to-do item.',
|
||||
null: false
|
||||
|
||||
field :target, Types::TodoableInterface,
|
||||
description: 'Target of the to-do item.',
|
||||
calls_gitaly: true,
|
||||
null: false
|
||||
description: 'Target of the to-do item.',
|
||||
calls_gitaly: true,
|
||||
null: false
|
||||
|
||||
field :target_type, Types::TodoTargetEnum,
|
||||
description: 'Target type of the to-do item.',
|
||||
null: false
|
||||
description: 'Target type of the to-do item.',
|
||||
null: false
|
||||
|
||||
field :body, GraphQL::Types::String,
|
||||
description: 'Body of the to-do item.',
|
||||
null: false,
|
||||
calls_gitaly: true # TODO This is only true when `target_type` is `Commit`. See https://gitlab.com/gitlab-org/gitlab/issues/34757#note_234752665
|
||||
description: 'Body of the to-do item.',
|
||||
null: false,
|
||||
calls_gitaly: true # TODO This is only true when `target_type` is `Commit`. See https://gitlab.com/gitlab-org/gitlab/issues/34757#note_234752665
|
||||
|
||||
field :state, Types::TodoStateEnum,
|
||||
description: 'State of the to-do item.',
|
||||
null: false
|
||||
description: 'State of the to-do item.',
|
||||
null: false
|
||||
|
||||
field :created_at, Types::TimeType,
|
||||
description: 'Timestamp this to-do item was created.',
|
||||
null: false
|
||||
description: 'Timestamp this to-do item was created.',
|
||||
null: false
|
||||
|
||||
field :note, Types::Notes::NoteType,
|
||||
description: 'Note which created this to-do item.',
|
||||
null: true
|
||||
description: 'Note which created this to-do item.',
|
||||
null: true
|
||||
|
||||
def project
|
||||
Gitlab::Graphql::Loaders::BatchModelLoader.new(Project, object.project_id).find
|
||||
|
|
|
|||
|
|
@ -32,10 +32,12 @@ module Users
|
|||
today = Date.today
|
||||
return if user.last_activity_on == today
|
||||
|
||||
lease = Gitlab::ExclusiveLease.new("activity_service:#{user.id}", timeout: LEASE_TIMEOUT)
|
||||
# Skip transaction checks for exclusive lease as it is breaking system specs.
|
||||
# See issue: https://gitlab.com/gitlab-org/gitlab/-/issues/441536
|
||||
return unless Gitlab::ExclusiveLease.skipping_transaction_check { lease.try_obtain }
|
||||
if Feature.disabled?(:do_not_use_exclusive_lease_for_user_activity_service)
|
||||
lease = Gitlab::ExclusiveLease.new("activity_service:#{user.id}", timeout: LEASE_TIMEOUT)
|
||||
# Skip transaction checks for exclusive lease as it is breaking system specs.
|
||||
# See issue: https://gitlab.com/gitlab-org/gitlab/-/issues/441536
|
||||
return unless Gitlab::ExclusiveLease.skipping_transaction_check { lease.try_obtain }
|
||||
end
|
||||
|
||||
user.update_attribute(:last_activity_on, today)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
name: do_not_use_exclusive_lease_for_user_activity_service
|
||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/441536
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/151342
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/458719
|
||||
milestone: '17.0'
|
||||
group: group::tenant scale
|
||||
type: gitlab_com_derisk
|
||||
default_enabled: false
|
||||
|
|
@ -19,7 +19,7 @@ This could be a sign that you're testing an EE-specific behavior in a FOSS test.
|
|||
Please make sure the spec files pass in AS-IF-FOSS mode either:
|
||||
|
||||
1. Locally with `FOSS_ONLY=1 bin/rspec -- %<spec_files>s`.
|
||||
1. In the MR pipeline by verifying that the `rspec foss-impact` job has passed.
|
||||
1. In the MR pipeline by verifying that the `rspec:predictive:trigger` job has passed in the as-if-foss cross project downstream pipeline.
|
||||
1. In the MR pipelines by setting the ~"pipeline:run-as-if-foss" label on the MR (you can do it with the `/label ~"pipeline:run-as-if-foss"` quick action) and start a new MR pipeline.
|
||||
|
||||
MSG
|
||||
|
|
|
|||
|
|
@ -9,19 +9,8 @@ class MigrateZoektSettingsInApplicationSettings < Gitlab::Database::Migration[2.
|
|||
end
|
||||
|
||||
def up
|
||||
return unless Gitlab.ee? # zoekt_settings available only in EE version
|
||||
|
||||
ApplicationSetting.reset_column_information
|
||||
|
||||
application_setting = ApplicationSetting.last
|
||||
return if application_setting.nil? || application_setting.zoekt_settings.any?
|
||||
|
||||
zoekt_settings = {
|
||||
zoekt_indexing_enabled: Feature.enabled?(:index_code_with_zoekt),
|
||||
zoekt_indexing_paused: Feature.enabled?(:zoekt_pause_indexing, type: :ops),
|
||||
zoekt_search_enabled: Feature.enabled?(:search_code_with_zoekt)
|
||||
}
|
||||
application_setting.update!(zoekt_settings: zoekt_settings)
|
||||
# no-op this was just a data migration which is already done in 16.11. The plan is to remove the feature-flags used
|
||||
# in this migration. So better to disable this migration in 17.0 to avoid any migration issues.
|
||||
end
|
||||
|
||||
def down
|
||||
|
|
|
|||
|
|
@ -75,10 +75,14 @@ Before you use a new Elasticsearch cluster in production, see the
|
|||
|
||||
> - Support for Elasticsearch 6.8 [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/350275) in GitLab 15.0.
|
||||
|
||||
You don't have to change the GitLab configuration when you upgrade Elasticsearch.
|
||||
When you upgrade Elasticsearch, you do not have to change the GitLab configuration.
|
||||
|
||||
You should pause indexing during an Elasticsearch upgrade so changes can still be tracked.
|
||||
When the Elasticsearch cluster is fully upgraded and active, [resume indexing](#unpause-indexing).
|
||||
During an Elasticsearch upgrade, you must:
|
||||
|
||||
- Pause indexing so changes can still be tracked.
|
||||
- Disable advanced search so searches do not fail with an `HTTP 500` error.
|
||||
|
||||
When the Elasticsearch cluster is fully upgraded and active, [resume indexing](#unpause-indexing) and enable advanced search.
|
||||
|
||||
When you upgrade to GitLab 15.0 and later, you must use Elasticsearch 7.x and later.
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ require 'gitlab' unless Object.const_defined?(:Gitlab)
|
|||
require 'set' # rubocop:disable Lint/RedundantRequireStatement -- Ruby 3.1 and earlier needs this. Drop this line after Ruby 3.2+ is only supported.
|
||||
|
||||
class GenerateAsIfFossEnv
|
||||
# rubocop:disable Style/WordArray -- Probably a bug? It already is
|
||||
FOSS_JOBS = Set.new(%w[
|
||||
build-assets-image
|
||||
build-qa-image
|
||||
|
|
@ -16,11 +17,16 @@ class GenerateAsIfFossEnv
|
|||
eslint
|
||||
generate-apollo-graphql-schema
|
||||
graphql-schema-dump
|
||||
rspec-predictive:pipeline-generate
|
||||
rspec:predictive:trigger
|
||||
rspec:predictive:trigger\ single-db
|
||||
rspec:predictive:trigger\ single-db-ci-connection
|
||||
rubocop
|
||||
qa:internal
|
||||
qa:selectors
|
||||
static-analysis
|
||||
]).freeze
|
||||
# rubocop:enable Style/WordArray
|
||||
|
||||
def initialize
|
||||
@client = Gitlab.client(
|
||||
|
|
@ -62,8 +68,10 @@ class GenerateAsIfFossEnv
|
|||
end
|
||||
|
||||
def each_job
|
||||
client.pipeline_jobs(ENV['CI_PROJECT_ID'], ENV['CI_PIPELINE_ID']).auto_paginate do |job|
|
||||
yield(job)
|
||||
%i[pipeline_jobs pipeline_bridges].each do |kind|
|
||||
client.public_send(kind, ENV['CI_PROJECT_ID'], ENV['CI_PIPELINE_ID']).auto_paginate do |job| # rubocop:disable GitlabSecurity/PublicSend -- We're sending with static values, no concerns
|
||||
yield(job)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -102,6 +102,9 @@ RSpec.describe '.gitlab/ci/rules.gitlab-ci.yml', feature_category: :tooling do
|
|||
|
||||
if base['when'] == 'never'
|
||||
expect(derived).to eq(base.except('when'))
|
||||
elsif base['if'].start_with?('$ENABLE_')
|
||||
derived_if = base['if'].sub('RSPEC', 'RSPEC_PREDICTIVE_TRIGGER')
|
||||
expect(derived).to eq(base.merge('if' => derived_if))
|
||||
elsif base['when'].nil?
|
||||
expect(derived).to eq(base.merge('when' => 'never'))
|
||||
end
|
||||
|
|
@ -119,7 +122,13 @@ RSpec.describe '.gitlab/ci/rules.gitlab-ci.yml', feature_category: :tooling do
|
|||
it_behaves_like 'predictive is inverse of non-predictive' do
|
||||
let(:base_rules) { config.dig('.rails:rules:ee-and-foss-default-rules', 'rules') }
|
||||
|
||||
let(:derived_rules) { config.dig('.rails:rules:rspec-predictive', 'rules') }
|
||||
let(:derived_rules) do
|
||||
config.dig('.rails:rules:rspec-predictive', 'rules').reject do |rule|
|
||||
# This happens in each specific rspec,
|
||||
# which is outside of .rails:rules:ee-and-foss-default-rules
|
||||
rule['if'].start_with?('$ENABLE_')
|
||||
end
|
||||
end
|
||||
|
||||
it 'contains an additional allow rule about code-backstage-patterns not present in the base' do
|
||||
expected_rule = {
|
||||
|
|
@ -135,24 +144,14 @@ RSpec.describe '.gitlab/ci/rules.gitlab-ci.yml', feature_category: :tooling do
|
|||
|
||||
describe '.rails:rules:single-db' do
|
||||
it_behaves_like 'predictive is inverse of non-predictive' do
|
||||
let(:base_rules) do
|
||||
config.dig('.rails:rules:single-db', 'rules').reject do |rule|
|
||||
rule['if'].start_with?('$ENABLE_') # We don't handle this yet
|
||||
end
|
||||
end
|
||||
|
||||
let(:base_rules) { config.dig('.rails:rules:single-db', 'rules') }
|
||||
let(:derived_rules) { config.dig('.rails:rules:rspec-predictive:single-db', 'rules') }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.rails:rules:single-db-ci-connection' do
|
||||
it_behaves_like 'predictive is inverse of non-predictive' do
|
||||
let(:base_rules) do
|
||||
config.dig('.rails:rules:single-db-ci-connection', 'rules').reject do |rule|
|
||||
rule['if'].start_with?('$ENABLE_') # We don't handle this yet
|
||||
end
|
||||
end
|
||||
|
||||
let(:base_rules) { config.dig('.rails:rules:single-db-ci-connection', 'rules') }
|
||||
let(:derived_rules) { config.dig('.rails:rules:rspec-predictive:single-db-ci-connection', 'rules') }
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -140,6 +140,10 @@ FactoryBot.define do
|
|||
avatar { fixture_file_upload('spec/fixtures/dk.png') }
|
||||
end
|
||||
|
||||
trait :with_last_activity_on_today do
|
||||
last_activity_on { Date.today }
|
||||
end
|
||||
|
||||
trait :with_sign_ins do
|
||||
sign_in_count { 3 }
|
||||
current_sign_in_at { FFaker::Time.between(10.days.ago, 1.day.ago) }
|
||||
|
|
|
|||
|
|
@ -1171,6 +1171,22 @@ describe('buildClient', () => {
|
|||
'start_time=2020-07-05T00:00:00.000Z&end_time=2020-07-06T00:00:00.000Z',
|
||||
);
|
||||
});
|
||||
|
||||
it('handles exact timestamps', async () => {
|
||||
await client.fetchLogs({
|
||||
filters: {
|
||||
dateRange: {
|
||||
timestamp: '2024-02-19T16:10:15.4433398Z',
|
||||
endDate: new Date('2024-02-19'),
|
||||
startDate: new Date('2024-02-19'),
|
||||
value: 'custom',
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(getQueryParam()).toContain(
|
||||
'start_time=2024-02-19T16:10:15.4433398Z&end_time=2024-02-19T16:10:15.4433398Z',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('attributes filters', () => {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import {
|
|||
DATE_RANGE_QUERY_KEY,
|
||||
DATE_RANGE_START_QUERY_KEY,
|
||||
DATE_RANGE_END_QUERY_KEY,
|
||||
TIMESTAMP_QUERY_KEY,
|
||||
} from '~/observability/constants';
|
||||
|
||||
describe('periodToDate', () => {
|
||||
|
|
@ -74,6 +75,15 @@ describe('queryToDateFilterObj', () => {
|
|||
};
|
||||
expect(queryToDateFilterObj(query)).toEqual({ value: '1h' });
|
||||
});
|
||||
|
||||
it('returns a date range object from a nano timestamp', () => {
|
||||
expect(queryToDateFilterObj({ timestamp: '2024-02-19T16:10:15.4433398Z' })).toEqual({
|
||||
value: CUSTOM_DATE_RANGE_OPTION,
|
||||
startDate: new Date('2024-02-19T16:10:15.443Z'),
|
||||
endDate: new Date('2024-02-19T16:10:15.443Z'),
|
||||
timestamp: '2024-02-19T16:10:15.4433398Z',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('dateFilterObjToQuery', () => {
|
||||
|
|
@ -99,6 +109,11 @@ describe('dateFilterObjToQuery', () => {
|
|||
[DATE_RANGE_END_QUERY_KEY]: '2020-01-02T00:00:00.000Z',
|
||||
});
|
||||
});
|
||||
it('converts a filter with timestamp', () => {
|
||||
expect(dateFilterObjToQuery({ timestamp: '2024-02-19T16:10:15.4433398Z' })).toEqual({
|
||||
[TIMESTAMP_QUERY_KEY]: '2024-02-19T16:10:15.4433398Z',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns empty object if filter is empty', () => {
|
||||
expect(dateFilterObjToQuery({})).toEqual({});
|
||||
|
|
|
|||
|
|
@ -4,9 +4,11 @@ require 'spec_helper'
|
|||
RSpec.describe 'getting a detailed sentry error', feature_category: :error_tracking do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:project) { create(:project, :repository) }
|
||||
# user should have `last_on_activity` set to today,
|
||||
# so that `Users::ActivityService` does not register any more updates.
|
||||
let_it_be(:current_user) { create(:user, :with_last_activity_on_today) }
|
||||
let_it_be(:project) { create(:project, :repository, namespace: create(:namespace, owner: current_user)) }
|
||||
let_it_be(:project_setting) { create(:project_error_tracking_setting, project: project) }
|
||||
let_it_be(:current_user) { project.first_owner }
|
||||
let_it_be(:sentry_detailed_error) { build(:error_tracking_sentry_detailed_error) }
|
||||
|
||||
let(:sentry_gid) { sentry_detailed_error.to_global_id.to_s }
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ RSpec.describe API::UsageData, feature_category: :service_ping do
|
|||
|
||||
context 'with unknown event' do
|
||||
it 'returns status ok' do
|
||||
expect(Gitlab::Redis::HLL).not_to receive(:add)
|
||||
expect(Gitlab::Redis::HLL).not_to receive(:add).with(hash_including(key: unknown_event))
|
||||
|
||||
post api(endpoint, user), params: { event: unknown_event }
|
||||
|
||||
|
|
|
|||
|
|
@ -1608,6 +1608,10 @@ RSpec.describe API::Users, :aggregate_failures, feature_category: :user_profile
|
|||
end
|
||||
|
||||
context 'updating password' do
|
||||
# user should have `last_on_activity` set to today,
|
||||
# so that `Users::ActivityService` does not register any more updates.
|
||||
let_it_be(:admin) { create(:admin, :with_last_activity_on_today) }
|
||||
|
||||
def update_password(user, admin, password = User.random_password)
|
||||
put api("/users/#{user.id}", admin, admin_mode: true), params: { password: password }
|
||||
end
|
||||
|
|
@ -1617,7 +1621,7 @@ RSpec.describe API::Users, :aggregate_failures, feature_category: :user_profile
|
|||
update_password(admin, admin)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(user.reload.password_expired?).to eq(false)
|
||||
expect(admin.reload.password_expired?).to eq(false)
|
||||
end
|
||||
|
||||
it 'does not enqueue the `admin changed your password` email' do
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Projects::MergeRequestsController, feature_category: :source_code_management do
|
||||
let_it_be(:merge_request) { create(:merge_request) }
|
||||
let_it_be(:project) { merge_request.project }
|
||||
let_it_be(:user) { merge_request.author }
|
||||
# user should have `last_on_activity` set to today,
|
||||
# so that `Users::ActivityService` does not register any more updates.
|
||||
let_it_be(:user) { create(:user, :with_last_activity_on_today, :with_namespace) }
|
||||
let_it_be(:project) { create(:project, :repository, namespace: user.namespace) }
|
||||
let_it_be(:merge_request) { create(:merge_request, source_project: project, author: user) }
|
||||
|
||||
describe 'GET #show' do
|
||||
let_it_be(:group) { create(:group) }
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'merge requests actions', feature_category: :source_code_management do
|
||||
let_it_be(:project) { create(:project, :repository) }
|
||||
# user should have `last_on_activity` set to today,
|
||||
# so that `Users::ActivityService` does not register any more updates.
|
||||
let_it_be(:user) { create(:user, :with_last_activity_on_today) }
|
||||
let_it_be(:project) { create(:project, :repository, namespace: create(:namespace, owner: user)) }
|
||||
|
||||
let(:merge_request) do
|
||||
create(
|
||||
|
|
@ -15,7 +18,6 @@ RSpec.describe 'merge requests actions', feature_category: :source_code_manageme
|
|||
)
|
||||
end
|
||||
|
||||
let(:user) { project.first_owner }
|
||||
let(:user2) { create(:user) }
|
||||
|
||||
before do
|
||||
|
|
|
|||
|
|
@ -53,15 +53,32 @@ RSpec.describe GenerateAsIfFossEnv, feature_category: :tooling do
|
|||
]
|
||||
end
|
||||
|
||||
before do
|
||||
messages = receive_message_chain(:client, :pipeline_jobs, :auto_paginate)
|
||||
|
||||
yield_jobs = jobs.inject(messages) do |stub, job|
|
||||
stub.and_yield(double(name: job)) # rubocop:disable RSpec/VerifiedDoubles -- As explained at the top of this file, we do not load the Gitlab client
|
||||
end
|
||||
|
||||
allow(Gitlab).to yield_jobs
|
||||
let(:bridges) do
|
||||
[
|
||||
'rspec-predictive:pipeline-generate',
|
||||
'rspec:predictive:trigger',
|
||||
'rspec:predictive:trigger single-db',
|
||||
'rspec:predictive:trigger single-db-ci-connection'
|
||||
]
|
||||
end
|
||||
|
||||
# rubocop:disable RSpec/VerifiedDoubles -- As explained at the top of this file, we do not load the Gitlab client
|
||||
before do
|
||||
client = double
|
||||
allow(Gitlab).to receive(:client).and_return(client)
|
||||
|
||||
allow(client).to yield_jobs(:pipeline_jobs, jobs)
|
||||
allow(client).to yield_jobs(:pipeline_bridges, bridges)
|
||||
end
|
||||
|
||||
def yield_jobs(api_method, jobs)
|
||||
messages = receive_message_chain(api_method, :auto_paginate)
|
||||
|
||||
jobs.inject(messages) do |stub, job_name|
|
||||
stub.and_yield(double(name: job_name))
|
||||
end
|
||||
end
|
||||
# rubocop:enable RSpec/VerifiedDoubles
|
||||
end
|
||||
|
||||
describe '#variables' do
|
||||
|
|
@ -100,7 +117,11 @@ RSpec.describe GenerateAsIfFossEnv, feature_category: :tooling do
|
|||
ENABLE_RUBOCOP: 'true',
|
||||
ENABLE_QA_INTERNAL: 'true',
|
||||
ENABLE_QA_SELECTORS: 'true',
|
||||
ENABLE_STATIC_ANALYSIS: 'true'
|
||||
ENABLE_STATIC_ANALYSIS: 'true',
|
||||
ENABLE_RSPEC_PREDICTIVE_PIPELINE_GENERATE: 'true',
|
||||
ENABLE_RSPEC_PREDICTIVE_TRIGGER: 'true',
|
||||
ENABLE_RSPEC_PREDICTIVE_TRIGGER_SINGLE_DB: 'true',
|
||||
ENABLE_RSPEC_PREDICTIVE_TRIGGER_SINGLE_DB_CI_CONNECTION: 'true'
|
||||
})
|
||||
end
|
||||
end
|
||||
|
|
@ -142,6 +163,10 @@ RSpec.describe GenerateAsIfFossEnv, feature_category: :tooling do
|
|||
ENABLE_QA_INTERNAL=true
|
||||
ENABLE_QA_SELECTORS=true
|
||||
ENABLE_STATIC_ANALYSIS=true
|
||||
ENABLE_RSPEC_PREDICTIVE_PIPELINE_GENERATE=true
|
||||
ENABLE_RSPEC_PREDICTIVE_TRIGGER=true
|
||||
ENABLE_RSPEC_PREDICTIVE_TRIGGER_SINGLE_DB=true
|
||||
ENABLE_RSPEC_PREDICTIVE_TRIGGER_SINGLE_DB_CI_CONNECTION=true
|
||||
ENV
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -643,7 +643,11 @@ RSpec.describe QuickActions::InterpretService, feature_category: :team_planning
|
|||
it 'returns the confidential message' do
|
||||
_, _, message = service.execute(content, issuable)
|
||||
|
||||
issuable_type = issuable.to_ability_name.humanize(capitalize: false)
|
||||
issuable_type = if issuable.to_ability_name == "work_item"
|
||||
'item'
|
||||
else
|
||||
issuable.to_ability_name.humanize(capitalize: false)
|
||||
end
|
||||
|
||||
expect(message).to eq("Made this #{issuable_type} confidential.")
|
||||
end
|
||||
|
|
|
|||
|
|
@ -41,10 +41,25 @@ RSpec.describe Users::ActivityService, feature_category: :user_profile do
|
|||
.to(Date.today)
|
||||
end
|
||||
|
||||
it 'tries to obtain ExclusiveLease' do
|
||||
expect(Gitlab::ExclusiveLease).to receive(:new).with("activity_service:#{user.id}", anything).and_call_original
|
||||
context 'for ExclusiveLease' do
|
||||
context 'when the feature flag `do_not_use_exclusive_lease_for_user_activity_service` is turned off' do
|
||||
before do
|
||||
stub_feature_flags(do_not_use_exclusive_lease_for_user_activity_service: false)
|
||||
end
|
||||
|
||||
subject.execute
|
||||
it 'tries to obtain ExclusiveLease' do
|
||||
expect(Gitlab::ExclusiveLease).to receive(:new).with("activity_service:#{user.id}", anything)
|
||||
.and_call_original
|
||||
|
||||
subject.execute
|
||||
end
|
||||
end
|
||||
|
||||
it 'does not try to obtain ExclusiveLease' do
|
||||
expect(Gitlab::ExclusiveLease).not_to receive(:new).with("activity_service:#{user.id}", anything)
|
||||
|
||||
subject.execute
|
||||
end
|
||||
end
|
||||
|
||||
it 'tracks RedisHLL event' do
|
||||
|
|
@ -108,14 +123,22 @@ RSpec.describe Users::ActivityService, feature_category: :user_profile do
|
|||
it_behaves_like 'does not update last_activity_on'
|
||||
end
|
||||
|
||||
context 'when a lease could not be obtained' do
|
||||
let(:last_activity_on) { nil }
|
||||
context 'for ExclusiveLease' do
|
||||
context 'when the feature flag `do_not_use_exclusive_lease_for_user_activity_service` is turned off' do
|
||||
before do
|
||||
stub_feature_flags(do_not_use_exclusive_lease_for_user_activity_service: false)
|
||||
end
|
||||
|
||||
before do
|
||||
stub_exclusive_lease_taken("activity_service:#{user.id}", timeout: 1.minute.to_i)
|
||||
context 'when a lease could not be obtained' do
|
||||
let(:last_activity_on) { nil }
|
||||
|
||||
before do
|
||||
stub_exclusive_lease_taken("activity_service:#{user.id}", timeout: 1.minute.to_i)
|
||||
end
|
||||
|
||||
it_behaves_like 'does not update last_activity_on'
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'does not update last_activity_on'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue