Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
b5bdf6e521
commit
da576e4a0b
|
|
@ -728,6 +728,12 @@ Migration/PreventIndexCreation:
|
|||
- !ruby/regexp /\Adb\/(post_)?migrate\/2020.*\.rb\z/
|
||||
- !ruby/regexp /\Adb\/(post_)?migrate\/20210[1-6].*\.rb\z/
|
||||
|
||||
Migration/SchemaAdditionMethodsNoPost:
|
||||
Enabled: true
|
||||
Include:
|
||||
- db/post_migrate/*.rb
|
||||
EnforcedSince: 20221024034228
|
||||
|
||||
Gitlab/RailsLogger:
|
||||
Exclude:
|
||||
- 'spec/**/*.rb'
|
||||
|
|
|
|||
4
Gemfile
4
Gemfile
|
|
@ -217,10 +217,10 @@ gem 'state_machines-activerecord', '~> 0.8.0'
|
|||
gem 'acts-as-taggable-on', '~> 9.0'
|
||||
|
||||
# Background jobs
|
||||
gem 'sidekiq', '~> 6.4.0'
|
||||
gem 'sidekiq', '~> 6.5.7'
|
||||
gem 'sidekiq-cron', '~> 1.8.0'
|
||||
gem 'redis-namespace', '~> 1.9.0'
|
||||
gem 'gitlab-sidekiq-fetcher', '0.8.0', require: 'sidekiq-reliable-fetch'
|
||||
gem 'gitlab-sidekiq-fetcher', '0.9.0', require: 'sidekiq-reliable-fetch'
|
||||
|
||||
# Cron Parser
|
||||
gem 'fugit', '~> 1.2.1'
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@
|
|||
{"name":"gitlab-markup","version":"1.8.1","platform":"ruby","checksum":"ab1f9fd016977497c2af25b76341dea670533014f406861834a0bd99f646707b"},
|
||||
{"name":"gitlab-net-dns","version":"0.9.1","platform":"ruby","checksum":"bcd1a08dcb31b731e8ff602d828de619d2d9f53f5812f6abacf11c720873d4cb"},
|
||||
{"name":"gitlab-omniauth-openid-connect","version":"0.10.0","platform":"ruby","checksum":"ea44a23ea93457057bba6a9912e883f5aefab36a941c6c58512c8a7095fb1153"},
|
||||
{"name":"gitlab-sidekiq-fetcher","version":"0.8.0","platform":"ruby","checksum":"9c564caa2a958d44a8d78672dc23b2a206102d0223b41b77b58626a945e37362"},
|
||||
{"name":"gitlab-sidekiq-fetcher","version":"0.9.0","platform":"ruby","checksum":"54041aec059f20c8e6dfce394e1b60e0c0a9c7cef32da912a58abbd333e13897"},
|
||||
{"name":"gitlab-styles","version":"9.0.0","platform":"ruby","checksum":"ef0edfab8f807a5be2309ba24dfc44fec5ba52ed68b87167c051e9ffdadb3bad"},
|
||||
{"name":"gitlab_chronic_duration","version":"0.10.6.2","platform":"ruby","checksum":"6dda4cfe7dca9b958f163ac8835c3d9cc70cf8df8cbb89bb2fbf9ba4375105fb"},
|
||||
{"name":"gitlab_omniauth-ldap","version":"2.2.0","platform":"ruby","checksum":"bb4d20acb3b123ed654a8f6a47d3fac673ece7ed0b6992edb92dca14bad2838c"},
|
||||
|
|
@ -533,7 +533,7 @@
|
|||
{"name":"sexp_processor","version":"4.15.1","platform":"ruby","checksum":"9291a0f2247f50d15068ee6965b67cd7b678b0d273e18adf3c0b2ea4a890125c"},
|
||||
{"name":"shellany","version":"0.0.1","platform":"ruby","checksum":"0e127a9132698766d7e752e82cdac8250b6adbd09e6c0a7fbbb6f61964fedee7"},
|
||||
{"name":"shoulda-matchers","version":"5.1.0","platform":"ruby","checksum":"a01d20589989e9653ab4a28c67d9db2b82bcf0a2496cf01d5e1a95a4aaaf5b07"},
|
||||
{"name":"sidekiq","version":"6.4.2","platform":"ruby","checksum":"0d3c05fecb5fbace5ff5efc63da707e02a9c4673fb8e33ceca10b5ec0e9f062c"},
|
||||
{"name":"sidekiq","version":"6.5.7","platform":"ruby","checksum":"7d966fd84d42a942615d6874be31e40f8bece841fdd9b96fc53cad22a590555c"},
|
||||
{"name":"sidekiq-cron","version":"1.8.0","platform":"ruby","checksum":"47da72ca73ce5b71896aaf7e7c4391386ec517dd003f184c50c0b727d82eb0ca"},
|
||||
{"name":"sigdump","version":"0.2.4","platform":"ruby","checksum":"0bf2176e55c1a262788623fe5ea57caddd6ba2abebe5e349d9d5e7c3a3010ed7"},
|
||||
{"name":"signet","version":"0.17.0","platform":"ruby","checksum":"1d2831930dc28da32e34bec68cf7ded97ee2867b208f97c500ee293829cb0004"},
|
||||
|
|
|
|||
13
Gemfile.lock
13
Gemfile.lock
|
|
@ -584,7 +584,8 @@ GEM
|
|||
addressable (~> 2.7)
|
||||
omniauth (>= 1.9, < 3)
|
||||
openid_connect (~> 1.2)
|
||||
gitlab-sidekiq-fetcher (0.8.0)
|
||||
gitlab-sidekiq-fetcher (0.9.0)
|
||||
json (>= 2.5)
|
||||
sidekiq (~> 6.1)
|
||||
gitlab-styles (9.0.0)
|
||||
rubocop (~> 1.36.0)
|
||||
|
|
@ -1314,10 +1315,10 @@ GEM
|
|||
shellany (0.0.1)
|
||||
shoulda-matchers (5.1.0)
|
||||
activesupport (>= 5.2.0)
|
||||
sidekiq (6.4.2)
|
||||
connection_pool (>= 2.2.2)
|
||||
sidekiq (6.5.7)
|
||||
connection_pool (>= 2.2.5)
|
||||
rack (~> 2.0)
|
||||
redis (>= 4.2.0)
|
||||
redis (>= 4.5.0, < 5)
|
||||
sidekiq-cron (1.8.0)
|
||||
fugit (~> 1)
|
||||
sidekiq (>= 4.2.1)
|
||||
|
|
@ -1635,7 +1636,7 @@ DEPENDENCIES
|
|||
gitlab-markup (~> 1.8.0)
|
||||
gitlab-net-dns (~> 0.9.1)
|
||||
gitlab-omniauth-openid-connect (~> 0.10.0)
|
||||
gitlab-sidekiq-fetcher (= 0.8.0)
|
||||
gitlab-sidekiq-fetcher (= 0.9.0)
|
||||
gitlab-styles (~> 9.0.0)
|
||||
gitlab_chronic_duration (~> 0.10.6.2)
|
||||
gitlab_omniauth-ldap (~> 2.2.0)
|
||||
|
|
@ -1787,7 +1788,7 @@ DEPENDENCIES
|
|||
sentry-sidekiq (~> 5.1.1)
|
||||
settingslogic (~> 2.0.9)
|
||||
shoulda-matchers (~> 5.1.0)
|
||||
sidekiq (~> 6.4.0)
|
||||
sidekiq (~> 6.5.7)
|
||||
sidekiq-cron (~> 1.8.0)
|
||||
sigdump (~> 0.2.4)
|
||||
simple_po_parser (~> 1.1.6)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
import ScopeNavigation from '~/search/sidebar/components/scope_navigation.vue';
|
||||
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
import { SCOPE_ISSUES, SCOPE_MERGE_REQUESTS } from '../constants';
|
||||
import ResultsFilters from './results_filters.vue';
|
||||
|
||||
|
|
@ -10,6 +11,7 @@ export default {
|
|||
ResultsFilters,
|
||||
ScopeNavigation,
|
||||
},
|
||||
mixins: [glFeatureFlagsMixin()],
|
||||
computed: {
|
||||
...mapState(['urlQuery']),
|
||||
showFilters() {
|
||||
|
|
@ -21,7 +23,7 @@ export default {
|
|||
|
||||
<template>
|
||||
<section class="search-sidebar gl-display-flex gl-flex-direction-column gl-mr-4 gl-mb-6 gl-mt-5">
|
||||
<scope-navigation />
|
||||
<scope-navigation v-if="glFeatures.searchPageVerticalNav" />
|
||||
<results-filters v-if="showFilters" />
|
||||
</section>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -226,7 +226,6 @@ module Types
|
|||
Types::IssueType.connection_type,
|
||||
null: true,
|
||||
description: 'Issues of the project.',
|
||||
extras: [:lookahead],
|
||||
resolver: Resolvers::ProjectIssuesResolver
|
||||
|
||||
field :work_items,
|
||||
|
|
|
|||
|
|
@ -439,8 +439,9 @@ class Deployment < ApplicationRecord
|
|||
end
|
||||
|
||||
# default tag limit is 100, 0 means no limit
|
||||
# when refs_by_oid is passed an SHA, returns refs for that commit
|
||||
def tags(limit: 100)
|
||||
project.repository.tag_names_contains(sha, limit: limit)
|
||||
project.repository.refs_by_oid(oid: sha, limit: limit, ref_patterns: [Gitlab::Git::TAG_REF_PREFIX]) || []
|
||||
end
|
||||
strong_memoize_attr :tags
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ class PagesDomain < ApplicationRecord
|
|||
SSL_RENEWAL_THRESHOLD = 30.days.freeze
|
||||
|
||||
enum certificate_source: { user_provided: 0, gitlab_provided: 1 }, _prefix: :certificate
|
||||
enum scope: { instance: 0, group: 1, project: 2 }, _prefix: :scope
|
||||
enum usage: { pages: 0, serverless: 1 }, _prefix: :usage
|
||||
enum scope: { instance: 0, group: 1, project: 2 }, _prefix: :scope, _default: :project
|
||||
enum usage: { pages: 0, serverless: 1 }, _prefix: :usage, _default: :pages
|
||||
|
||||
belongs_to :project
|
||||
has_many :acme_orders, class_name: "PagesDomainAcmeOrder"
|
||||
|
|
@ -35,10 +35,8 @@ class PagesDomain < ApplicationRecord
|
|||
validate :validate_intermediates, if: ->(domain) { domain.certificate.present? && domain.certificate_changed? }
|
||||
validate :validate_custom_domain_count_per_project, on: :create
|
||||
|
||||
default_value_for(:auto_ssl_enabled, allows_nil: false) { ::Gitlab::LetsEncrypt.enabled? }
|
||||
default_value_for :scope, allows_nil: false, value: :project
|
||||
default_value_for :wildcard, allows_nil: false, value: false
|
||||
default_value_for :usage, allows_nil: false, value: :pages
|
||||
attribute :auto_ssl_enabled, default: -> { ::Gitlab::LetsEncrypt.enabled? }
|
||||
attribute :wildcard, default: false
|
||||
|
||||
attr_encrypted :key,
|
||||
mode: :per_attribute_iv_and_salt,
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class ProjectSetting < ApplicationRecord
|
|||
|
||||
validate :validates_mr_default_target_self
|
||||
|
||||
default_value_for(:legacy_open_source_license_available) do
|
||||
attribute :legacy_open_source_license_available, default: -> do
|
||||
Feature.enabled?(:legacy_open_source_license_available, type: :ops)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ module Serverless
|
|||
validates :uuid, presence: true, uniqueness: true, length: { is: ::Serverless::Domain::UUID_LENGTH },
|
||||
format: { with: HEX_REGEXP, message: 'only allows hex characters' }
|
||||
|
||||
default_value_for(:uuid, allows_nil: false) { ::Serverless::Domain.generate_uuid }
|
||||
after_initialize :set_uuid, if: :new_record?
|
||||
|
||||
delegate :domain, to: :pages_domain
|
||||
delegate :cluster, to: :knative
|
||||
|
|
@ -29,5 +29,11 @@ module Serverless
|
|||
.includes(:pages_domain, :knative)
|
||||
.find_by(uuid: uuid)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_uuid
|
||||
self.uuid = ::Serverless::Domain.generate_uuid
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,11 +5,14 @@ module Deployments
|
|||
presents ::Deployment, as: :deployment
|
||||
|
||||
delegator_override :tags
|
||||
|
||||
# Note: this returns the path key as 'tags/tag_name' but it is used as a URL in the UI
|
||||
|
||||
def tags
|
||||
super.map do |tag|
|
||||
{
|
||||
name: tag,
|
||||
path: "tags/#{tag}"
|
||||
name: tag.delete_prefix(Gitlab::Git::TAG_REF_PREFIX),
|
||||
path: tag.delete_prefix('refs/')
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -35,19 +35,19 @@ enable_json_logs = Gitlab.config.sidekiq.log_format == 'json'
|
|||
enable_sidekiq_memory_killer = ENV['SIDEKIQ_MEMORY_KILLER_MAX_RSS'].to_i.nonzero?
|
||||
|
||||
Sidekiq.configure_server do |config|
|
||||
config.options[:strict] = false
|
||||
config.options[:queues] = Gitlab::SidekiqConfig.expand_queues(config.options[:queues])
|
||||
config[:strict] = false
|
||||
config[:queues] = Gitlab::SidekiqConfig.expand_queues(config[:queues])
|
||||
|
||||
if enable_json_logs
|
||||
config.log_formatter = Gitlab::SidekiqLogging::JSONFormatter.new
|
||||
config.options[:job_logger] = Gitlab::SidekiqLogging::StructuredLogger
|
||||
config[:job_logger] = Gitlab::SidekiqLogging::StructuredLogger
|
||||
|
||||
# Remove the default-provided handler. The exception is logged inside
|
||||
# Gitlab::SidekiqLogging::StructuredLogger
|
||||
config.error_handlers.reject! { |handler| handler.is_a?(Sidekiq::ExceptionHandler::Logger) }
|
||||
config.error_handlers.delete(Sidekiq::DEFAULT_ERROR_HANDLER)
|
||||
end
|
||||
|
||||
Sidekiq.logger.info "Listening on queues #{config.options[:queues].uniq.sort}"
|
||||
Sidekiq.logger.info "Listening on queues #{config[:queues].uniq.sort}"
|
||||
|
||||
config.redis = queues_config_hash
|
||||
|
||||
|
|
@ -84,13 +84,13 @@ Sidekiq.configure_server do |config|
|
|||
end
|
||||
|
||||
if enable_reliable_fetch?
|
||||
config.options[:semi_reliable_fetch] = enable_semi_reliable_fetch_mode?
|
||||
config[:semi_reliable_fetch] = enable_semi_reliable_fetch_mode?
|
||||
Sidekiq::ReliableFetch.setup_reliable_fetch!(config)
|
||||
end
|
||||
|
||||
Gitlab::SidekiqVersioning.install!
|
||||
|
||||
config.options[:cron_poll_interval] = Gitlab.config.cron_jobs.poll_interval
|
||||
config[:cron_poll_interval] = Gitlab.config.cron_jobs.poll_interval
|
||||
load_cron_jobs!
|
||||
|
||||
# Avoid autoload issue such as 'Mail::Parsers::AddressStruct'
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ if ENV['ENABLE_SIDEKIQ_CLUSTER']
|
|||
# Allow sidekiq to cleanly terminate and push any running jobs back
|
||||
# into the queue. We use the configured timeout and add a small
|
||||
# grace period
|
||||
sleep(Sidekiq.options[:timeout] + 5)
|
||||
sleep(Sidekiq[:timeout] + 5)
|
||||
|
||||
# Signaling the Sidekiq Pgroup as KILL is not forwarded to
|
||||
# a possible child process. In Sidekiq Cluster, all child Sidekiq
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
BLUEPRINT_LABEL = 'Architecture Evolution Blueprint'
|
||||
|
||||
return unless helper.ci?
|
||||
|
||||
blueprint_changes = helper.changed_files(%r{^doc/architecture/blueprints/.*})
|
||||
|
||||
BLUEPRINT_SHORT_MESSAGE = <<~MSG
|
||||
This merge request requires a review from an [Architecture Evolution Coach](https://about.gitlab.com/handbook/engineering/architecture/workflow/).
|
||||
MSG
|
||||
|
||||
BLUEPRINT_LONG_MESSAGE = <<~MSG
|
||||
## Architecture Evolution Review
|
||||
|
||||
#{BLUEPRINT_SHORT_MESSAGE}
|
||||
|
||||
Following files, that may require the additional review, have been changed:
|
||||
#{helper.markdown_list(blueprint_changes.to_set)}
|
||||
MSG
|
||||
|
||||
if blueprint_changes.any?
|
||||
message(BLUEPRINT_SHORT_MESSAGE)
|
||||
markdown(BLUEPRINT_LONG_MESSAGE)
|
||||
|
||||
helper.labels_to_add.push(BLUEPRINT_LABEL) unless helper.mr_has_labels?(BLUEPRINT_LABEL)
|
||||
end
|
||||
|
|
@ -758,7 +758,7 @@ If you are running GitLab 14.4 and earlier:
|
|||
|
||||
To promote the **secondary** cluster to a **primary** cluster, update `role: secondary` to `role: primary`.
|
||||
|
||||
If the cluster remains as a primary site, you can remove the entire `psql` section; it refers to the tracking database and is ignored whilst the cluster is acting as a primary site.
|
||||
If the cluster remains as a primary site, you can remove the entire `psql` section; it refers to the tracking database and is ignored while the cluster is acting as a primary site.
|
||||
|
||||
Update the cluster with the new configuration:
|
||||
|
||||
|
|
|
|||
|
|
@ -212,12 +212,20 @@ It's possible that this limit changes to a lower number in the future.
|
|||
|
||||
## Size of commit titles and descriptions
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292039) in GitLab 13.9
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292039) in GitLab 13.9.
|
||||
|
||||
Commits with arbitrarily large messages may be pushed to GitLab, but when
|
||||
displaying commits, titles (the first line of the commit message)
|
||||
limits to 1KiB, and descriptions (the rest of the message) limits to
|
||||
1MiB.
|
||||
Commits with arbitrarily large messages may be pushed to GitLab, but the following
|
||||
display limits apply:
|
||||
|
||||
- **Title** - The first line of the commit message. Limited to 1 KiB.
|
||||
- **Description** - The rest of the commit message. Limited to 1 MiB.
|
||||
|
||||
When a commit is pushed, GitLab processes the title and description to replace
|
||||
references to issues (`#123`) and merge requests (`!123`) with links to the
|
||||
issues and merge requests.
|
||||
|
||||
When a branch with a large number of commits is pushed, only the last 100 commits
|
||||
are processed.
|
||||
|
||||
## Number of issues in the milestone overview
|
||||
|
||||
|
|
|
|||
|
|
@ -64,5 +64,5 @@ The MemoryKiller is controlled using environment variables.
|
|||
|
||||
If the process hard shutdown/restart is not performed by Sidekiq,
|
||||
the Sidekiq process is forcefully terminated after
|
||||
`Sidekiq.options[:timeout] + 2` seconds. An external supervision mechanism
|
||||
`Sidekiq[:timeout] + 2` seconds. An external supervision mechanism
|
||||
(for example, runit) must restart Sidekiq afterwards.
|
||||
|
|
|
|||
|
|
@ -58,59 +58,6 @@ This section is for links to information elsewhere in the GitLab documentation.
|
|||
some of which is absolutely not for production use. Including:
|
||||
- Understanding EXPLAIN plans.
|
||||
|
||||
### Troubleshooting/Fixes
|
||||
|
||||
- [GitLab database requirements](../../install/requirements.md#database),
|
||||
including
|
||||
- Support for MySQL was removed in GitLab 12.1; [migrate to PostgreSQL](../../update/mysql_to_postgresql.md).
|
||||
- Required extension: `pg_trgm`
|
||||
- Required extension: `btree_gist`
|
||||
|
||||
- Errors like this in the `production/sidekiq` log; see:
|
||||
[Set `default_transaction_isolation` into read committed](https://docs.gitlab.com/omnibus/settings/database.html#set-default_transaction_isolation-into-read-committed):
|
||||
|
||||
```plaintext
|
||||
ActiveRecord::StatementInvalid PG::TRSerializationFailure: ERROR: could not serialize access due to concurrent update
|
||||
```
|
||||
|
||||
- PostgreSQL HA [replication slot errors](https://docs.gitlab.com/omnibus/settings/database.html#troubleshooting-upgrades-in-an-ha-cluster):
|
||||
|
||||
```plaintext
|
||||
pg_basebackup: could not create temporary replication slot "pg_basebackup_12345": ERROR: all replication slots are in use
|
||||
HINT: Free one or increase max_replication_slots.
|
||||
```
|
||||
|
||||
- Geo [replication errors](../geo/replication/troubleshooting.md#fixing-postgresql-database-replication-errors) including:
|
||||
|
||||
```plaintext
|
||||
ERROR: replication slots can only be used if max_replication_slots > 0
|
||||
|
||||
FATAL: could not start WAL streaming: ERROR: replication slot "geo_secondary_my_domain_com" does not exist
|
||||
|
||||
Command exceeded allowed execution time
|
||||
|
||||
PANIC: could not write to file 'pg_xlog/xlogtemp.123': No space left on device
|
||||
```
|
||||
|
||||
- [Checking Geo configuration](../geo/replication/troubleshooting.md), including:
|
||||
- Reconfiguring hosts/ports.
|
||||
- Checking and fixing user/password mappings.
|
||||
|
||||
- [Common Geo errors](../geo/replication/troubleshooting.md#fixing-common-errors).
|
||||
|
||||
- Mismatch in `pg_dump` and `psql` versions:
|
||||
|
||||
```plaintext
|
||||
Dumping PostgreSQL database gitlabhq_production ... pg_dump: error: server version: 13.3; pg_dump version: 14.2
|
||||
pg_dump: error: aborting because of server version mismatch
|
||||
```
|
||||
|
||||
To fix this, see [Backup and restore a non-packaged PostgreSQL database](https://docs.gitlab.com/omnibus/settings/database.html#backup-and-restore-a-non-packaged-postgresql-database).
|
||||
|
||||
- Deploying PostgreSQL on Azure Database for PostgreSQL - Flexible Server may result in an error stating `extension "btree_gist" is not allow-listed for "azure_pg_admin" users in Azure Database for PostgreSQL`
|
||||
|
||||
To resolve the above error, [allow-list the extension](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/concepts-extensions#how-to-use-postgresql-extensions) prior to install.
|
||||
|
||||
## Support topics
|
||||
|
||||
### Database deadlocks
|
||||
|
|
@ -259,3 +206,73 @@ To resolve the error, run `VACUUM` manually:
|
|||
1. In the `backend>` prompt, run `VACUUM;`. This command can take several minutes to complete.
|
||||
1. Wait for the command to complete, then press <kbd>Control</kbd> + <kbd>D</kbd> to exit.
|
||||
1. Start GitLab with the command `gitlab-ctl start`.
|
||||
|
||||
### GitLab database requirements
|
||||
|
||||
The [database requirements](../../install/requirements.md#database) for GitLab include:
|
||||
|
||||
- Support for MySQL was removed in GitLab 12.1; [migrate to PostgreSQL](../../update/mysql_to_postgresql.md).
|
||||
- Review and install the [required extension list](../../install/postgresql_extensions.md).
|
||||
|
||||
### Serialization errors in the `production/sidekiq` log
|
||||
|
||||
If you receive errors like this example in your `production/sidekiq` log, read
|
||||
about [setting `default_transaction_isolation` into read committed](https://docs.gitlab.com/omnibus/settings/database.html#set-default_transaction_isolation-into-read-committed) to fix the problem:
|
||||
|
||||
```plaintext
|
||||
ActiveRecord::StatementInvalid PG::TRSerializationFailure: ERROR: could not serialize access due to concurrent update
|
||||
```
|
||||
|
||||
### PostgreSQL replication slot errors
|
||||
|
||||
If you receive errors like this example, read about how to resolve PostgreSQL HA
|
||||
[replication slot errors](https://docs.gitlab.com/omnibus/settings/database.html#troubleshooting-upgrades-in-an-ha-cluster):
|
||||
|
||||
```plaintext
|
||||
pg_basebackup: could not create temporary replication slot "pg_basebackup_12345": ERROR: all replication slots are in use
|
||||
HINT: Free one or increase max_replication_slots.
|
||||
```
|
||||
|
||||
### Geo replication errors
|
||||
|
||||
If you receive errors like this example, read about how to resolve
|
||||
[Geo replication errors](../geo/replication/troubleshooting.md#fixing-postgresql-database-replication-errors):
|
||||
|
||||
```plaintext
|
||||
ERROR: replication slots can only be used if max_replication_slots > 0
|
||||
|
||||
FATAL: could not start WAL streaming: ERROR: replication slot "geo_secondary_my_domain_com" does not exist
|
||||
|
||||
Command exceeded allowed execution time
|
||||
|
||||
PANIC: could not write to file 'pg_xlog/xlogtemp.123': No space left on device
|
||||
```
|
||||
|
||||
### Review Geo configuration and common errors
|
||||
|
||||
When troubleshooting problems with Geo, you should:
|
||||
|
||||
- Review [common Geo errors](../geo/replication/troubleshooting.md#fixing-common-errors).
|
||||
- [Review your Geo configuration](../geo/replication/troubleshooting.md), including:
|
||||
- Reconfiguring hosts and ports.
|
||||
- Reviewing and fixing the user and password mappings.
|
||||
|
||||
### Mismatch in `pg_dump` and `psql` versions
|
||||
|
||||
If you receive errors like this example, read about how to
|
||||
[back up and restore a non-packaged PostgreSQL database](https://docs.gitlab.com/omnibus/settings/database.html#backup-and-restore-a-non-packaged-postgresql-database):
|
||||
|
||||
```plaintext
|
||||
Dumping PostgreSQL database gitlabhq_production ... pg_dump: error: server version: 13.3; pg_dump version: 14.2
|
||||
pg_dump: error: aborting because of server version mismatch
|
||||
```
|
||||
|
||||
### Extension `btree_gist` is not allow-listed
|
||||
|
||||
Deploying PostgreSQL on an Azure Database for PostgreSQL - Flexible Server may result in this error:
|
||||
|
||||
```plaintext
|
||||
extension "btree_gist" is not allow-listed for "azure_pg_admin" users in Azure Database for PostgreSQL
|
||||
```
|
||||
|
||||
To resolve this error, [allow-list the extension](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/concepts-extensions#how-to-use-postgresql-extensions) prior to install.
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
|
|||
"value": "TEST_1",
|
||||
"protected": false,
|
||||
"masked": false,
|
||||
"raw": false,
|
||||
"environment_scope": "*"
|
||||
},
|
||||
{
|
||||
|
|
@ -40,6 +41,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
|
|||
"value": "TEST_2",
|
||||
"protected": false,
|
||||
"masked": false,
|
||||
"raw": false,
|
||||
"environment_scope": "*"
|
||||
}
|
||||
]
|
||||
|
|
@ -69,6 +71,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
|
|||
"value": "TEST_1",
|
||||
"protected": false,
|
||||
"masked": false,
|
||||
"raw": false,
|
||||
"environment_scope": "*"
|
||||
}
|
||||
```
|
||||
|
|
@ -89,6 +92,7 @@ POST /groups/:id/variables
|
|||
| `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file` |
|
||||
| `protected` | boolean | no | Whether the variable is protected |
|
||||
| `masked` | boolean | no | Whether the variable is masked |
|
||||
| `raw` | boolean | no | Whether the variable is expandable |
|
||||
| `environment_scope` **(PREMIUM)** | string | no | The [environment scope](../ci/variables/index.md#limit-the-environment-scope-of-a-cicd-variable) of a variable |
|
||||
|
||||
```shell
|
||||
|
|
@ -103,6 +107,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
|
|||
"variable_type": "env_var",
|
||||
"protected": false,
|
||||
"masked": false,
|
||||
"raw": false,
|
||||
"environment_scope": "*"
|
||||
}
|
||||
```
|
||||
|
|
@ -123,6 +128,7 @@ PUT /groups/:id/variables/:key
|
|||
| `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file` |
|
||||
| `protected` | boolean | no | Whether the variable is protected |
|
||||
| `masked` | boolean | no | Whether the variable is masked |
|
||||
| `raw` | boolean | no | Whether the variable is expandable |
|
||||
| `environment_scope` **(PREMIUM)** | string | no | The [environment scope](../ci/variables/index.md#limit-the-environment-scope-of-a-cicd-variable) of a variable |
|
||||
|
||||
```shell
|
||||
|
|
@ -137,6 +143,7 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
|
|||
"variable_type": "env_var",
|
||||
"protected": true,
|
||||
"masked": true,
|
||||
"raw": true,
|
||||
"environment_scope": "*"
|
||||
}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -28,14 +28,16 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
|
|||
"variable_type": "env_var",
|
||||
"value": "TEST_1",
|
||||
"protected": false,
|
||||
"masked": false
|
||||
"masked": false,
|
||||
"raw": false
|
||||
},
|
||||
{
|
||||
"key": "TEST_VARIABLE_2",
|
||||
"variable_type": "env_var",
|
||||
"value": "TEST_2",
|
||||
"protected": false,
|
||||
"masked": false
|
||||
"masked": false,
|
||||
"raw": false
|
||||
}
|
||||
]
|
||||
```
|
||||
|
|
@ -62,7 +64,8 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
|
|||
"variable_type": "env_var",
|
||||
"value": "TEST_1",
|
||||
"protected": false,
|
||||
"masked": false
|
||||
"masked": false,
|
||||
"raw": false
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -83,6 +86,7 @@ POST /admin/ci/variables
|
|||
| `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file`. |
|
||||
| `protected` | boolean | no | Whether the variable is protected. |
|
||||
| `masked` | boolean | no | Whether the variable is masked. |
|
||||
| `raw` | boolean | no | Whether the variable is expandable. |
|
||||
|
||||
```shell
|
||||
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
|
||||
|
|
@ -95,7 +99,8 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
|
|||
"value": "new value",
|
||||
"variable_type": "env_var",
|
||||
"protected": false,
|
||||
"masked": false
|
||||
"masked": false,
|
||||
"raw": false
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -114,6 +119,7 @@ PUT /admin/ci/variables/:key
|
|||
| `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file`. |
|
||||
| `protected` | boolean | no | Whether the variable is protected. |
|
||||
| `masked` | boolean | no | Whether the variable is masked. |
|
||||
| `raw` | boolean | no | Whether the variable is expandable. |
|
||||
|
||||
```shell
|
||||
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
|
||||
|
|
@ -126,7 +132,8 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
|
|||
"value": "updated value",
|
||||
"variable_type": "env_var",
|
||||
"protected": true,
|
||||
"masked": true
|
||||
"masked": true,
|
||||
"raw": true
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
|
|||
"value": "TEST_1",
|
||||
"protected": false,
|
||||
"masked": true,
|
||||
"raw": false,
|
||||
"environment_scope": "*"
|
||||
},
|
||||
{
|
||||
|
|
@ -39,6 +40,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
|
|||
"value": "TEST_2",
|
||||
"protected": false,
|
||||
"masked": false,
|
||||
"raw": false,
|
||||
"environment_scope": "*"
|
||||
}
|
||||
]
|
||||
|
|
@ -70,6 +72,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
|
|||
"value": "TEST_1",
|
||||
"protected": false,
|
||||
"masked": true,
|
||||
"raw": false,
|
||||
"environment_scope": "*"
|
||||
}
|
||||
```
|
||||
|
|
@ -92,6 +95,7 @@ POST /projects/:id/variables
|
|||
| `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file` |
|
||||
| `protected` | boolean | no | Whether the variable is protected. Default: `false` |
|
||||
| `masked` | boolean | no | Whether the variable is masked. Default: `false` |
|
||||
| `raw` | boolean | no | Whether the variable is expandable. Default: `false` |
|
||||
| `environment_scope` | string | no | The `environment_scope` of the variable. Default: `*` |
|
||||
|
||||
```shell
|
||||
|
|
@ -106,6 +110,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
|
|||
"value": "new value",
|
||||
"protected": false,
|
||||
"masked": false,
|
||||
"raw": false,
|
||||
"environment_scope": "*"
|
||||
}
|
||||
```
|
||||
|
|
@ -127,6 +132,7 @@ PUT /projects/:id/variables/:key
|
|||
| `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file` |
|
||||
| `protected` | boolean | no | Whether the variable is protected |
|
||||
| `masked` | boolean | no | Whether the variable is masked |
|
||||
| `raw` | boolean | no | Whether the variable is expandable. Default: `false` |
|
||||
| `environment_scope` | string | no | The `environment_scope` of the variable |
|
||||
| `filter` | hash | no | Available filters: `[environment_scope]`. See the [`filter` parameter details](#the-filter-parameter). |
|
||||
|
||||
|
|
@ -142,6 +148,7 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
|
|||
"value": "updated value",
|
||||
"protected": true,
|
||||
"masked": false,
|
||||
"raw": false,
|
||||
"environment_scope": "*"
|
||||
}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -249,3 +249,4 @@ In progress.
|
|||
- 2022-04-30: Additional [benchmarking started](https://gitlab.com/gitlab-org/gitlab/-/issues/361019) to evaluate impact.
|
||||
- 2022-06-31: [Pipeline partitioning design](pipeline_partitioning.md) document [merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87683) merged.
|
||||
- 2022-09-01: Engineering effort started to implement partitioning.
|
||||
- 2022-11-01: The fastest growing CI table partitioned: `ci_builds_metadata`.
|
||||
|
|
|
|||
|
|
@ -1294,15 +1294,25 @@ class MyThingResolver < BaseResolver
|
|||
end
|
||||
```
|
||||
|
||||
The final thing that is needed is that every field that uses this resolver needs
|
||||
to advertise the need for lookahead:
|
||||
The `LooksAhead` concern also provides basic support for preloading associations based on nested GraphQL field
|
||||
definitions. The [WorkItemsResolver](https://gitlab.com/gitlab-org/gitlab/-/blob/e824a7e39e08a83fb162db6851de147cf0bfe14a/app/graphql/resolvers/work_items_resolver.rb#L46)
|
||||
is a good example for this. `nested_preloads` is another method you can define to return a hash, but unlike the
|
||||
`preloads` method, the value for each hash key is another hash and not the list of associations to preload. So in
|
||||
the previous example, you could override `nested_preloads` like this:
|
||||
|
||||
```ruby
|
||||
# in ParentType
|
||||
field :my_things, MyThingType.connection_type, null: true,
|
||||
extras: [:lookahead], # Necessary
|
||||
resolver: MyThingResolver,
|
||||
description: 'My things.'
|
||||
class MyThingResolver < BaseResolver
|
||||
# ...
|
||||
|
||||
def nested_preloads
|
||||
{
|
||||
root_field: {
|
||||
nested_field1: :association_to_preload,
|
||||
nested_field2: [:association1, :association2]
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
For an example of real world use, please
|
||||
|
|
|
|||
|
|
@ -1230,6 +1230,25 @@ Instead of:
|
|||
|
||||
([Vale](../testing.md#vale) rule: [`SubstitutionSuggestions.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/SubstitutionSuggestions.yml))
|
||||
|
||||
## while
|
||||
|
||||
Use **while** to refer only to something occurring in time. For example,
|
||||
**Leave the window open while the process runs.**
|
||||
|
||||
Do not use **while** for comparison. For example, use:
|
||||
|
||||
- Job 1 can run quickly. However, job 2 is more precise.
|
||||
|
||||
Instead of:
|
||||
|
||||
- While job 1 can run quickly, job 2 is more precise.
|
||||
|
||||
For details, see the [Microsoft style guide](https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/w/while).
|
||||
|
||||
## whilst
|
||||
|
||||
Do not use **whilst**. Use [while](#while) instead. **While** is more succinct and easier for non-native English speakers to understand.
|
||||
|
||||
## whitelist
|
||||
|
||||
Do not use **whitelist**. Another option is **allowlist**. ([Vale](../testing.md#vale) rule: [`InclusionCultural.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/InclusionCultural.yml))
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ group: Style Guide
|
|||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
# Tutorial topic type
|
||||
# Tutorial page type
|
||||
|
||||
A tutorial is page that contains an end-to-end walkthrough of a complex workflow or scenario.
|
||||
In general, you might consider using a tutorial when:
|
||||
|
|
@ -77,3 +77,14 @@ you can:
|
|||
- Use future tense from time to time, especially when you're introducing
|
||||
steps. For example, `Next, you will associate your issues with your epics`.
|
||||
- Be more conversational. For example, `This task might take a while to complete`.
|
||||
|
||||
## Metadata
|
||||
|
||||
On pages that are tutorials, add the most appropriate `stage:` and `group:` metadata at the top of the file.
|
||||
If the majority of the content does not align with a single group, specify `none` for the stage
|
||||
and `Tutorials` for the group:
|
||||
|
||||
```plaintext
|
||||
stage: none
|
||||
group: Tutorials
|
||||
```
|
||||
|
|
|
|||
|
|
@ -410,7 +410,7 @@ To subscribe to a label:
|
|||
1. To the right of any label, select **Subscribe**.
|
||||
1. Optional. If you are subscribing to a group label from a project, select either:
|
||||
- **Subscribe at project level** to be notified about events in this project.
|
||||
- **Subscribe at group level**: to be notified about events in the whole group.
|
||||
- **Subscribe at group level** to be notified about events in the whole group.
|
||||
|
||||
## Set label priority
|
||||
|
||||
|
|
|
|||
|
|
@ -59,13 +59,17 @@ module API
|
|||
desc: 'The value of a variable'
|
||||
|
||||
optional :protected,
|
||||
type: String,
|
||||
type: Boolean,
|
||||
desc: 'Whether the variable is protected'
|
||||
|
||||
optional :masked,
|
||||
type: String,
|
||||
type: Boolean,
|
||||
desc: 'Whether the variable is masked'
|
||||
|
||||
optional :raw,
|
||||
type: Boolean,
|
||||
desc: 'Whether the variable will be expanded'
|
||||
|
||||
optional :variable_type,
|
||||
type: String,
|
||||
values: ::Ci::InstanceVariable.variable_types.keys,
|
||||
|
|
@ -99,13 +103,17 @@ module API
|
|||
desc: 'The value of a variable'
|
||||
|
||||
optional :protected,
|
||||
type: String,
|
||||
type: Boolean,
|
||||
desc: 'Whether the variable is protected'
|
||||
|
||||
optional :masked,
|
||||
type: String,
|
||||
type: Boolean,
|
||||
desc: 'Whether the variable is masked'
|
||||
|
||||
optional :raw,
|
||||
type: Boolean,
|
||||
desc: 'Whether the variable will be expanded'
|
||||
|
||||
optional :variable_type,
|
||||
type: String,
|
||||
values: ::Ci::InstanceVariable.variable_types.keys,
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ module API
|
|||
requires :value, type: String, desc: 'The value of the variable'
|
||||
optional :protected, type: Boolean, desc: 'Whether the variable is protected'
|
||||
optional :masked, type: Boolean, desc: 'Whether the variable is masked'
|
||||
optional :raw, type: Boolean, desc: 'Whether the variable will be expanded'
|
||||
optional :variable_type, type: String, values: ::Ci::Variable.variable_types.keys, desc: 'The type of variable, must be one of env_var or file. Defaults to env_var'
|
||||
optional :environment_scope, type: String, desc: 'The environment_scope of the variable'
|
||||
end
|
||||
|
|
@ -81,6 +82,7 @@ module API
|
|||
optional :value, type: String, desc: 'The value of the variable'
|
||||
optional :protected, type: Boolean, desc: 'Whether the variable is protected'
|
||||
optional :masked, type: Boolean, desc: 'Whether the variable is masked'
|
||||
optional :raw, type: Boolean, desc: 'Whether the variable will be expanded'
|
||||
optional :variable_type, type: String, values: ::Ci::Variable.variable_types.keys, desc: 'The type of variable, must be one of env_var or file'
|
||||
optional :environment_scope, type: String, desc: 'The environment_scope of the variable'
|
||||
optional :filter, type: Hash, desc: 'Available filters: [environment_scope]. Example: filter[environment_scope]=production' do
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ module API
|
|||
documentation: { type: 'boolean' }
|
||||
expose :masked?, as: :masked, if: -> (entity, _) { entity.respond_to?(:masked?) },
|
||||
documentation: { type: 'boolean' }
|
||||
expose :raw?, as: :raw, if: -> (entity, _) { entity.respond_to?(:raw?) }, documentation: { type: 'boolean' }
|
||||
expose :environment_scope, if: -> (entity, _) { entity.respond_to?(:environment_scope) },
|
||||
documentation: { type: 'string', example: '*' }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ module API
|
|||
requires :value, type: String, desc: 'The value of the variable'
|
||||
optional :protected, type: String, desc: 'Whether the variable is protected'
|
||||
optional :masked, type: String, desc: 'Whether the variable is masked'
|
||||
optional :raw, type: String, desc: 'Whether the variable will be expanded'
|
||||
optional :variable_type, type: String, values: ::Ci::GroupVariable.variable_types.keys, desc: 'The type of variable, must be one of env_var or file. Defaults to env_var'
|
||||
|
||||
use :optional_group_variable_params_ee
|
||||
|
|
@ -81,6 +82,7 @@ module API
|
|||
optional :value, type: String, desc: 'The value of the variable'
|
||||
optional :protected, type: String, desc: 'Whether the variable is protected'
|
||||
optional :masked, type: String, desc: 'Whether the variable is masked'
|
||||
optional :raw, type: String, desc: 'Whether the variable will be expanded'
|
||||
optional :variable_type, type: String, values: ::Ci::GroupVariable.variable_types.keys, desc: 'The type of variable, must be one of env_var or file'
|
||||
|
||||
use :optional_group_variable_params_ee
|
||||
|
|
|
|||
|
|
@ -534,9 +534,9 @@ module Gitlab
|
|||
# Returns matching refs for OID
|
||||
#
|
||||
# Limit of 0 means there is no limit.
|
||||
def refs_by_oid(oid:, limit: 0)
|
||||
def refs_by_oid(oid:, limit: 0, ref_patterns: nil)
|
||||
wrapped_gitaly_errors do
|
||||
gitaly_ref_client.find_refs_by_oid(oid: oid, limit: limit)
|
||||
gitaly_ref_client.find_refs_by_oid(oid: oid, limit: limit, ref_patterns: ref_patterns)
|
||||
end
|
||||
rescue CommandError, TypeError, NoRepository
|
||||
nil
|
||||
|
|
|
|||
|
|
@ -232,8 +232,8 @@ module Gitlab
|
|||
GitalyClient.call(@storage, :ref_service, :pack_refs, request, timeout: GitalyClient.long_timeout)
|
||||
end
|
||||
|
||||
def find_refs_by_oid(oid:, limit:)
|
||||
request = Gitaly::FindRefsByOIDRequest.new(repository: @gitaly_repo, sort_field: :refname, oid: oid, limit: limit)
|
||||
def find_refs_by_oid(oid:, limit:, ref_patterns: nil)
|
||||
request = Gitaly::FindRefsByOIDRequest.new(repository: @gitaly_repo, sort_field: :refname, oid: oid, limit: limit, ref_patterns: ref_patterns)
|
||||
|
||||
response = GitalyClient.call(@storage, :ref_service, :find_refs_by_oid, request, timeout: GitalyClient.medium_timeout)
|
||||
response&.refs&.to_a
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Patch to address https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1932
|
||||
# It restores the behavior of `poll_internal_average` to the one from Sidekiq 6.4.2
|
||||
# (see https://github.com/mperham/sidekiq/blob/v6.4.2/lib/sidekiq/scheduled.rb#L173-L175)
|
||||
# It restores the behavior of `poll_internal_average` to the one from Sidekiq 6.5.7
|
||||
# when the cron poll interval is not configured.
|
||||
# (see https://github.com/mperham/sidekiq/blob/v6.5.7/lib/sidekiq/scheduled.rb#L176-L178)
|
||||
require 'sidekiq/version'
|
||||
require 'sidekiq/cron/version'
|
||||
|
||||
if Gem::Version.new(Sidekiq::VERSION) != Gem::Version.new('6.4.2')
|
||||
if Gem::Version.new(Sidekiq::VERSION) != Gem::Version.new('6.5.7')
|
||||
raise 'New version of sidekiq detected, please remove or update this patch'
|
||||
end
|
||||
|
||||
|
|
@ -17,11 +18,8 @@ end
|
|||
module Gitlab
|
||||
module Patch
|
||||
module SidekiqCronPoller
|
||||
def poll_interval_average
|
||||
# Note: This diverges from the Sidekiq implementation in 6.4.2 to address a bug where the poll interval wouldn't
|
||||
# scale properly when the process count changes, and to take into account the `cron_poll_interval` setting. See
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/99030#note_1117078517 for more details
|
||||
Gitlab.config.cron_jobs.poll_interval || Sidekiq.options[:poll_interval_average] || scaled_poll_interval
|
||||
def poll_interval_average(count)
|
||||
Gitlab.config.cron_jobs.poll_interval || @config[:poll_interval_average] || scaled_poll_interval(count) # rubocop:disable Gitlab/ModuleWithInstanceVariables
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -68,14 +68,14 @@ module Gitlab
|
|||
|
||||
GEO_NODES_LOAD = 'SELECT 1 AS one FROM "geo_nodes" LIMIT 1'
|
||||
LICENSES_LOAD = 'SELECT "licenses".* FROM "licenses" ORDER BY "licenses"."id"'
|
||||
ATTR_INTROSPECTION = %r/SELECT .*\ba.attname\b.* (FROM|JOIN) pg_attribute a/m.freeze
|
||||
SCHEMA_INTROSPECTION = %r/SELECT.*(FROM|JOIN) (pg_attribute|pg_class)/m.freeze
|
||||
|
||||
# queries can be safely ignored if they are amoritized in regular usage
|
||||
# (i.e. only requested occasionally and otherwise cached).
|
||||
def ignorable?(sql)
|
||||
return true if sql&.include?(GEO_NODES_LOAD)
|
||||
return true if sql&.include?(LICENSES_LOAD)
|
||||
return true if ATTR_INTROSPECTION =~ sql
|
||||
return true if SCHEMA_INTROSPECTION.match?(sql)
|
||||
|
||||
false
|
||||
end
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def sidekiq?
|
||||
!!(defined?(::Sidekiq) && Sidekiq.server?)
|
||||
!!(defined?(::Sidekiq) && Sidekiq.try(:server?))
|
||||
end
|
||||
|
||||
def rake?
|
||||
|
|
@ -94,7 +94,7 @@ module Gitlab
|
|||
#
|
||||
# These threads execute Sidekiq client middleware when jobs
|
||||
# are enqueued and those can access DB / Redis.
|
||||
threads += Sidekiq.options[:concurrency] + 2
|
||||
threads += Sidekiq[:concurrency] + 2
|
||||
end
|
||||
|
||||
if puma?
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ module Gitlab
|
|||
# the current Sidekiq process
|
||||
def current_worker_queue_mappings
|
||||
worker_queue_mappings
|
||||
.select { |worker, queue| Sidekiq.options[:queues].include?(queue) }
|
||||
.select { |worker, queue| Sidekiq[:queues].include?(queue) }
|
||||
.to_h
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -118,9 +118,9 @@ module Gitlab
|
|||
return unless enabled?
|
||||
|
||||
# Tell sidekiq to restart itself
|
||||
# Keep extra safe to wait `Sidekiq.options[:timeout] + 2` seconds before SIGKILL
|
||||
# Keep extra safe to wait `Sidekiq[:timeout] + 2` seconds before SIGKILL
|
||||
refresh_state(:shutting_down)
|
||||
signal_and_wait(Sidekiq.options[:timeout] + 2, 'SIGTERM', 'gracefully shut down')
|
||||
signal_and_wait(Sidekiq[:timeout] + 2, 'SIGTERM', 'gracefully shut down')
|
||||
return unless enabled?
|
||||
|
||||
# Ideally we should never reach this condition
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@
|
|||
module Gitlab
|
||||
module SidekiqMiddleware
|
||||
class ArgumentsLogger
|
||||
include Sidekiq::ServerMiddleware
|
||||
|
||||
def call(worker, job, queue)
|
||||
Sidekiq.logger.info "arguments: #{Gitlab::Json.dump(job['args'])}"
|
||||
logger.info "arguments: #{Gitlab::Json.dump(job['args'])}"
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ module Gitlab
|
|||
def initialize_process_metrics
|
||||
metrics = self.metrics
|
||||
|
||||
metrics[:sidekiq_concurrency].set({}, Sidekiq.options[:concurrency].to_i)
|
||||
metrics[:sidekiq_concurrency].set({}, Sidekiq[:concurrency].to_i)
|
||||
|
||||
return unless ::Feature.enabled?(:sidekiq_job_completion_metric_initialize)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../../migration_helpers'
|
||||
|
||||
module RuboCop
|
||||
module Cop
|
||||
module Migration
|
||||
# Cop that checks that no background batched migration helpers are called by regular migrations.
|
||||
class SchemaAdditionMethodsNoPost < RuboCop::Cop::Base
|
||||
include MigrationHelpers
|
||||
|
||||
MSG = "This method may not be used in post migrations. Please see documentation here: https://docs.gitlab.com/ee/development/migration_style_guide.html#choose-an-appropriate-migration-type"
|
||||
|
||||
FORBIDDEN_METHODS = %w[
|
||||
add_column
|
||||
create_table
|
||||
].freeze
|
||||
|
||||
SYMBOLIZED_MATCHER = FORBIDDEN_METHODS.map { |w| ":#{w}" }.join(' | ')
|
||||
|
||||
def_node_matcher :on_forbidden_method, <<~PATTERN
|
||||
(send nil? {#{SYMBOLIZED_MATCHER}} ...)
|
||||
PATTERN
|
||||
|
||||
def on_send(node)
|
||||
return unless time_enforced?(node)
|
||||
|
||||
on_forbidden_method(node) do
|
||||
add_offense(node, message: MSG)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -49,6 +49,14 @@ module RuboCop
|
|||
dirname(node).end_with?('db/post_migrate', 'db/geo/post_migrate')
|
||||
end
|
||||
|
||||
# Returns true if we've defined an 'EnforcedSince' variable in rubocop.yml and the migration version
|
||||
# is greater.
|
||||
def time_enforced?(node)
|
||||
return false unless enforced_since
|
||||
|
||||
version(node) > enforced_since
|
||||
end
|
||||
|
||||
def version(node)
|
||||
File.basename(node.location.expression.source_buffer.name).split('_').first.to_i
|
||||
end
|
||||
|
|
@ -80,5 +88,9 @@ module RuboCop
|
|||
def rubocop_path
|
||||
File.expand_path(__dir__)
|
||||
end
|
||||
|
||||
def enforced_since
|
||||
@enforced_since ||= config.for_cop(name)['EnforcedSince']
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -252,6 +252,7 @@ FactoryBot.define do
|
|||
transient do
|
||||
create_templates { nil }
|
||||
create_branch { nil }
|
||||
create_tag { nil }
|
||||
end
|
||||
|
||||
after :create do |project, evaluator|
|
||||
|
|
@ -288,6 +289,13 @@ FactoryBot.define do
|
|||
|
||||
end
|
||||
|
||||
if evaluator.create_tag
|
||||
project.repository.add_tag(
|
||||
project.creator,
|
||||
evaluator.create_tag,
|
||||
project.repository.commit.sha)
|
||||
end
|
||||
|
||||
project.track_project_repository
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,9 +6,18 @@
|
|||
"variable_type"
|
||||
],
|
||||
"properties": {
|
||||
"key": { "type": "string" },
|
||||
"value": { "type": "string" },
|
||||
"variable_type": { "type": "string" }
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
},
|
||||
"variable_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"raw": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import Vuex from 'vuex';
|
|||
import { MOCK_QUERY } from 'jest/search/mock_data';
|
||||
import GlobalSearchSidebar from '~/search/sidebar/components/app.vue';
|
||||
import ResultsFilters from '~/search/sidebar/components/results_filters.vue';
|
||||
import ScopeNavigation from '~/search/sidebar/components/scope_navigation.vue';
|
||||
|
||||
Vue.use(Vuex);
|
||||
|
||||
|
|
@ -15,7 +16,7 @@ describe('GlobalSearchSidebar', () => {
|
|||
resetQuery: jest.fn(),
|
||||
};
|
||||
|
||||
const createComponent = (initialState) => {
|
||||
const createComponent = (initialState, featureFlags) => {
|
||||
const store = new Vuex.Store({
|
||||
state: {
|
||||
urlQuery: MOCK_QUERY,
|
||||
|
|
@ -26,6 +27,11 @@ describe('GlobalSearchSidebar', () => {
|
|||
|
||||
wrapper = shallowMount(GlobalSearchSidebar, {
|
||||
store,
|
||||
provide: {
|
||||
glFeatures: {
|
||||
...featureFlags,
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -35,6 +41,7 @@ describe('GlobalSearchSidebar', () => {
|
|||
|
||||
const findSidebarSection = () => wrapper.find('section');
|
||||
const findFilters = () => wrapper.findComponent(ResultsFilters);
|
||||
const findSidebarNavigation = () => wrapper.findComponent(ScopeNavigation);
|
||||
|
||||
describe('renders properly', () => {
|
||||
describe('scope=projects', () => {
|
||||
|
|
@ -78,4 +85,22 @@ describe('GlobalSearchSidebar', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when search_page_vertical_nav is enabled', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({}, { searchPageVerticalNav: true });
|
||||
});
|
||||
it('shows the vertical navigation', () => {
|
||||
expect(findSidebarNavigation().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when search_page_vertical_nav is disabled', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({}, { searchPageVerticalNav: false });
|
||||
});
|
||||
it('hides the vertical navigation', () => {
|
||||
expect(findSidebarNavigation().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -358,7 +358,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::SidekiqServerMiddleware, :clean_
|
|||
end
|
||||
|
||||
def process_job(job)
|
||||
Sidekiq::JobRetry.new.local(worker_class, job.to_json, 'default') do
|
||||
Sidekiq::JobRetry.new(Sidekiq).local(worker_class, job.to_json, 'default') do
|
||||
worker_class.process_job(job)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::GitalyClient::RefService do
|
||||
let_it_be(:project) { create(:project, :repository) }
|
||||
let_it_be(:project) { create(:project, :repository, create_tag: 'test') }
|
||||
|
||||
let(:storage_name) { project.repository_storage }
|
||||
let(:relative_path) { project.disk_path + '.git' }
|
||||
|
|
@ -438,12 +438,28 @@ RSpec.describe Gitlab::GitalyClient::RefService do
|
|||
it 'sends a find_refs_by_oid message' do
|
||||
expect_any_instance_of(Gitaly::RefService::Stub)
|
||||
.to receive(:find_refs_by_oid)
|
||||
.with(gitaly_request_with_params(sort_field: 'refname', oid: oid, limit: 1), kind_of(Hash))
|
||||
.with(gitaly_request_with_params(sort_field: 'refname',
|
||||
oid: oid,
|
||||
limit: 1), kind_of(Hash))
|
||||
.and_call_original
|
||||
|
||||
refs = client.find_refs_by_oid(oid: oid, limit: 1)
|
||||
|
||||
expect(refs.to_a).to eq([Gitlab::Git::BRANCH_REF_PREFIX + project.repository.root_ref])
|
||||
end
|
||||
|
||||
it 'filters by ref_patterns' do
|
||||
expect_any_instance_of(Gitaly::RefService::Stub)
|
||||
.to receive(:find_refs_by_oid)
|
||||
.with(gitaly_request_with_params(sort_field: 'refname',
|
||||
oid: oid,
|
||||
limit: 1,
|
||||
ref_patterns: [Gitlab::Git::TAG_REF_PREFIX]), kind_of(Hash))
|
||||
.and_call_original
|
||||
|
||||
refs = client.find_refs_by_oid(oid: oid, limit: 1, ref_patterns: [Gitlab::Git::TAG_REF_PREFIX])
|
||||
|
||||
expect(refs.to_a).to eq([Gitlab::Git::TAG_REF_PREFIX + 'test'])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -91,6 +91,9 @@ RSpec.describe Gitlab::QueryLimiting::Transaction do
|
|||
SELECT a.attname, a.other_column
|
||||
FROM pg_attribute a
|
||||
SQL
|
||||
transaction.increment(
|
||||
"SELECT a.attnum, a.attname\nFROM pg_attribute a\nWHERE a.attrelid = 10605202\nAND a.attnum IN (3)\n"
|
||||
)
|
||||
end.not_to change(transaction, :count)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ RSpec.describe Gitlab::Runtime do
|
|||
before do
|
||||
stub_const('::Sidekiq', sidekiq_type)
|
||||
allow(sidekiq_type).to receive(:server?).and_return(true)
|
||||
allow(sidekiq_type).to receive(:options).and_return(concurrency: 2)
|
||||
allow(sidekiq_type).to receive(:[]).with(:concurrency).and_return(2)
|
||||
end
|
||||
|
||||
it_behaves_like "valid runtime", :sidekiq, 5
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ RSpec.describe Gitlab::SidekiqConfig do
|
|||
allow(::Gitlab::SidekiqConfig::WorkerRouter)
|
||||
.to receive(:global).and_return(::Gitlab::SidekiqConfig::WorkerRouter.new(test_routes))
|
||||
|
||||
allow(Sidekiq).to receive(:options).and_return(queues: %w[default background_migration])
|
||||
allow(Sidekiq).to receive(:[]).with(:queues).and_return(%w[default background_migration])
|
||||
|
||||
mappings = described_class.current_worker_queue_mappings
|
||||
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
|
|||
stub_const("#{described_class}::CHECK_INTERVAL_SECONDS", check_interval_seconds)
|
||||
stub_const("#{described_class}::GRACE_BALLOON_SECONDS", grace_balloon_seconds)
|
||||
allow(Process).to receive(:getpgrp).and_return(pid)
|
||||
allow(Sidekiq).to receive(:options).and_return(timeout: 9)
|
||||
allow(Sidekiq).to receive(:[]).with(:timeout).and_return(9)
|
||||
end
|
||||
|
||||
it 'return true when everything is within limit', :aggregate_failures do
|
||||
|
|
@ -257,7 +257,7 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
|
|||
before do
|
||||
stub_const("#{described_class}::SHUTDOWN_TIMEOUT_SECONDS", shutdown_timeout_seconds)
|
||||
stub_feature_flags(sidekiq_memory_killer_read_only_mode: false)
|
||||
allow(Sidekiq).to receive(:options).and_return(timeout: 9)
|
||||
allow(Sidekiq).to receive(:[]).with(:timeout).and_return(9)
|
||||
allow(memory_killer).to receive(:get_rss_kb).and_return(100)
|
||||
allow(memory_killer).to receive(:get_soft_limit_rss_kb).and_return(200)
|
||||
allow(memory_killer).to receive(:get_hard_limit_rss_kb).and_return(300)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ RSpec.describe Gitlab::SidekiqMiddleware::ServerMetrics do
|
|||
|
||||
describe '.initialize_process_metrics' do
|
||||
it 'sets concurrency metrics' do
|
||||
expect(concurrency_metric).to receive(:set).with({}, Sidekiq.options[:concurrency].to_i)
|
||||
expect(concurrency_metric).to receive(:set).with({}, Sidekiq[:concurrency].to_i)
|
||||
|
||||
described_class.initialize_process_metrics
|
||||
end
|
||||
|
|
@ -65,7 +65,7 @@ RSpec.describe Gitlab::SidekiqMiddleware::ServerMetrics do
|
|||
end
|
||||
|
||||
it 'sets the concurrency metric' do
|
||||
expect(concurrency_metric).to receive(:set).with({}, Sidekiq.options[:concurrency].to_i)
|
||||
expect(concurrency_metric).to receive(:set).with({}, Sidekiq[:concurrency].to_i)
|
||||
|
||||
described_class.initialize_process_metrics
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ require 'sidekiq/testing'
|
|||
RSpec.describe Gitlab::SidekiqMiddleware do
|
||||
let(:job_args) { [0.01] }
|
||||
let(:disabled_sidekiq_middlewares) { [] }
|
||||
let(:chain) { Sidekiq::Middleware::Chain.new }
|
||||
let(:chain) { Sidekiq::Middleware::Chain.new(Sidekiq) }
|
||||
let(:queue) { 'test' }
|
||||
let(:enabled_sidekiq_middlewares) { all_sidekiq_middlewares - disabled_sidekiq_middlewares }
|
||||
let(:worker_class) do
|
||||
|
|
|
|||
|
|
@ -1323,9 +1323,12 @@ RSpec.describe Deployment do
|
|||
subject { deployment.tags }
|
||||
|
||||
it 'will return tags related to this deployment' do
|
||||
expect(project.repository).to receive(:tag_names_contains).with(deployment.sha, limit: 100).and_return(['test'])
|
||||
expect(project.repository).to receive(:refs_by_oid).with(oid: deployment.sha,
|
||||
limit: 100,
|
||||
ref_patterns: [Gitlab::Git::TAG_REF_PREFIX])
|
||||
.and_return(["#{Gitlab::Git::TAG_REF_PREFIX}test"])
|
||||
|
||||
is_expected.to match_array(['test'])
|
||||
is_expected.to match_array(['refs/tags/test'])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -209,6 +209,10 @@ RSpec.describe PagesDomain do
|
|||
expect(subject.wildcard).to eq(false)
|
||||
end
|
||||
|
||||
it 'defaults auto_ssl_enabled to false' do
|
||||
expect(subject.auto_ssl_enabled).to eq(false)
|
||||
end
|
||||
|
||||
it 'defaults scope to project' do
|
||||
expect(subject.scope).to eq('project')
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@ RSpec.describe ProjectSetting, type: :model do
|
|||
using RSpec::Parameterized::TableSyntax
|
||||
it { is_expected.to belong_to(:project) }
|
||||
|
||||
describe 'default values' do
|
||||
it { expect(subject.legacy_open_source_license_available).to be_truthy }
|
||||
end
|
||||
|
||||
describe 'scopes' do
|
||||
let_it_be(:project_1) { create(:project) }
|
||||
let_it_be(:project_2) { create(:project) }
|
||||
|
|
|
|||
|
|
@ -5,6 +5,16 @@ require 'spec_helper'
|
|||
RSpec.describe ::Serverless::DomainCluster do
|
||||
subject { create(:serverless_domain_cluster) }
|
||||
|
||||
describe 'default values' do
|
||||
subject(:domain_cluster) { build(:serverless_domain_cluster) }
|
||||
|
||||
before do
|
||||
allow(::Serverless::Domain).to receive(:generate_uuid).and_return('randomtoken')
|
||||
end
|
||||
|
||||
it { expect(domain_cluster.uuid).to eq('randomtoken') }
|
||||
end
|
||||
|
||||
describe 'validations' do
|
||||
it { is_expected.to validate_presence_of(:pages_domain) }
|
||||
it { is_expected.to validate_presence_of(:knative) }
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ RSpec.describe Deployments::DeploymentPresenter do
|
|||
|
||||
describe '#tags' do
|
||||
it do
|
||||
expect(deployment).to receive(:tags).and_return(['test'])
|
||||
expect(deployment).to receive(:tags).and_return(['refs/tags/test'])
|
||||
expect(presenter.tags).to eq([{ name: 'test', path: 'tags/test' }])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -71,7 +71,8 @@ RSpec.describe ::API::Admin::Ci::Variables do
|
|||
key: 'TEST_VARIABLE_2',
|
||||
value: 'PROTECTED_VALUE_2',
|
||||
protected: true,
|
||||
masked: true
|
||||
masked: true,
|
||||
raw: true
|
||||
}
|
||||
end.to change { ::Ci::InstanceVariable.count }.by(1)
|
||||
|
||||
|
|
@ -80,6 +81,7 @@ RSpec.describe ::API::Admin::Ci::Variables do
|
|||
expect(json_response['value']).to eq('PROTECTED_VALUE_2')
|
||||
expect(json_response['protected']).to be_truthy
|
||||
expect(json_response['masked']).to be_truthy
|
||||
expect(json_response['raw']).to be_truthy
|
||||
expect(json_response['variable_type']).to eq('env_var')
|
||||
end
|
||||
|
||||
|
|
@ -107,6 +109,7 @@ RSpec.describe ::API::Admin::Ci::Variables do
|
|||
expect(json_response['value']).to eq('VALUE_2')
|
||||
expect(json_response['protected']).to be_falsey
|
||||
expect(json_response['masked']).to be_falsey
|
||||
expect(json_response['raw']).to be_falsey
|
||||
expect(json_response['variable_type']).to eq('file')
|
||||
end
|
||||
|
||||
|
|
@ -162,7 +165,8 @@ RSpec.describe ::API::Admin::Ci::Variables do
|
|||
variable_type: 'file',
|
||||
value: 'VALUE_1_UP',
|
||||
protected: true,
|
||||
masked: true
|
||||
masked: true,
|
||||
raw: true
|
||||
}
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
|
|
@ -170,6 +174,7 @@ RSpec.describe ::API::Admin::Ci::Variables do
|
|||
expect(variable.reload).to be_protected
|
||||
expect(json_response['variable_type']).to eq('file')
|
||||
expect(json_response['masked']).to be_truthy
|
||||
expect(json_response['raw']).to be_truthy
|
||||
end
|
||||
|
||||
it 'masks the new value when logging' do
|
||||
|
|
|
|||
|
|
@ -940,7 +940,12 @@ RSpec.describe API::Ci::Pipelines do
|
|||
subject
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(json_response).to contain_exactly({ "variable_type" => "env_var", "key" => "foo", "value" => "bar" })
|
||||
expect(json_response).to contain_exactly({
|
||||
"variable_type" => "env_var",
|
||||
"key" => "foo",
|
||||
"value" => "bar",
|
||||
"raw" => false
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -961,7 +966,12 @@ RSpec.describe API::Ci::Pipelines do
|
|||
subject
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(json_response).to contain_exactly({ "variable_type" => "env_var", "key" => "foo", "value" => "bar" })
|
||||
expect(json_response).to contain_exactly({
|
||||
"variable_type" => "env_var",
|
||||
"key" => "foo",
|
||||
"value" => "bar",
|
||||
"raw" => false
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ RSpec.describe API::Ci::Variables do
|
|||
expect(json_response['value']).to eq(variable.value)
|
||||
expect(json_response['protected']).to eq(variable.protected?)
|
||||
expect(json_response['masked']).to eq(variable.masked?)
|
||||
expect(json_response['raw']).to eq(variable.raw?)
|
||||
expect(json_response['variable_type']).to eq('env_var')
|
||||
end
|
||||
|
||||
|
|
@ -115,7 +116,7 @@ RSpec.describe API::Ci::Variables do
|
|||
context 'authorized user with proper permissions' do
|
||||
it 'creates variable' do
|
||||
expect do
|
||||
post api("/projects/#{project.id}/variables", user), params: { key: 'TEST_VARIABLE_2', value: 'PROTECTED_VALUE_2', protected: true, masked: true }
|
||||
post api("/projects/#{project.id}/variables", user), params: { key: 'TEST_VARIABLE_2', value: 'PROTECTED_VALUE_2', protected: true, masked: true, raw: true }
|
||||
end.to change { project.variables.count }.by(1)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
|
|
@ -123,6 +124,7 @@ RSpec.describe API::Ci::Variables do
|
|||
expect(json_response['value']).to eq('PROTECTED_VALUE_2')
|
||||
expect(json_response['protected']).to be_truthy
|
||||
expect(json_response['masked']).to be_truthy
|
||||
expect(json_response['raw']).to be_truthy
|
||||
expect(json_response['variable_type']).to eq('env_var')
|
||||
end
|
||||
|
||||
|
|
@ -145,6 +147,7 @@ RSpec.describe API::Ci::Variables do
|
|||
expect(json_response['value']).to eq('VALUE_2')
|
||||
expect(json_response['protected']).to be_falsey
|
||||
expect(json_response['masked']).to be_falsey
|
||||
expect(json_response['raw']).to be_falsey
|
||||
expect(json_response['variable_type']).to eq('file')
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ RSpec.describe API::GroupVariables do
|
|||
|
||||
it 'creates variable' do
|
||||
expect do
|
||||
post api("/groups/#{group.id}/variables", user), params: { key: 'TEST_VARIABLE_2', value: 'PROTECTED_VALUE_2', protected: true, masked: true }
|
||||
post api("/groups/#{group.id}/variables", user), params: { key: 'TEST_VARIABLE_2', value: 'PROTECTED_VALUE_2', protected: true, masked: true, raw: true }
|
||||
end.to change { group.variables.count }.by(1)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
|
|
@ -100,6 +100,7 @@ RSpec.describe API::GroupVariables do
|
|||
expect(json_response['masked']).to be_truthy
|
||||
expect(json_response['variable_type']).to eq('env_var')
|
||||
expect(json_response['environment_scope']).to eq('*')
|
||||
expect(json_response['raw']).to be_truthy
|
||||
end
|
||||
|
||||
it 'masks the new value when logging' do
|
||||
|
|
@ -121,6 +122,7 @@ RSpec.describe API::GroupVariables do
|
|||
expect(json_response['value']).to eq('VALUE_2')
|
||||
expect(json_response['protected']).to be_falsey
|
||||
expect(json_response['masked']).to be_falsey
|
||||
expect(json_response['raw']).to be_falsey
|
||||
expect(json_response['variable_type']).to eq('file')
|
||||
expect(json_response['environment_scope']).to eq('*')
|
||||
end
|
||||
|
|
@ -161,7 +163,7 @@ RSpec.describe API::GroupVariables do
|
|||
initial_variable = group.variables.reload.first
|
||||
value_before = initial_variable.value
|
||||
|
||||
put api("/groups/#{group.id}/variables/#{variable.key}", user), params: { variable_type: 'file', value: 'VALUE_1_UP', protected: true, masked: true }
|
||||
put api("/groups/#{group.id}/variables/#{variable.key}", user), params: { variable_type: 'file', value: 'VALUE_1_UP', protected: true, masked: true, raw: true }
|
||||
|
||||
updated_variable = group.variables.reload.first
|
||||
|
||||
|
|
@ -171,6 +173,7 @@ RSpec.describe API::GroupVariables do
|
|||
expect(updated_variable).to be_protected
|
||||
expect(json_response['variable_type']).to eq('file')
|
||||
expect(json_response['masked']).to be_truthy
|
||||
expect(json_response['raw']).to be_truthy
|
||||
end
|
||||
|
||||
it 'masks the new value when logging' do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/migration/schema_addition_methods_no_post'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Migration::SchemaAdditionMethodsNoPost do
|
||||
before do
|
||||
allow(cop).to receive(:time_enforced?).and_return true
|
||||
end
|
||||
|
||||
it "does not allow 'add_column' to be called" do
|
||||
expect_offense(<<~CODE)
|
||||
add_column
|
||||
^^^^^^^^^^ #{described_class::MSG}
|
||||
CODE
|
||||
end
|
||||
|
||||
it "does not allow 'create_table' to be called" do
|
||||
expect_offense(<<~CODE)
|
||||
create_table
|
||||
^^^^^^^^^^^^ #{described_class::MSG}
|
||||
CODE
|
||||
end
|
||||
end
|
||||
|
|
@ -52,4 +52,21 @@ RSpec.describe RuboCop::MigrationHelpers do
|
|||
|
||||
it { expect(fake_cop.version(node)).to eq(20200210184420) }
|
||||
end
|
||||
|
||||
describe '#time_enforced?' do
|
||||
before do
|
||||
allow(fake_cop).to receive(:name).and_return("TestCop")
|
||||
allow(fake_cop).to receive(:config).and_return(double(for_cop: { 'EnforcedSince' => 20221018000000 }))
|
||||
end
|
||||
|
||||
where(:name, :expected) do
|
||||
'/gitlab/db/post_migrate/20200210184420_create_operations_scopes_table.rb' | false
|
||||
'/gitlab/db/post_migrate/20220210184420_create_fake_table.rb' | false
|
||||
'/gitlab/db/post_migrate/20221019184420_add_id_to_reports_table.rb' | true
|
||||
end
|
||||
|
||||
with_them do
|
||||
it { expect(fake_cop.time_enforced?(node)).to eq(expected) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ RSpec.shared_context 'when handling retried jobs' do |url|
|
|||
'retry' => true
|
||||
)
|
||||
|
||||
allow(klass).to receive(:sidekiq_retry_in_block).and_return(proc { time })
|
||||
allow(klass).to receive(:sidekiq_retry_in_block).and_return(proc { time.to_i })
|
||||
|
||||
begin
|
||||
Sidekiq::JobRetry.new.local(klass, message, klass.queue) { raise 'boom' }
|
||||
Sidekiq::JobRetry.new(Sidekiq).local(klass, message, klass.queue) { raise 'boom' }
|
||||
rescue Sidekiq::JobRetry::Skip
|
||||
# Sidekiq scheduled the retry
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,6 +6,15 @@ require 'sidekiq/testing'
|
|||
module SidekiqMiddleware
|
||||
def with_sidekiq_server_middleware(&block)
|
||||
Sidekiq::Testing.server_middleware.clear
|
||||
|
||||
if Gem::Version.new(Sidekiq::VERSION) != Gem::Version.new('6.5.7')
|
||||
raise 'New version of sidekiq detected, please remove this line'
|
||||
end
|
||||
|
||||
# This line is a workaround for a Sidekiq bug that is already fixed in v7.0.0
|
||||
# https://github.com/mperham/sidekiq/commit/1b83a152786ed382f07fff12d2608534f1e3c922
|
||||
Sidekiq::Testing.server_middleware.instance_variable_set(:@config, Sidekiq)
|
||||
|
||||
Sidekiq::Testing.server_middleware(&block)
|
||||
ensure
|
||||
Sidekiq::Testing.server_middleware.clear
|
||||
|
|
|
|||
Loading…
Reference in New Issue