Skip to content
Snippets Groups Projects
Commit e1443690 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent d466ee50
No related branches found
No related tags found
No related merge requests found
Showing
with 315 additions and 5 deletions
# frozen_string_literal: true
module Environments
class AutoStopCronWorker
include ApplicationWorker
include CronjobQueue # rubocop:disable Scalability/CronWorkerContext
feature_category :continuous_delivery
def perform
return unless Feature.enabled?(:auto_stop_environments)
AutoStopService.new.execute
end
end
end
---
title: 'Geo: Don''t clean up files in object storage when Geo is responsible of syncing
them'
merge_request: 24901
author:
type: fixed
---
title: Fixes a new line issue with suggestions in the last line of a file
merge_request: 22732
author:
type: fixed
---
title: Update broken links to Cloud Run for Anthos documentation
merge_request: 25159
author:
type: fixed
---
title: Create operations strategies and scopes tables
merge_request: 24819
author:
type: added
---
title: Add migration to save Instance Administrators group ID in application_settings table
merge_request: 24796
author:
type: changed
Loading
Loading
@@ -373,6 +373,9 @@ production: &base
# Remove expired build artifacts
expire_build_artifacts_worker:
cron: "50 * * * *"
# Stop expired environments
environments_auto_stop_cron_worker:
cron: "24 * * * *"
# Periodically run 'git fsck' on all repositories. If started more than
# once per hour you will have concurrent 'git fsck' jobs.
repository_check_worker:
Loading
Loading
Loading
Loading
@@ -403,6 +403,9 @@ Settings.cron_jobs['pipeline_schedule_worker']['job_class'] = 'PipelineScheduleW
Settings.cron_jobs['expire_build_artifacts_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['expire_build_artifacts_worker']['cron'] ||= '50 * * * *'
Settings.cron_jobs['expire_build_artifacts_worker']['job_class'] = 'ExpireBuildArtifactsWorker'
Settings.cron_jobs['environments_auto_stop_cron_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['environments_auto_stop_cron_worker']['cron'] ||= '24 * * * *'
Settings.cron_jobs['environments_auto_stop_cron_worker']['job_class'] = 'Environments::AutoStopCronWorker'
Settings.cron_jobs['repository_check_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['repository_check_worker']['cron'] ||= '20 * * * *'
Settings.cron_jobs['repository_check_worker']['job_class'] = 'RepositoryCheck::DispatchWorker'
Loading
Loading
# frozen_string_literal: true
class CreateIndexOnAutoStopIn < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index :environments, %i[state auto_stop_at], where: "auto_stop_at IS NOT NULL AND state = 'available'"
end
def down
remove_concurrent_index :environments, %i[state auto_stop_at]
end
end
# frozen_string_literal: true
class AddFeatureFilterTypeToUserPreferences < ActiveRecord::Migration[6.0]
DOWNTIME = false
def change
add_column :user_preferences, :feature_filter_type, :bigint
end
end
# frozen_string_literal: true
class CreateOperationsStrategiesTable < ActiveRecord::Migration[6.0]
DOWNTIME = false
def change
create_table :operations_strategies do |t|
t.references :feature_flag, index: true, null: false, foreign_key: { to_table: :operations_feature_flags, on_delete: :cascade }
t.string :name, null: false, limit: 255
t.jsonb :parameters, null: false, default: {}
end
end
end
# frozen_string_literal: true
class CreateOperationsScopesTable < ActiveRecord::Migration[6.0]
DOWNTIME = false
def change
create_table :operations_scopes do |t|
t.references :strategy, null: false, index: false, foreign_key: { to_table: :operations_strategies, on_delete: :cascade }
t.string :environment_scope, null: false, limit: 255
end
add_index :operations_scopes, [:strategy_id, :environment_scope], unique: true
end
end
# frozen_string_literal: true
class SaveInstanceAdministratorsGroupId < ActiveRecord::Migration[6.0]
DOWNTIME = false
def up
execute(
<<-SQL
UPDATE
application_settings
SET
instance_administrators_group_id = (
SELECT
namespace_id
FROM
projects
WHERE
id = application_settings.instance_administration_project_id
)
WHERE
instance_administrators_group_id IS NULL
AND
instance_administration_project_id IS NOT NULL
AND
ID in (
SELECT
max(id)
FROM
application_settings
)
SQL
)
end
def down
# no-op
# The change performed by `up` cannot be reversed because once the migration runs,
# we do not know what value application_settings.instance_administrators_group_id
# had before the migration was run.
end
end
Loading
Loading
@@ -1494,10 +1494,12 @@ ActiveRecord::Schema.define(version: 2020_02_12_052620) do
t.string "state", default: "available", null: false
t.string "slug", null: false
t.datetime_with_timezone "auto_stop_at"
t.index ["auto_stop_at"], name: "index_environments_on_auto_stop_at", where: "(auto_stop_at IS NOT NULL)"
t.index ["name"], name: "index_environments_on_name_varchar_pattern_ops", opclass: :varchar_pattern_ops
t.index ["project_id", "name"], name: "index_environments_on_project_id_and_name", unique: true
t.index ["project_id", "slug"], name: "index_environments_on_project_id_and_slug", unique: true
t.index ["project_id", "state", "environment_type"], name: "index_environments_on_project_id_state_environment_type"
t.index ["state", "auto_stop_at"], name: "index_environments_on_state_and_auto_stop_at", where: "((auto_stop_at IS NOT NULL) AND ((state)::text = 'available'::text))"
end
 
create_table "epic_issues", id: :serial, force: :cascade do |t|
Loading
Loading
@@ -2934,6 +2936,19 @@ ActiveRecord::Schema.define(version: 2020_02_12_052620) do
t.index ["project_id", "token_encrypted"], name: "index_feature_flags_clients_on_project_id_and_token_encrypted", unique: true
end
 
create_table "operations_scopes", force: :cascade do |t|
t.bigint "strategy_id", null: false
t.string "environment_scope", limit: 255, null: false
t.index ["strategy_id", "environment_scope"], name: "index_operations_scopes_on_strategy_id_and_environment_scope", unique: true
end
create_table "operations_strategies", force: :cascade do |t|
t.bigint "feature_flag_id", null: false
t.string "name", limit: 255, null: false
t.jsonb "parameters", default: {}, null: false
t.index ["feature_flag_id"], name: "index_operations_strategies_on_feature_flag_id"
end
create_table "packages_build_infos", force: :cascade do |t|
t.integer "package_id", null: false
t.integer "pipeline_id"
Loading
Loading
@@ -4169,6 +4184,7 @@ ActiveRecord::Schema.define(version: 2020_02_12_052620) do
t.boolean "setup_for_company"
t.boolean "render_whitespace_in_code"
t.integer "tab_width", limit: 2
t.bigint "feature_filter_type"
t.index ["user_id"], name: "index_user_preferences_on_user_id", unique: true
end
 
Loading
Loading
@@ -4867,6 +4883,8 @@ ActiveRecord::Schema.define(version: 2020_02_12_052620) do
add_foreign_key "operations_feature_flag_scopes", "operations_feature_flags", column: "feature_flag_id", on_delete: :cascade
add_foreign_key "operations_feature_flags", "projects", on_delete: :cascade
add_foreign_key "operations_feature_flags_clients", "projects", on_delete: :cascade
add_foreign_key "operations_scopes", "operations_strategies", column: "strategy_id", on_delete: :cascade
add_foreign_key "operations_strategies", "operations_feature_flags", column: "feature_flag_id", on_delete: :cascade
add_foreign_key "packages_build_infos", "ci_pipelines", column: "pipeline_id", on_delete: :nullify
add_foreign_key "packages_build_infos", "packages_packages", column: "package_id", on_delete: :cascade
add_foreign_key "packages_conan_file_metadata", "packages_package_files", column: "package_file_id", on_delete: :cascade
Loading
Loading
Loading
Loading
@@ -546,3 +546,8 @@ old method:
- Replication is synchronous and we preserve the order of events.
- Replication of the events happen at the same time as the changes in the
database.
## Self-service framework
If you want to add easy Geo replication of a resource you're working
on, check out our [self-service framework](geo/framework.md).
# Geo self-service framework (alpha)
NOTE: **Note:** This document might be subjected to change. It's a
proposal we're working on and once the implementation is complete this
documentation will be updated. Follow progress in the
[epic](https://gitlab.com/groups/gitlab-org/-/epics/2161).
NOTE: **Note:** The Geo self-service framework is currently in
alpha. If you need to replicate a new data type, reach out to the Geo
team to discuss the options. You can contact them in `#g_geo` on Slack
or mention `@geo-team` in the issue or merge request.
Geo provides an API to make it possible to easily replicate data types
across Geo nodes. This API is presented as a Ruby Domain-Specific
Language (DSL) and aims to make it possible to replicate data with
minimal effort of the engineer who created a data type.
## Nomenclature
Before digging into the API, developers need to know some Geo-specific
naming conventions.
Model
: A model is an Active Model, which is how it is known in the entire
Rails codebase. It usually is tied to a database table. From Geo
perspective, a model can have one or more resources.
Resource
: A resource is a piece of data that belongs to a model and is
produced by a GitLab feature. It is persisted using a storage
mechanism. By default, a resource is not a replicable.
Data type
: Data type is how a resource is stored. Each resource should
fit in one of the data types Geo supports:
:- Git repository
:- Blob
:- Database
: For more detail, see [Data types](../../administration/geo/replication/datatypes.md).
Geo Replicable
: A Replicable is a resource Geo wants to sync across Geo nodes. There
is a limited set of supported data types of replicables. The effort
required to implement replication of a resource that belongs to one
of the known data types is minimal.
Geo Replicator
: A Geo Replicator is the object that knows how to replicate a
replicable. It's responsible for:
:- Firing events (producer)
:- Consuming events (consumer)
: It's tied to the Geo Replicable data type. All replicators have a
common interface that can be used to process (that is, produce and
consume) events. It takes care of the communication between the
primary node (where events are produced) and the secondary node
(where events are consumed). The engineer who wants to incorporate
Geo in their feature will use the API of replicators to make this
happen.
Geo Domain-Specific Language
: The syntactic sugar that allows engineers to easily specify which
resources should be replicated and how.
## Geo Domain-Specific Language
### The replicator
First of all, you need to write a replicator. The replicators live in
[`ee/app/replicators/geo`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/app/replicators/geo).
For each resource that needs to be replicated, there should be a
separate replicator specified, even if multiple resources are tied to
the same model.
For example, the following replicator replicates a package file:
```ruby
module Geo
class PackageFileReplicator < Gitlab::Geo::Replicator
# Include one of the strategies your resource needs
include ::Geo::BlobReplicatorStrategy
# Specify the CarrierWave uploader needed by the used strategy
def carrierwave_uploader
model_record.file
end
private
# Specify the model this replicator belongs to
def model
::Packages::PackageFile
end
end
end
```
The class name should be unique. It also is tightly coupled to the
table name for the registry, so for this example the registry table
will be `package_file_registry`.
For the different data types Geo supports there are different
strategies to include. Pick one that fits your needs.
### Linking to a model
To tie this replicator to the model, you need to add the following to
the model code:
```ruby
class Packages::PackageFile < ApplicationRecord
include ::Gitlab::Geo::ReplicableModel
with_replicator Geo::PackageFileReplicator
end
```
### API
When this is set in place, it's easy to access the replicator through
the model:
```ruby
package_file = Packages::PackageFile.find(4) # just a random id as example
replicator = package_file.replicator
```
Or get the model back from the replicator:
```ruby
replicator.model_record
=> <Packages::PackageFile id:4>
```
The replicator can be used to generate events, for example in
ActiveRecord hooks:
```ruby
after_create_commit -> { replicator.publish_created_event }
```
#### Library
The framework behind all this is located in
[`ee/lib/gitlab/geo/`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/lib/gitlab/geo).
Loading
Loading
@@ -5,7 +5,7 @@ type: reference, howto
# Epics **(PREMIUM)**
 
> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.2.
> In [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/issues/37081), single-level Epics were moved to **(PREMIUM)**.
> In [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/issues/37081), single-level Epics were moved to Premium tier.
 
Epics let you manage your portfolio of projects more efficiently and with less
effort by tracking groups of issues that share a theme, across projects and
Loading
Loading
Loading
Loading
@@ -204,7 +204,7 @@ You can save a copy of a GitLab defined dashboard that can be customized and ada
 
1. Click on the "Duplicate dashboard" in the dashboard dropdown.
 
NOTE:**Note:**
NOTE: **Note:**
Only GitLab-defined dashboards can be duplicated.
 
1. Input the file name and other information, such as a new commit message, and click on "Duplicate".
Loading
Loading
Loading
Loading
@@ -18,7 +18,7 @@ module Gitlab
private
 
def raw_diff
"#{diff_header}\n#{from_content_as_diff}#{to_content_as_diff}"
"#{diff_header}\n#{from_content_as_diff}\n#{to_content_as_diff}"
end
 
def diff_header
Loading
Loading
@@ -26,7 +26,7 @@ module Gitlab
end
 
def from_content_as_diff
from_content.lines.map { |line| line.prepend('-') }.join
from_content.lines.map { |line| line.prepend('-') }.join.delete_suffix("\n")
end
 
def to_content_as_diff
Loading
Loading
Loading
Loading
@@ -20,7 +20,7 @@ module Gitlab
paid_signup_flow: {
feature_toggle: :paid_signup_flow,
environment: ::Gitlab.dev_env_or_com?,
enabled_ratio: 0.25,
enabled_ratio: 0.5,
tracking_category: 'Growth::Acquisition::Experiment::PaidSignUpFlow'
},
suggest_pipeline: {
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment