diff --git a/.gitlab/merge_request_templates/New End To End Test.md b/.gitlab/merge_request_templates/New End To End Test.md
index 4c42b324553..46ccdb1cb0c 100644
--- a/.gitlab/merge_request_templates/New End To End Test.md
+++ b/.gitlab/merge_request_templates/New End To End Test.md
@@ -10,7 +10,10 @@ Please link to the respective test case in the testcases project
- [ ] Note if the test is intended to run in specific scenarios. If a scenario is new, add a link to the MR that adds the new scenario.
- [ ] Follow the end-to-end tests [style guide](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/style_guide.html) and [best practices](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/best_practices.html).
- [ ] Use the appropriate [RSpec metadata tag(s)](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/rspec_metadata_tests.html#rspec-metadata-for-end-to-end-tests).
-- [ ] Ensure that a created resource is removed after test execution. A `Group` resource can be shared between multiple tests. Do not remove it unless it has a unique path. Note that we have a cleanup job that periodically removes groups under `gitlab-qa-sandbox-group`.
+- Most resources will be cleaned up via the general [cleanup task](https://gitlab.com/gitlab-org/gitlab/-/blob/44345381e89d6bbd440f7b4c680d03e8b75b86de/qa/qa/tools/test_resources_handler.rb#L44). Check that is successful, or ensure resources are cleaned up in the test:
+ - [ ] New resources have `api_get_path` and `api_delete_path` implemented if possible.
+ - [ ] If any resource cannot be deleted in the general delete task, make sure it is [ignored](https://gitlab.com/gitlab-org/gitlab/-/blob/44345381e89d6bbd440f7b4c680d03e8b75b86de/qa/qa/tools/test_resources_handler.rb#L29).
+ - [ ] If any resource cannot be deleted in the general delete task, remove it in the test (e.g., in an `after` block).
- [ ] Ensure that no [transient bugs](https://about.gitlab.com/handbook/engineering/quality/issue-triage/#transient-bugs) are hidden accidentally due to the usage of `waits` and `reloads`.
- [ ] Verify the tags to ensure it runs on the desired test environments.
- [ ] If this MR has a dependency on another MR, such as a GitLab QA MR, specify the order in which the MRs should be merged.
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index e9517fdb50c..208c7a3ab24 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-c54d613d0eb9c573d79f5da0975655f11f007932
+0c72a4ba3de2125098d72fce52b99df3d4ad5475
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index adc3a912a91..976241a5149 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -38,6 +38,7 @@ class Projects::PipelinesController < Projects::ApplicationController
track_redis_hll_event :charts, name: 'p_analytics_ci_cd_pipelines', if: -> { should_track_ci_cd_pipelines? }
track_redis_hll_event :charts, name: 'p_analytics_ci_cd_deployment_frequency', if: -> { should_track_ci_cd_deployment_frequency? }
track_redis_hll_event :charts, name: 'p_analytics_ci_cd_lead_time', if: -> { should_track_ci_cd_lead_time? }
+ track_redis_hll_event :charts, name: 'p_analytics_ci_cd_time_to_restore_service', if: -> { should_track_ci_cd_time_to_restore_service? }
wrap_parameters Ci::Pipeline
@@ -361,6 +362,10 @@ class Projects::PipelinesController < Projects::ApplicationController
def should_track_ci_cd_lead_time?
params[:chart] == 'lead-time'
end
+
+ def should_track_ci_cd_time_to_restore_service?
+ params[:chart] == 'time-to-restore-service'
+ end
end
Projects::PipelinesController.prepend_mod_with('Projects::PipelinesController')
diff --git a/app/graphql/types/ci/runner_upgrade_status_type_enum.rb b/app/graphql/types/ci/runner_upgrade_status_type_enum.rb
index 02feafe3df9..7c52ab5562a 100644
--- a/app/graphql/types/ci/runner_upgrade_status_type_enum.rb
+++ b/app/graphql/types/ci/runner_upgrade_status_type_enum.rb
@@ -5,9 +5,9 @@ module Types
class RunnerUpgradeStatusTypeEnum < BaseEnum
graphql_name 'CiRunnerUpgradeStatusType'
- value 'UNKNOWN', description: 'Upgrade status is unknown.', value: :unknown
+ ::Ci::RunnerVersion::STATUS_DESCRIPTIONS.each do |status, description|
+ status = :invalid if status == :invalid_version
- Gitlab::Ci::RunnerUpgradeCheck::STATUSES.each do |status, description|
value status.to_s.upcase, description: description, value: status
end
end
diff --git a/app/models/ci/runner_version.rb b/app/models/ci/runner_version.rb
new file mode 100644
index 00000000000..ddbfad08cbb
--- /dev/null
+++ b/app/models/ci/runner_version.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Ci
+ class RunnerVersion < Ci::ApplicationRecord
+ include EnumWithNil
+
+ enum_with_nil status: {
+ not_processed: nil,
+ invalid_version: -1,
+ unknown: 0,
+ not_available: 1,
+ available: 2,
+ recommended: 3
+ }
+
+ STATUS_DESCRIPTIONS = {
+ invalid_version: 'Runner version is not valid.',
+ unknown: 'Upgrade status is unknown.',
+ not_available: 'Upgrade is not available for the runner.',
+ available: 'Upgrade is available for the runner.',
+ recommended: 'Upgrade is available and recommended for the runner.'
+ }.freeze
+
+ # Override auto generated negative scope (from available) so the scope has expected behavior
+ scope :not_available, -> { where(status: :not_available) }
+
+ validates :version, length: { maximum: 2048 }
+ end
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index 40096dfa411..b35036d0af7 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -476,8 +476,8 @@ class User < ApplicationRecord
end
scope :order_recent_sign_in, -> { reorder(arel_table[:current_sign_in_at].desc.nulls_last) }
scope :order_oldest_sign_in, -> { reorder(arel_table[:current_sign_in_at].asc.nulls_last) }
- scope :order_recent_last_activity, -> { reorder(arel_table[:last_activity_on].desc.nulls_last) }
- scope :order_oldest_last_activity, -> { reorder(arel_table[:last_activity_on].asc.nulls_first) }
+ scope :order_recent_last_activity, -> { reorder(arel_table[:last_activity_on].desc.nulls_last, arel_table[:id].asc) }
+ scope :order_oldest_last_activity, -> { reorder(arel_table[:last_activity_on].asc.nulls_first, arel_table[:id].desc) }
scope :by_id_and_login, ->(id, login) { where(id: id).where('username = LOWER(:login) OR email = LOWER(:login)', login: login) }
scope :dormant, -> { with_state(:active).human_or_service_user.where('last_activity_on <= ?', MINIMUM_INACTIVE_DAYS.day.ago.to_date) }
scope :with_no_activity, -> { with_state(:active).human_or_service_user.where(last_activity_on: nil).where('created_at <= ?', MINIMUM_DAYS_CREATED.day.ago.to_date) }
diff --git a/config/initializers/1_acts_as_taggable.rb b/config/initializers/1_acts_as_taggable.rb
index 59412aef755..0c34bf3941b 100644
--- a/config/initializers/1_acts_as_taggable.rb
+++ b/config/initializers/1_acts_as_taggable.rb
@@ -15,3 +15,36 @@ raise "Counter cache is not disabled" if
model.connection_specification_name = Ci::ApplicationRecord.connection_specification_name
model.singleton_class.delegate :connection, :sticking, to: '::Ci::ApplicationRecord'
end
+
+# Modified from https://github.com/mbleigh/acts-as-taggable-on/pull/1081
+# with insert_all, which is not supported in MySQL
+# See https://gitlab.com/gitlab-org/gitlab/-/issues/338346#note_996969960
+module ActsAsTaggableOnTagPatch
+ def find_or_create_all_with_like_by_name(*list)
+ list = Array(list).flatten
+
+ return [] if list.empty?
+
+ existing_tags = named_any(list)
+
+ missing = list.reject do |tag_name|
+ comparable_tag_name = comparable_name(tag_name)
+ existing_tags.find { |tag| comparable_name(tag.name) == comparable_tag_name }
+ end
+
+ if missing.empty?
+ new_tags = []
+ else
+ attributes_to_add = missing.map do |tag_name|
+ { name: tag_name }
+ end
+
+ insert_all(attributes_to_add, unique_by: :name)
+ new_tags = named_any(missing)
+ end
+
+ existing_tags + new_tags
+ end
+end
+
+::ActsAsTaggableOn::Tag.singleton_class.prepend(ActsAsTaggableOnTagPatch)
diff --git a/config/metrics/counts_28d/20210216174910_analytics_unique_visits_for_any_target_monthly.yml b/config/metrics/counts_28d/20210216174910_analytics_unique_visits_for_any_target_monthly.yml
index ceb185c7108..c8cb9693a7f 100644
--- a/config/metrics/counts_28d/20210216174910_analytics_unique_visits_for_any_target_monthly.yml
+++ b/config/metrics/counts_28d/20210216174910_analytics_unique_visits_for_any_target_monthly.yml
@@ -33,6 +33,11 @@ options:
- p_analytics_ci_cd_pipelines
- p_analytics_ci_cd_deployment_frequency
- p_analytics_ci_cd_lead_time
+ - p_analytics_ci_cd_time_to_restore_service
+ - g_analytics_ci_cd_release_statistics
+ - g_analytics_ci_cd_deployment_frequency
+ - g_analytics_ci_cd_lead_time
+ - g_analytics_ci_cd_time_to_restore_service
distribution:
- ce
- ee
diff --git a/config/metrics/counts_28d/20220622084700_p_analytics_ci_cd_time_to_restore_service_monthly.yml b/config/metrics/counts_28d/20220622084700_p_analytics_ci_cd_time_to_restore_service_monthly.yml
new file mode 100644
index 00000000000..a9a62b1aa79
--- /dev/null
+++ b/config/metrics/counts_28d/20220622084700_p_analytics_ci_cd_time_to_restore_service_monthly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.analytics.p_analytics_ci_cd_time_to_restore_service_monthly
+name: p_analytics_ci_cd_time_to_restore_service_monthly
+description: Count of unique visits to the project level CI/CD Analytics Time to restore service tab
+product_section: dev
+product_stage: manage
+product_group: optimize
+product_category:
+value_type: number
+status: active
+milestone: "15.2"
+introduced_by_url:
+time_frame: 28d
+data_source: redis_hll
+data_category: operational
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- premium
+- ultimate
+options:
+ events:
+ - p_analytics_ci_cd_time_to_restore_service
diff --git a/config/metrics/counts_7d/20220622084654_p_analytics_ci_cd_time_to_restore_service_weekly.yml b/config/metrics/counts_7d/20220622084654_p_analytics_ci_cd_time_to_restore_service_weekly.yml
new file mode 100644
index 00000000000..681fed23d11
--- /dev/null
+++ b/config/metrics/counts_7d/20220622084654_p_analytics_ci_cd_time_to_restore_service_weekly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.analytics.p_analytics_ci_cd_time_to_restore_service_weekly
+name: p_analytics_ci_cd_time_to_restore_service_weekly
+description: Count of unique visits to the project level CI/CD Analytics Time to restore service tab
+product_section: dev
+product_stage: manage
+product_group: optimize
+product_category:
+value_type: number
+status: active
+milestone: "15.2"
+introduced_by_url:
+time_frame: 7d
+data_source: redis_hll
+data_category: operational
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- premium
+- ultimate
+options:
+ events:
+ - p_analytics_ci_cd_time_to_restore_service
diff --git a/db/docs/ci_runner_versions.yml b/db/docs/ci_runner_versions.yml
new file mode 100644
index 00000000000..e0221e3956f
--- /dev/null
+++ b/db/docs/ci_runner_versions.yml
@@ -0,0 +1,9 @@
+---
+table_name: ci_runner_versions
+classes:
+- Ci::RunnerVersion
+feature_categories:
+- runner_fleet
+description: Information about used Ci::Runner versions
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90982
+milestone: '15.2'
diff --git a/db/migrate/20220624081524_add_ci_runner_versions_table.rb b/db/migrate/20220624081524_add_ci_runner_versions_table.rb
new file mode 100644
index 00000000000..844c5898d75
--- /dev/null
+++ b/db/migrate/20220624081524_add_ci_runner_versions_table.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddCiRunnerVersionsTable < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def up
+ create_table :ci_runner_versions, id: false do |t|
+ t.text :version, primary_key: true, index: true, null: false, limit: 2048
+ t.integer :status, null: true, limit: 2, index: true
+ end
+ end
+
+ def down
+ drop_table :ci_runner_versions, if_exists: true
+ end
+end
diff --git a/db/migrate/20220624090458_add_index_on_runner_version.rb b/db/migrate/20220624090458_add_index_on_runner_version.rb
new file mode 100644
index 00000000000..e28bf0d8a76
--- /dev/null
+++ b/db/migrate/20220624090458_add_index_on_runner_version.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexOnRunnerVersion < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_ci_runners_on_version'
+
+ def up
+ add_concurrent_index :ci_runners, :version, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :ci_runners, INDEX_NAME
+ end
+end
diff --git a/db/schema_migrations/20220624081524 b/db/schema_migrations/20220624081524
new file mode 100644
index 00000000000..f643b1223a8
--- /dev/null
+++ b/db/schema_migrations/20220624081524
@@ -0,0 +1 @@
+3245905956e4781629bbf6398c9534cf35eab469e8a703f755ed26de90dee0e1
\ No newline at end of file
diff --git a/db/schema_migrations/20220624090458 b/db/schema_migrations/20220624090458
new file mode 100644
index 00000000000..62473bf8bd3
--- /dev/null
+++ b/db/schema_migrations/20220624090458
@@ -0,0 +1 @@
+cf3c6e8d720ce48272b8b9658d3c240e8fe3c9a26284a9e169f7bb6a40c862bc
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 78ba17044d4..e511bd88618 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -13080,6 +13080,12 @@ CREATE SEQUENCE ci_runner_projects_id_seq
ALTER SEQUENCE ci_runner_projects_id_seq OWNED BY ci_runner_projects.id;
+CREATE TABLE ci_runner_versions (
+ version text NOT NULL,
+ status smallint,
+ CONSTRAINT check_b5a3714594 CHECK ((char_length(version) <= 2048))
+);
+
CREATE TABLE ci_runners (
id integer NOT NULL,
token character varying,
@@ -24577,6 +24583,9 @@ ALTER TABLE ONLY ci_runner_namespaces
ALTER TABLE ONLY ci_runner_projects
ADD CONSTRAINT ci_runner_projects_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_runner_versions
+ ADD CONSTRAINT ci_runner_versions_pkey PRIMARY KEY (version);
+
ALTER TABLE ONLY ci_runners
ADD CONSTRAINT ci_runners_pkey PRIMARY KEY (id);
@@ -27633,6 +27642,10 @@ CREATE UNIQUE INDEX index_ci_runner_namespaces_on_runner_id_and_namespace_id ON
CREATE INDEX index_ci_runner_projects_on_project_id ON ci_runner_projects USING btree (project_id);
+CREATE INDEX index_ci_runner_versions_on_status ON ci_runner_versions USING btree (status);
+
+CREATE INDEX index_ci_runner_versions_on_version ON ci_runner_versions USING btree (version);
+
CREATE INDEX index_ci_runners_on_active ON ci_runners USING btree (active, id);
CREATE INDEX index_ci_runners_on_contacted_at_and_id_desc ON ci_runners USING btree (contacted_at, id DESC);
@@ -27663,6 +27676,8 @@ CREATE INDEX index_ci_runners_on_token_expires_at_and_id_desc ON ci_runners USIN
CREATE INDEX index_ci_runners_on_token_expires_at_desc_and_id_desc ON ci_runners USING btree (token_expires_at DESC, id DESC);
+CREATE INDEX index_ci_runners_on_version ON ci_runners USING btree (version);
+
CREATE UNIQUE INDEX index_ci_running_builds_on_build_id ON ci_running_builds USING btree (build_id);
CREATE INDEX index_ci_running_builds_on_project_id ON ci_running_builds USING btree (project_id);
diff --git a/doc/administration/logs.md b/doc/administration/logs.md
index 5a2c1190896..671c264ed85 100644
--- a/doc/administration/logs.md
+++ b/doc/administration/logs.md
@@ -1063,23 +1063,23 @@ For Omnibus GitLab installations, Mattermost logs are in these locations:
## Workhorse Logs
-For Omnibus GitLab installations, Workhorse logs are in `/var/log/gitlab/gitlab-workhorse/`.
+For Omnibus GitLab installations, Workhorse logs are in `/var/log/gitlab/gitlab-workhorse/current`.
## PostgreSQL Logs
-For Omnibus GitLab installations, PostgreSQL logs are in `/var/log/gitlab/postgresql/`.
+For Omnibus GitLab installations, PostgreSQL logs are in `/var/log/gitlab/postgresql/current`.
## Prometheus Logs
-For Omnibus GitLab installations, Prometheus logs are in `/var/log/gitlab/prometheus/`.
+For Omnibus GitLab installations, Prometheus logs are in `/var/log/gitlab/prometheus/current`.
## Redis Logs
-For Omnibus GitLab installations, Redis logs are in `/var/log/gitlab/redis/`.
+For Omnibus GitLab installations, Redis logs are in `/var/log/gitlab/redis/current`.
## Alertmanager Logs
-For Omnibus GitLab installations, Alertmanager logs are in `/var/log/gitlab/alertmanager/`.
+For Omnibus GitLab installations, Alertmanager logs are in `/var/log/gitlab/alertmanager/current`.
@@ -1091,11 +1091,11 @@ For Omnibus GitLab installations, crond logs are in `/var/log/gitlab/crond/`.
## Grafana Logs
-For Omnibus GitLab installations, Grafana logs are in `/var/log/gitlab/grafana/`.
+For Omnibus GitLab installations, Grafana logs are in `/var/log/gitlab/grafana/current`.
## LogRotate Logs
-For Omnibus GitLab installations, `logrotate` logs are in `/var/log/gitlab/logrotate/`.
+For Omnibus GitLab installations, `logrotate` logs are in `/var/log/gitlab/logrotate/current`.
## GitLab Monitor Logs
@@ -1103,12 +1103,12 @@ For Omnibus GitLab installations, GitLab Monitor logs are in `/var/log/gitlab/gi
## GitLab Exporter
-For Omnibus GitLab installations, GitLab Exporter logs are in `/var/log/gitlab/gitlab-exporter/`.
+For Omnibus GitLab installations, GitLab Exporter logs are in `/var/log/gitlab/gitlab-exporter/current`.
## GitLab agent server
For Omnibus GitLab installations, GitLab agent server logs are
-in `/var/log/gitlab/gitlab-kas/`.
+in `/var/log/gitlab/gitlab-kas/current`.
## Praefect Logs
diff --git a/doc/development/i18n/externalization.md b/doc/development/i18n/externalization.md
index 2aea15de443..18704fc2b60 100644
--- a/doc/development/i18n/externalization.md
+++ b/doc/development/i18n/externalization.md
@@ -411,6 +411,56 @@ use `%{created_at}` in Ruby but `%{createdAt}` in JavaScript. Make sure to
// => When x == 2: 'Last 2 days'
```
+- In Vue:
+
+ One of [the recommended ways to organize translated strings for Vue files](#vue-files) is to extract them into a `constants.js` file.
+ That can be difficult to do when there are pluralized strings because the `count` variable won't be known inside the constants file.
+ To overcome this, we recommend creating a function which takes a `count` argument:
+
+ ```javascript
+ // .../feature/constants.js
+ import { n__ } from '~/locale';
+
+ export const I18N = {
+ // Strings that are only singular don't need to be a function
+ someDaysRemain: __('Some days remain'),
+ daysRemaining(count) { return n__('%d day remaining', '%d days remaining', count); },
+ };
+ ```
+
+ Then within a Vue component the function can be used to retrieve the correct pluralization form of the string:
+
+ ```javascript
+ // .../feature/components/days_remaining.vue
+ import { sprintf } from '~/locale';
+ import { I18N } from '../constants';
+
+
+
+
+ gradlew file, then the analyzer automatically switches to one of the
pre-installed Gradle versions, based on the version of Java specified by the
DS_JAVA_VERSION variable.
+ By default, the analyzer uses Java 17 and Gradle 7.3.3.
You can view the - Gradle Java compatibility matrix to see which version - of Gradle is selected for each Java version. Note that we only support switching to one of these pre-installed Gradle versions - for Java versions 13 to 17. +
+ For Java versions 8 and 11, Gradle 6.7.1 is automatically selected, and for Java versions 13 to 17, Gradle 7.3.3 is automatically selected.