summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-10-29 15:09:12 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-10-29 15:09:12 +0000
commit4dfd78cb55b08ab20124187d1aab6a431da3e302 (patch)
treea14b0086833e11b88bc023455b7c1bc8d8dbc5f4
parent5a7d44a955572b912d13ba8949e976f61b5c7f1b (diff)
downloadgitlab-ce-4dfd78cb55b08ab20124187d1aab6a431da3e302.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/CODEOWNERS29
-rw-r--r--app/assets/javascripts/reports/components/grouped_test_reports_app.vue12
-rw-r--r--app/assets/javascripts/reports/components/report_section.vue1
-rw-r--r--app/assets/javascripts/single_file_diff.js7
-rw-r--r--app/helpers/ci/runners_helper.rb8
-rw-r--r--app/models/ci/daily_build_group_report_result.rb9
-rw-r--r--app/models/pages_deployment.rb2
-rw-r--r--app/models/project.rb7
-rw-r--r--app/services/ci/append_build_trace_service.rb65
-rw-r--r--app/services/pages/destroy_deployments_service.rb16
-rw-r--r--app/services/projects/update_pages_service.rb12
-rw-r--r--app/services/projects/update_repository_storage_service.rb16
-rw-r--r--app/views/admin/health_check/show.html.haml2
-rw-r--r--app/views/admin/system_info/show.html.haml4
-rw-r--r--app/views/projects/environments/show.html.haml1
-rw-r--r--app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml5
-rw-r--r--app/views/projects/no_repo.html.haml7
-rw-r--r--app/views/projects/pages/_ssl_limitations_warning.html.haml2
-rw-r--r--app/views/projects/pages_domains/_lets_encrypt_callout.html.haml2
-rw-r--r--app/views/shared/boards/components/sidebar/_assignee.html.haml2
-rw-r--r--app/views/shared/boards/components/sidebar/_due_date.html.haml2
-rw-r--r--app/views/shared/boards/components/sidebar/_labels.html.haml2
-rw-r--r--app/views/shared/boards/components/sidebar/_milestone.html.haml2
-rw-r--r--app/workers/all_queues.yml8
-rw-r--r--app/workers/destroy_pages_deployments_worker.rb19
-rwxr-xr-xbin/mail_room3
-rwxr-xr-xbin/web_unicorn3
-rw-r--r--changelogs/unreleased/224509-replace-board-sidebar-chevron.yml5
-rw-r--r--changelogs/unreleased/225180-replace-fa-warning-icons-with-gitlab-svg-warning-solid-icon.yml5
-rw-r--r--changelogs/unreleased/ImproveShellScriptsVariable.yml5
-rw-r--r--changelogs/unreleased/add-ci-status-css-to-environments.yml5
-rw-r--r--changelogs/unreleased/allow_repo_storage_moves_without_repo.yml5
-rw-r--r--config/sidekiq_queues.yml2
-rw-r--r--doc/api/graphql/reference/gitlab_schema.graphql91
-rw-r--r--doc/api/graphql/reference/gitlab_schema.json252
-rw-r--r--doc/api/graphql/reference/index.md11
-rw-r--r--doc/architecture/blueprints/cloud_native_build_logs/index.md3
-rw-r--r--doc/architecture/blueprints/cloud_native_gitlab_pages/index.md3
-rw-r--r--doc/architecture/blueprints/feature_flags_development/index.md3
-rw-r--r--doc/architecture/blueprints/image_resizing/index.md3
-rw-r--r--doc/architecture/index.md3
-rw-r--r--doc/ci/lint.md6
-rw-r--r--doc/downgrade_ee_to_ce/README.md6
-rw-r--r--doc/install/digitaloceandocker.md3
-rw-r--r--doc/install/pivotal/index.md6
-rw-r--r--doc/install/postgresql_extensions.md6
-rw-r--r--doc/integration/README.md3
-rw-r--r--doc/integration/akismet.md6
-rw-r--r--doc/integration/auth0.md6
-rw-r--r--doc/integration/azure.md6
-rw-r--r--doc/integration/bitbucket.md6
-rw-r--r--doc/integration/cas.md6
-rw-r--r--doc/integration/external-issue-tracker.md6
-rw-r--r--doc/integration/facebook.md6
-rw-r--r--doc/integration/github.md6
-rw-r--r--doc/integration/gitlab.md6
-rw-r--r--doc/integration/gmail_action_buttons_for_gitlab.md6
-rw-r--r--doc/integration/google.md6
-rw-r--r--doc/integration/jenkins.md6
-rw-r--r--doc/integration/jenkins_deprecated.md6
-rw-r--r--doc/integration/oauth2_generic.md6
-rw-r--r--doc/integration/oauth_provider.md6
-rw-r--r--doc/integration/omniauth.md6
-rw-r--r--doc/integration/openid_connect_provider.md6
-rw-r--r--doc/integration/recaptcha.md6
-rw-r--r--doc/integration/salesforce.md6
-rw-r--r--doc/integration/shibboleth.md6
-rw-r--r--doc/integration/slash_commands.md6
-rw-r--r--doc/integration/trello_power_up.md6
-rw-r--r--doc/integration/twitter.md6
-rw-r--r--doc/user/analytics/merge_request_analytics.md8
-rw-r--r--doc/user/group/saml_sso/index.md2
-rw-r--r--lib/api/ci/runner.rb27
-rw-r--r--lib/gitlab/badge/coverage/report.rb12
-rw-r--r--locale/gitlab.pot3
-rw-r--r--spec/frontend/reports/components/grouped_test_reports_app_spec.js31
-rw-r--r--spec/models/ci/daily_build_group_report_result_spec.rb34
-rw-r--r--spec/models/pages_deployment_spec.rb13
-rw-r--r--spec/models/project_spec.rb23
-rw-r--r--spec/services/ci/append_build_trace_service_spec.rb57
-rw-r--r--spec/services/pages/destroy_deployments_service_spec.rb29
-rw-r--r--spec/services/projects/update_pages_service_spec.rb23
-rw-r--r--spec/services/projects/update_repository_storage_service_spec.rb18
-rw-r--r--spec/workers/destroy_pages_deployments_worker_spec.rb38
84 files changed, 1069 insertions, 61 deletions
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index 5187ac01b58..a24fef5e44d 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -207,6 +207,35 @@ Dangerfile @gl-quality/eng-prod
/ee/lib/gitlab/ci/reports/license_scanning/ @gitlab-org/secure/composition-analysis-be
/ee/lib/gitlab/ci/reports/security/ @gitlab-org/secure/composition-analysis-be @gitlab-org/secure/dynamic-analysis-be @gitlab-org/secure/static-analysis-be @gitlab-org/secure/fuzzing-be
+[Container Security]
+/ee/app/views/projects/threat_monitoring/** @gitlab-org/threat-management/defend/container-security/frontend
+/ee/app/assets/javascripts/pages/projects/threat_monitoring/** @gitlab-org/threat-management/defend/container-security/frontend
+/ee/app/assets/javascripts/threat_monitoring/** @gitlab-org/threat-management/defend/container-security/frontend
+/ee/spec/frontend/threat_monitoring/** @gitlab-org/threat-management/defend/container-security/frontend
+
+/ee/app/controllers/projects/threat_monitoring_controller.rb @gitlab-org/threat-management/defend/container-security/backend
+/ee/spec/controllers/projects/threat_monitoring_controller_spec.rb @gitlab-org/threat-management/defend/container-security/backend
+/lib/gitlab/kubernetes/cilium_network_policy.rb @gitlab-org/threat-management/defend/container-security/backend
+/spec/lib/gitlab/kubernetes/cilium_network_policy_spec.rb @gitlab-org/threat-management/defend/container-security/backend
+/lib/gitlab/kubernetes/network_policy_common.rb @gitlab-org/threat-management/defend/container-security/backend
+/spec/support/shared_examples/lib/gitlab/kubernetes/network_policy_common_shared_examples.rb @gitlab-org/threat-management/defend/container-security/backend
+/lib/gitlab/kubernetes/network_policy.rb @gitlab-org/threat-management/defend/container-security/backend
+/spec/lib/gitlab/kubernetes/network_policy_spec.rb @gitlab-org/threat-management/defend/container-security/backend
+/ee/app/services/network_policies/** @gitlab-org/threat-management/defend/container-security/backend
+/ee/spec/services/network_policies/** @gitlab-org/threat-management/defend/container-security/backend
+/ee/app/controllers/projects/security/waf_anomalies_controller.rb @gitlab-org/threat-management/defend/container-security/backend
+/ee/spec/controllers/projects/security/waf_anomalies_controller_spec.rb @gitlab-org/threat-management/defend/container-security/backend
+/app/models/clusters/applications/cilium.rb @gitlab-org/threat-management/defend/container-security/backend
+/spec/models/clusters/applications/cilium_spec.rb @gitlab-org/threat-management/defend/container-security/backend
+/ee/app/controllers/projects/security/network_policies_controller.rb @gitlab-org/threat-management/defend/container-security/backend
+/ee/spec/controllers/projects/security/network_policies_controller_spec.rb @gitlab-org/threat-management/defend/container-security/backend
+/ee/app/workers/network_policy_metrics_worker.rb @gitlab-org/threat-management/defend/container-security/backend
+/ee/spec/workers/network_policy_metrics_worker_spec.rb @gitlab-org/threat-management/defend/container-security/backend
+/ee/app/services/network_policies/** @gitlab-org/threat-management/defend/container-security/backend
+/ee/spec/services/network_policies/** @gitlab-org/threat-management/defend/container-security/backend
+/ee/lib/gitlab/usage_data_counters/network_policy_counter.rb @gitlab-org/threat-management/defend/container-security/backend
+/ee/spec/lib/gitlab/usage_data_counters/network_policy_counter_spec.rb @gitlab-org/threat-management/defend/container-security/backend
+
[Code Owners]
/ee/lib/gitlab/code_owners.rb @reprazent @kerrizor @garyh
/ee/lib/gitlab/code_owners/ @reprazent @kerrizor @garyh
diff --git a/app/assets/javascripts/reports/components/grouped_test_reports_app.vue b/app/assets/javascripts/reports/components/grouped_test_reports_app.vue
index 47f04019595..29378aebdd2 100644
--- a/app/assets/javascripts/reports/components/grouped_test_reports_app.vue
+++ b/app/assets/javascripts/reports/components/grouped_test_reports_app.vue
@@ -1,5 +1,6 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
+import { once } from 'lodash';
import { GlButton } from '@gitlab/ui';
import { sprintf, s__ } from '~/locale';
import { componentNames } from './issue_body';
@@ -8,6 +9,7 @@ import SummaryRow from './summary_row.vue';
import IssuesList from './issues_list.vue';
import Modal from './modal.vue';
import createStore from '../store';
+import Tracking from '~/tracking';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { summaryTextBuilder, reportTextBuilder, statusIcon } from '../store/utils';
@@ -21,7 +23,7 @@ export default {
Modal,
GlButton,
},
- mixins: [glFeatureFlagsMixin()],
+ mixins: [glFeatureFlagsMixin(), Tracking.mixin()],
props: {
endpoint: {
type: String,
@@ -58,6 +60,11 @@ export default {
showViewFullReport() {
return this.pipelinePath.length;
},
+ handleToggleEvent() {
+ return once(() => {
+ this.track(this.$options.expandEvent);
+ });
+ },
},
created() {
this.setEndpoint(this.endpoint);
@@ -102,6 +109,7 @@ export default {
return report.resolved_failures.concat(report.resolved_errors);
},
},
+ expandEvent: 'expand_test_report_widget',
};
</script>
<template>
@@ -111,7 +119,9 @@ export default {
:loading-text="groupedSummaryText"
:error-text="groupedSummaryText"
:has-issues="reports.length > 0"
+ :should-emit-toggle-event="true"
class="mr-widget-section grouped-security-reports mr-report"
+ @toggleEvent="handleToggleEvent"
>
<template v-if="showViewFullReport" #actionButtons>
<gl-button
diff --git a/app/assets/javascripts/reports/components/report_section.vue b/app/assets/javascripts/reports/components/report_section.vue
index 63af8a5a9ac..cf5c0ceadfe 100644
--- a/app/assets/javascripts/reports/components/report_section.vue
+++ b/app/assets/javascripts/reports/components/report_section.vue
@@ -189,6 +189,7 @@ export default {
<button
v-if="isCollapsible"
type="button"
+ data-testid="report-section-expand-button"
class="js-collapse-btn btn float-right btn-sm align-self-center qa-expand-report-button"
@click="toggleCollapsed"
>
diff --git a/app/assets/javascripts/single_file_diff.js b/app/assets/javascripts/single_file_diff.js
index 5fa6cef7195..3492f19c996 100644
--- a/app/assets/javascripts/single_file_diff.js
+++ b/app/assets/javascripts/single_file_diff.js
@@ -7,11 +7,14 @@ import { deprecatedCreateFlash as createFlash } from './flash';
import FilesCommentButton from './files_comment_button';
import initImageDiffHelper from './image_diff/helpers/init_image_diff';
import syntaxHighlight from './syntax_highlight';
+import { spriteIcon } from '~/lib/utils/common_utils';
const WRAPPER = '<div class="diff-content"></div>';
const LOADING_HTML = '<span class="spinner"></span>';
-const ERROR_HTML =
- '<div class="nothing-here-block"><i class="fa fa-warning"></i> Could not load diff</div>';
+const ERROR_HTML = `<div class="nothing-here-block">${spriteIcon(
+ 'warning-solid',
+ 's16',
+)} Could not load diff</div>`;
const COLLAPSED_HTML =
'<div class="nothing-here-block diff-collapsed">This diff is collapsed. <button class="click-to-expand btn btn-link">Click to expand it.</button></div>';
diff --git a/app/helpers/ci/runners_helper.rb b/app/helpers/ci/runners_helper.rb
index 552acf61f47..432aad663e4 100644
--- a/app/helpers/ci/runners_helper.rb
+++ b/app/helpers/ci/runners_helper.rb
@@ -2,13 +2,15 @@
module Ci
module RunnersHelper
+ include IconsHelper
+
def runner_status_icon(runner)
status = runner.status
case status
when :not_connected
- content_tag :i, nil,
- class: "fa fa-warning",
- title: "New runner. Has not connected yet"
+ content_tag(:span, title: "New runner. Has not connected yet") do
+ sprite_icon("warning-solid", size: 24, css_class: "gl-vertical-align-bottom!")
+ end
when :online, :offline, :paused
content_tag :i, nil,
diff --git a/app/models/ci/daily_build_group_report_result.rb b/app/models/ci/daily_build_group_report_result.rb
index c829ee57b37..e9f3366b939 100644
--- a/app/models/ci/daily_build_group_report_result.rb
+++ b/app/models/ci/daily_build_group_report_result.rb
@@ -4,6 +4,7 @@ module Ci
class DailyBuildGroupReportResult < ApplicationRecord
extend Gitlab::Ci::Model
+ REPORT_WINDOW = 90.days
PARAM_TYPES = %w[coverage].freeze
belongs_to :last_pipeline, class_name: 'Ci::Pipeline', foreign_key: :last_pipeline_id
@@ -15,6 +16,7 @@ module Ci
scope :by_projects, -> (ids) { where(project_id: ids) }
scope :with_coverage, -> { where("(data->'coverage') IS NOT NULL") }
scope :with_default_branch, -> { where(default_branch: true) }
+ scope :by_date, -> (start_date) { where(date: report_window(start_date)..Date.current) }
store_accessor :data, :coverage
@@ -26,6 +28,13 @@ module Ci
def recent_results(attrs, limit: nil)
where(attrs).order(date: :desc, group_name: :asc).limit(limit)
end
+
+ def report_window(start_date)
+ default_date = REPORT_WINDOW.ago.to_date
+ date = Date.parse(start_date) rescue default_date
+
+ [date, default_date].max
+ end
end
end
end
diff --git a/app/models/pages_deployment.rb b/app/models/pages_deployment.rb
index 08e541f3b93..fb13dbfb8ca 100644
--- a/app/models/pages_deployment.rb
+++ b/app/models/pages_deployment.rb
@@ -7,6 +7,8 @@ class PagesDeployment < ApplicationRecord
belongs_to :project, optional: false
belongs_to :ci_build, class_name: 'Ci::Build', optional: true
+ scope :older_than, -> (id) { where('id < ?', id) }
+
validates :file, presence: true
validates :file_store, presence: true, inclusion: { in: ObjectStorage::SUPPORTED_STORES }
validates :size, presence: true, numericality: { greater_than: 0, only_integer: true }
diff --git a/app/models/project.rb b/app/models/project.rb
index c43f78f3db9..7e4ec6c7036 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -346,7 +346,8 @@ class Project < ApplicationRecord
# GitLab Pages
has_many :pages_domains
has_one :pages_metadatum, class_name: 'ProjectPagesMetadatum', inverse_of: :project
- has_many :pages_deployments
+ # we need to clean up files, not only remove records
+ has_many :pages_deployments, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
# Can be too many records. We need to implement delete_all in batches.
# Issue https://gitlab.com/gitlab-org/gitlab/-/issues/228637
@@ -1801,6 +1802,8 @@ class Project < ApplicationRecord
mark_pages_as_not_deployed unless destroyed?
+ DestroyPagesDeploymentsWorker.perform_async(id)
+
# 1. We rename pages to temporary directory
# 2. We wait 5 minutes, due to NFS caching
# 3. We asynchronously remove pages with force
@@ -1817,7 +1820,7 @@ class Project < ApplicationRecord
end
def mark_pages_as_not_deployed
- ensure_pages_metadatum.update!(deployed: false, artifacts_archive: nil)
+ ensure_pages_metadatum.update!(deployed: false, artifacts_archive: nil, pages_deployment: nil)
end
def write_repository_config(gl_full_path: full_path)
diff --git a/app/services/ci/append_build_trace_service.rb b/app/services/ci/append_build_trace_service.rb
new file mode 100644
index 00000000000..602f8c5030d
--- /dev/null
+++ b/app/services/ci/append_build_trace_service.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+module Ci
+ class AppendBuildTraceService
+ Result = Struct.new(:status, :stream_size, keyword_init: true)
+ TraceRangeError = Class.new(StandardError)
+
+ attr_reader :build, :params
+
+ def initialize(build, params)
+ @build = build
+ @params = params
+ end
+
+ def execute(body_data)
+ # TODO:
+ # it seems that `Content-Range` as formatted by runner is wrong,
+ # the `byte_end` should point to final byte, but it points byte+1
+ # that means that we have to calculate end of body,
+ # as we cannot use `content_length[1]`
+ # Issue: https://gitlab.com/gitlab-org/gitlab-runner/issues/3275
+
+ content_range = stream_range.split('-')
+ body_start = content_range[0].to_i
+ body_end = body_start + body_data.bytesize
+
+ stream_size = build.trace.append(body_data, body_start)
+
+ unless stream_size == body_end
+ log_range_error(stream_size, body_end)
+
+ return Result.new(status: 416, stream_size: stream_size)
+ end
+
+ Result.new(status: 202, stream_size: stream_size)
+ end
+
+ private
+
+ def stream_range
+ params.fetch(:content_range)
+ end
+
+ def log_range_error(stream_size, body_end)
+ extra = {
+ build_id: build.id,
+ body_end: body_end,
+ stream_size: stream_size,
+ stream_class: stream_size.class,
+ stream_range: stream_range
+ }
+
+ build.trace_chunks.last.try do |chunk|
+ extra.merge!(
+ chunk_index: chunk.chunk_index,
+ chunk_store: chunk.data_store,
+ chunks_count: build.trace_chunks.count
+ )
+ end
+
+ ::Gitlab::ErrorTracking
+ .log_exception(TraceRangeError.new, extra)
+ end
+ end
+end
diff --git a/app/services/pages/destroy_deployments_service.rb b/app/services/pages/destroy_deployments_service.rb
new file mode 100644
index 00000000000..45d906bec7a
--- /dev/null
+++ b/app/services/pages/destroy_deployments_service.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Pages
+ class DestroyDeploymentsService
+ def initialize(project, last_deployment_id = nil)
+ @project = project
+ @last_deployment_id = last_deployment_id
+ end
+
+ def execute
+ deployments_to_destroy = @project.pages_deployments
+ deployments_to_destroy = deployments_to_destroy.older_than(@last_deployment_id) if @last_deployment_id
+ deployments_to_destroy.find_each(&:destroy) # rubocop: disable CodeReuse/ActiveRecord
+ end
+ end
+end
diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb
index d64ad693c6c..9a1e6595a76 100644
--- a/app/services/projects/update_pages_service.rb
+++ b/app/services/projects/update_pages_service.rb
@@ -12,6 +12,11 @@ module Projects
# as it shares the namespace with groups
TMP_EXTRACT_PATH = '@pages.tmp'
+ # old deployment can be cached by pages daemon
+ # so we need to give pages daemon some time update cache
+ # 10 minutes is enough, but 30 feels safer
+ OLD_DEPLOYMENTS_DESTRUCTION_DELAY = 30.minutes.freeze
+
attr_reader :build
def initialize(project, build)
@@ -128,6 +133,7 @@ module Projects
entries_count = build.artifacts_metadata_entry("", recursive: true).entries.count
sha256 = build.job_artifacts_archive.file_sha256
+ deployment = nil
File.open(artifacts_path) do |file|
deployment = project.pages_deployments.create!(file: file,
file_count: entries_count,
@@ -135,7 +141,11 @@ module Projects
project.pages_metadatum.update!(pages_deployment: deployment)
end
- # TODO: schedule old deployment removal https://gitlab.com/gitlab-org/gitlab/-/issues/235730
+ DestroyPagesDeploymentsWorker.perform_in(
+ OLD_DEPLOYMENTS_DESTRUCTION_DELAY,
+ project.id,
+ deployment.id
+ )
rescue => e
# we don't want to break current pages deployment process if something goes wrong
# TODO: remove this rescue as part of https://gitlab.com/gitlab-org/gitlab/-/issues/245308
diff --git a/app/services/projects/update_repository_storage_service.rb b/app/services/projects/update_repository_storage_service.rb
index a479d53a43a..e0d2398bc66 100644
--- a/app/services/projects/update_repository_storage_service.rb
+++ b/app/services/projects/update_repository_storage_service.rb
@@ -54,7 +54,7 @@ module Projects
end
def mirror_repositories
- mirror_repository
+ mirror_repository if project.repository_exists?
if project.wiki.repository_exists?
mirror_repository(type: Gitlab::GlRepository::WIKI)
@@ -92,12 +92,14 @@ module Projects
end
def remove_old_paths
- Gitlab::Git::Repository.new(
- source_storage_name,
- "#{project.disk_path}.git",
- nil,
- nil
- ).remove
+ if project.repository_exists?
+ Gitlab::Git::Repository.new(
+ source_storage_name,
+ "#{project.disk_path}.git",
+ nil,
+ nil
+ ).remove
+ end
if project.wiki.repository_exists?
Gitlab::Git::Repository.new(
diff --git a/app/views/admin/health_check/show.html.haml b/app/views/admin/health_check/show.html.haml
index 76e4fa971a3..78f0fd325fb 100644
--- a/app/views/admin/health_check/show.html.haml
+++ b/app/views/admin/health_check/show.html.haml
@@ -30,7 +30,7 @@
= sprite_icon('check', css_class: 'cgreen')
#{ s_('HealthCheck|Healthy') }
- else
- = icon('warning', class: 'cred')
+ = sprite_icon('warning-solid', css_class: 'cred')
#{ s_('HealthCheck|Unhealthy') }
.card-body
- if no_errors
diff --git a/app/views/admin/system_info/show.html.haml b/app/views/admin/system_info/show.html.haml
index 312ca62cfdf..ca6efe9b095 100644
--- a/app/views/admin/system_info/show.html.haml
+++ b/app/views/admin/system_info/show.html.haml
@@ -9,7 +9,7 @@
- if @cpus
%h2= _('%{cores} cores') % { cores: @cpus.length }
- else
- = icon('warning', class: 'text-warning')
+ = sprite_icon('warning-solid', css_class: 'text-warning')
= _('Unable to collect CPU info')
.bg-light.light-well.gl-mt-3
%h4= _('Memory Usage')
@@ -17,7 +17,7 @@
- if @memory
%h2 #{number_to_human_size(@memory.active_bytes)} / #{number_to_human_size(@memory.total_bytes)}
- else
- = icon('warning', class: 'text-warning')
+ = sprite_icon('warning-solid', css_class: 'text-warning')
= _('Unable to collect memory info')
.bg-light.light-well.gl-mt-3
%h4= _('Uptime')
diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml
index a9667cf8a2f..0cb44bd03fb 100644
--- a/app/views/projects/environments/show.html.haml
+++ b/app/views/projects/environments/show.html.haml
@@ -3,6 +3,7 @@
- page_title _("Environments")
- add_page_specific_style 'page_bundles/xterm'
- add_page_specific_style 'page_bundles/environments'
+- add_page_specific_style 'page_bundles/ci_status'
#environments-detail-view{ data: { name: @environment.name, id: @environment.id, delete_path: environment_delete_path(@environment)} }
- if @environment.available? && can?(current_user, :stop_environment, @environment)
diff --git a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
index e341831e17d..1d9aad81a9e 100644
--- a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
+++ b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
@@ -19,7 +19,7 @@
- if ref
- if generic_commit_status.ref
.icon-container
- = generic_commit_status.tags.any? ? icon('tag') : sprite_icon('fork', size: 10)
+ = generic_commit_status.tags.any? ? sprite_icon('tag', size: 10) : sprite_icon('fork', size: 10)
= link_to generic_commit_status.ref, project_commits_path(generic_commit_status.project, generic_commit_status.ref)
- else
.light none
@@ -30,7 +30,8 @@
= link_to generic_commit_status.short_sha, project_commit_path(generic_commit_status.project, generic_commit_status.sha), class: "commit-sha"
- if retried
- = icon('warning', class: 'text-warning has-tooltip', title: 'Status was retried.')
+ %span.has-tooltip{ title: _('Status was retried.') }
+ = sprite_icon('warning-solid', class: 'text-warning')
.label-container
- if generic_commit_status.tags.any?
diff --git a/app/views/projects/no_repo.html.haml b/app/views/projects/no_repo.html.haml
index c44d3da23bb..8631f03cc1b 100644
--- a/app/views/projects/no_repo.html.haml
+++ b/app/views/projects/no_repo.html.haml
@@ -1,9 +1,10 @@
- breadcrumb_title _("Details")
- page_title _("Details")
-%h2
- %i.fa.fa-warning
- #{ _('No repository') }
+%h2.gl-display-flex
+ .gl-display-flex.gl-align-items-center.gl-justify-content-center
+ = sprite_icon('warning-solid', size: 24, css_class: 'gl-mr-2')
+ = _('No repository')
%p.slead
#{ _('The repository for this project does not exist.') }
diff --git a/app/views/projects/pages/_ssl_limitations_warning.html.haml b/app/views/projects/pages/_ssl_limitations_warning.html.haml
index 7188e169824..1f2907d183e 100644
--- a/app/views/projects/pages/_ssl_limitations_warning.html.haml
+++ b/app/views/projects/pages/_ssl_limitations_warning.html.haml
@@ -1,5 +1,5 @@
.bs-callout.bs-callout-warning
- %i.fa.fa-warning
+ = sprite_icon("warning-solid", css_class: "gl-text-orange-600")
%strong= _("Warning:")
- pages_host = Gitlab.config.pages.host
= s_("GitLabPages|When using Pages under the general domain of a GitLab instance (%{pages_host}), you cannot use HTTPS with sub-subdomains. This means that if your username/groupname contains a dot it will not work. This is a limitation of the HTTP Over TLS protocol. HTTP pages will continue to work provided you don't redirect HTTP to HTTPS.").html_safe % { pages_host: pages_host }
diff --git a/app/views/projects/pages_domains/_lets_encrypt_callout.html.haml b/app/views/projects/pages_domains/_lets_encrypt_callout.html.haml
index a86637c36b3..9072312c100 100644
--- a/app/views/projects/pages_domains/_lets_encrypt_callout.html.haml
+++ b/app/views/projects/pages_domains/_lets_encrypt_callout.html.haml
@@ -6,7 +6,7 @@
.col-sm-10.offset-sm-2
.bs-callout.bs-callout-warning.mt-0
.row.align-items-center.mx-2
- = icon('warning', class: 'mr-2')
+ = sprite_icon('warning-solid', css_class: ' mr-2 gl-text-orange-600')
= _("Something went wrong while obtaining the Let's Encrypt certificate.")
.row.mx-0.mt-3
= link_to s_('GitLabPagesDomains|Retry'), retry_auto_ssl_project_pages_domain_path(@project, domain_presenter), class: "btn btn-sm btn-grouped btn-warning", method: :post
diff --git a/app/views/shared/boards/components/sidebar/_assignee.html.haml b/app/views/shared/boards/components/sidebar/_assignee.html.haml
index af6a519a967..e22a7807b3b 100644
--- a/app/views/shared/boards/components/sidebar/_assignee.html.haml
+++ b/app/views/shared/boards/components/sidebar/_assignee.html.haml
@@ -23,7 +23,7 @@
%button.dropdown-menu-toggle.js-user-search.js-author-search.js-multiselect.js-save-user-data.js-issue-board-sidebar{ type: 'button', ref: 'assigneeDropdown', data: board_sidebar_user_data,
":data-issuable-id" => "issue.iid" }
= dropdown_options[:title]
- = icon("chevron-down")
+ = sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
.dropdown-menu.dropdown-select.dropdown-menu-user.dropdown-menu-selectable.dropdown-menu-author
= dropdown_title("Assign to")
= dropdown_filter("Search users")
diff --git a/app/views/shared/boards/components/sidebar/_due_date.html.haml b/app/views/shared/boards/components/sidebar/_due_date.html.haml
index d8ed3b13bf1..ab4d22ac03d 100644
--- a/app/views/shared/boards/components/sidebar/_due_date.html.haml
+++ b/app/views/shared/boards/components/sidebar/_due_date.html.haml
@@ -24,7 +24,7 @@
%button.dropdown-menu-toggle.js-due-date-select.js-issue-boards-due-date{ type: 'button',
data: { toggle: 'dropdown', field_name: "issue[due_date]", ability_name: "issue" } }
%span.dropdown-toggle-text= _("Due date")
- = icon('chevron-down')
+ = sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
.dropdown-menu.dropdown-menu-due-date
= dropdown_title(_('Due date'))
= dropdown_content do
diff --git a/app/views/shared/boards/components/sidebar/_labels.html.haml b/app/views/shared/boards/components/sidebar/_labels.html.haml
index 61f3ebcdba4..5af52d4de23 100644
--- a/app/views/shared/boards/components/sidebar/_labels.html.haml
+++ b/app/views/shared/boards/components/sidebar/_labels.html.haml
@@ -27,7 +27,7 @@
data: label_dropdown_data(@project, namespace_path: @namespace_path, field_name: "issue[label_names][]") }
%span.dropdown-toggle-text
{{ labelDropdownTitle }}
- = icon('chevron-down')
+ = sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
.dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable.dropdown-extended-height
= render partial: "shared/issuable/label_page_default"
- if can?(current_user, :admin_label, current_board_parent)
diff --git a/app/views/shared/boards/components/sidebar/_milestone.html.haml b/app/views/shared/boards/components/sidebar/_milestone.html.haml
index 2c894e9b1b3..6143f1d5afe 100644
--- a/app/views/shared/boards/components/sidebar/_milestone.html.haml
+++ b/app/views/shared/boards/components/sidebar/_milestone.html.haml
@@ -21,7 +21,7 @@
":data-issuable-id" => "issue.iid",
":data-project-id" => "issue.project_id" }
= _("Milestone")
- = icon("chevron-down")
+ = sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
.dropdown-menu.dropdown-select.dropdown-menu-selectable
= dropdown_title(_("Assign milestone"))
= dropdown_filter(_("Search milestones"))
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index 7f5fca18c4c..f7ba8eb09a0 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -1425,6 +1425,14 @@
:weight: 1
:idempotent:
:tags: []
+- :name: destroy_pages_deployments
+ :feature_category: :pages
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: detect_repository_languages
:feature_category: :source_code_management
:has_external_dependencies:
diff --git a/app/workers/destroy_pages_deployments_worker.rb b/app/workers/destroy_pages_deployments_worker.rb
new file mode 100644
index 00000000000..32b539325c9
--- /dev/null
+++ b/app/workers/destroy_pages_deployments_worker.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class DestroyPagesDeploymentsWorker
+ include ApplicationWorker
+
+ idempotent!
+
+ loggable_arguments 0, 1
+ sidekiq_options retry: 3
+ feature_category :pages
+
+ def perform(project_id, last_deployment_id = nil)
+ project = Project.find_by_id(project_id)
+
+ return unless project
+
+ ::Pages::DestroyDeploymentsService.new(project, last_deployment_id).execute
+ end
+end
diff --git a/bin/mail_room b/bin/mail_room
index 2539e3d388e..be608be4229 100755
--- a/bin/mail_room
+++ b/bin/mail_room
@@ -9,7 +9,8 @@ mail_room_config="$app_root/config/mail_room.yml"
get_mail_room_pid()
{
- local pid=$(cat $mail_room_pidfile)
+ local pid
+ pid=$(cat $mail_room_pidfile)
if [ -z "$pid" ] ; then
echo "Could not find a PID in $mail_room_pidfile"
exit 1
diff --git a/bin/web_unicorn b/bin/web_unicorn
index ecd0bbd10b0..41e2ac44351 100755
--- a/bin/web_unicorn
+++ b/bin/web_unicorn
@@ -9,7 +9,8 @@ unicorn_cmd="bundle exec unicorn_rails -c $unicorn_config -E $RAILS_ENV"
get_unicorn_pid()
{
- local pid=$(cat $unicorn_pidfile)
+ local pid
+ pid=$(cat $unicorn_pidfile)
if [ -z "$pid" ] ; then
echo "Could not find a PID in $unicorn_pidfile"
exit 1
diff --git a/changelogs/unreleased/224509-replace-board-sidebar-chevron.yml b/changelogs/unreleased/224509-replace-board-sidebar-chevron.yml
new file mode 100644
index 00000000000..395d0499abf
--- /dev/null
+++ b/changelogs/unreleased/224509-replace-board-sidebar-chevron.yml
@@ -0,0 +1,5 @@
+---
+title: Replace chevron-down fa-icon in board sidebar
+merge_request: 46075
+author:
+type: other
diff --git a/changelogs/unreleased/225180-replace-fa-warning-icons-with-gitlab-svg-warning-solid-icon.yml b/changelogs/unreleased/225180-replace-fa-warning-icons-with-gitlab-svg-warning-solid-icon.yml
new file mode 100644
index 00000000000..67ecca873d8
--- /dev/null
+++ b/changelogs/unreleased/225180-replace-fa-warning-icons-with-gitlab-svg-warning-solid-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-warning icons with GitLab SVG warning-solid icon
+merge_request: 46214
+author:
+type: changed
diff --git a/changelogs/unreleased/ImproveShellScriptsVariable.yml b/changelogs/unreleased/ImproveShellScriptsVariable.yml
new file mode 100644
index 00000000000..d95f93b6f7d
--- /dev/null
+++ b/changelogs/unreleased/ImproveShellScriptsVariable.yml
@@ -0,0 +1,5 @@
+---
+title: Declare and assign variable separately in Shell Script
+merge_request: 46121
+author: Peter Dave Hello @PeterDaveHello
+type: other
diff --git a/changelogs/unreleased/add-ci-status-css-to-environments.yml b/changelogs/unreleased/add-ci-status-css-to-environments.yml
new file mode 100644
index 00000000000..2ea47f432e1
--- /dev/null
+++ b/changelogs/unreleased/add-ci-status-css-to-environments.yml
@@ -0,0 +1,5 @@
+---
+title: Add CI Status CSS to the Environments Page
+merge_request: 46382
+author:
+type: fixed
diff --git a/changelogs/unreleased/allow_repo_storage_moves_without_repo.yml b/changelogs/unreleased/allow_repo_storage_moves_without_repo.yml
new file mode 100644
index 00000000000..4975480e349
--- /dev/null
+++ b/changelogs/unreleased/allow_repo_storage_moves_without_repo.yml
@@ -0,0 +1,5 @@
+---
+title: Allow project storage to be updated when no repositories exist
+merge_request: 46385
+author:
+type: fixed
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 258a75f47fb..ded8b769ff1 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -86,6 +86,8 @@
- 1
- - design_management_new_version
- 1
+- - destroy_pages_deployments
+ - 1
- - detect_repository_languages
- 1
- - disallow_two_factor_for_group
diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql
index cd134233f77..3999f982a36 100644
--- a/doc/api/graphql/reference/gitlab_schema.graphql
+++ b/doc/api/graphql/reference/gitlab_schema.graphql
@@ -2683,6 +2683,66 @@ Identifier of Clusters::Cluster
scalar ClustersClusterID
"""
+Represents the code coverage activity for a group
+"""
+type CodeCoverageActivity {
+ """
+ Average percentage of the different code coverage results available for the group.
+ """
+ averageCoverage: Float
+
+ """
+ Number of different code coverage results available for the group.
+ """
+ coverageCount: Int
+
+ """
+ Date when the code coverage was created.
+ """
+ date: Date!
+
+ """
+ Number of projects with code coverage results for the group.
+ """
+ projectCount: Int
+}
+
+"""
+The connection type for CodeCoverageActivity.
+"""
+type CodeCoverageActivityConnection {
+ """
+ A list of edges.
+ """
+ edges: [CodeCoverageActivityEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [CodeCoverageActivity]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type CodeCoverageActivityEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: CodeCoverageActivity
+}
+
+"""
Represents the code coverage summary for a project
"""
type CodeCoverageSummary {
@@ -7966,6 +8026,37 @@ type Group {
): BoardConnection
"""
+ Represents the code coverage activity for this group. Available only when
+ feature flag `group_coverage_data_report` is enabled
+ """
+ codeCoverageActivities(
+ """
+ Returns the elements in the list that come after the specified cursor.
+ """
+ after: String
+
+ """
+ Returns the elements in the list that come before the specified cursor.
+ """
+ before: String
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+
+ """
+ First day for which to fetch code coverage activity (maximum time window is set to 90 days)
+ """
+ startDate: Date!
+ ): CodeCoverageActivityConnection
+
+ """
Container repositories of the project
"""
containerRepositories(
diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json
index cfca138011a..0b4f3652cc8 100644
--- a/doc/api/graphql/reference/gitlab_schema.json
+++ b/doc/api/graphql/reference/gitlab_schema.json
@@ -7330,6 +7330,191 @@
},
{
"kind": "OBJECT",
+ "name": "CodeCoverageActivity",
+ "description": "Represents the code coverage activity for a group",
+ "fields": [
+ {
+ "name": "averageCoverage",
+ "description": "Average percentage of the different code coverage results available for the group.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Float",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "coverageCount",
+ "description": "Number of different code coverage results available for the group.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "date",
+ "description": "Date when the code coverage was created.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Date",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "projectCount",
+ "description": "Number of projects with code coverage results for the group.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "CodeCoverageActivityConnection",
+ "description": "The connection type for CodeCoverageActivity.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "CodeCoverageActivityEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "CodeCoverageActivity",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "pageInfo",
+ "description": "Information to aid in pagination.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "PageInfo",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "CodeCoverageActivityEdge",
+ "description": "An edge in a connection.",
+ "fields": [
+ {
+ "name": "cursor",
+ "description": "A cursor for use in pagination.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "node",
+ "description": "The item at the end of the edge.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "CodeCoverageActivity",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
"name": "CodeCoverageSummary",
"description": "Represents the code coverage summary for a project",
"fields": [
@@ -22009,6 +22194,73 @@
"deprecationReason": null
},
{
+ "name": "codeCoverageActivities",
+ "description": "Represents the code coverage activity for this group. Available only when feature flag `group_coverage_data_report` is enabled",
+ "args": [
+ {
+ "name": "startDate",
+ "description": "First day for which to fetch code coverage activity (maximum time window is set to 90 days)",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Date",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "after",
+ "description": "Returns the elements in the list that come after the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "before",
+ "description": "Returns the elements in the list that come before the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "first",
+ "description": "Returns the first _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "last",
+ "description": "Returns the last _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "CodeCoverageActivityConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "containerRepositories",
"description": "Container repositories of the project",
"args": [
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index fb3086975b2..5e960f293bd 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -418,6 +418,17 @@ Autogenerated return type of ClusterAgentTokenDelete.
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+### CodeCoverageActivity
+
+Represents the code coverage activity for a group.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `averageCoverage` | Float | Average percentage of the different code coverage results available for the group. |
+| `coverageCount` | Int | Number of different code coverage results available for the group. |
+| `date` | Date! | Date when the code coverage was created. |
+| `projectCount` | Int | Number of projects with code coverage results for the group. |
+
### CodeCoverageSummary
Represents the code coverage summary for a project.
diff --git a/doc/architecture/blueprints/cloud_native_build_logs/index.md b/doc/architecture/blueprints/cloud_native_build_logs/index.md
index 25abfe36e88..f901a724653 100644
--- a/doc/architecture/blueprints/cloud_native_build_logs/index.md
+++ b/doc/architecture/blueprints/cloud_native_build_logs/index.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
description: 'Next iteration of build logs architecture at GitLab'
---
diff --git a/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md b/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md
index 37e69d46ae1..27d2f1362e5 100644
--- a/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md
+++ b/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
description: 'Making GitLab Pages a Cloud Native application - architecture blueprint.'
---
diff --git a/doc/architecture/blueprints/feature_flags_development/index.md b/doc/architecture/blueprints/feature_flags_development/index.md
index 0aeb2b51b39..76fb5f5c7db 100644
--- a/doc/architecture/blueprints/feature_flags_development/index.md
+++ b/doc/architecture/blueprints/feature_flags_development/index.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
description: 'Internal usage of Feature Flags for GitLab development'
---
diff --git a/doc/architecture/blueprints/image_resizing/index.md b/doc/architecture/blueprints/image_resizing/index.md
index 964e935cbb1..ed2dc01b7ed 100644
--- a/doc/architecture/blueprints/image_resizing/index.md
+++ b/doc/architecture/blueprints/image_resizing/index.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
description: 'Image Resizing'
---
diff --git a/doc/architecture/index.md b/doc/architecture/index.md
index 0a2ade6b7b0..0cac646ea83 100644
--- a/doc/architecture/index.md
+++ b/doc/architecture/index.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
description: 'Architecture Practice at GitLab'
---
diff --git a/doc/ci/lint.md b/doc/ci/lint.md
index 716a4218d97..f6e0370b32b 100644
--- a/doc/ci/lint.md
+++ b/doc/ci/lint.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# CI Lint
If you want to test the validity of your GitLab CI/CD configuration before committing
diff --git a/doc/downgrade_ee_to_ce/README.md b/doc/downgrade_ee_to_ce/README.md
index cba21668816..2561ee875d2 100644
--- a/doc/downgrade_ee_to_ce/README.md
+++ b/doc/downgrade_ee_to_ce/README.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Downgrading from EE to CE
If you ever decide to downgrade your Enterprise Edition back to the Community
diff --git a/doc/install/digitaloceandocker.md b/doc/install/digitaloceandocker.md
index fe32b37a9ed..deb8a8cc6ca 100644
--- a/doc/install/digitaloceandocker.md
+++ b/doc/install/digitaloceandocker.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: howto
---
diff --git a/doc/install/pivotal/index.md b/doc/install/pivotal/index.md
index 6a4b361c842..41a5ea82ea2 100644
--- a/doc/install/pivotal/index.md
+++ b/doc/install/pivotal/index.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# GitLab Pivotal Tile **(PREMIUM ONLY)**
CAUTION: **Discontinued:**
diff --git a/doc/install/postgresql_extensions.md b/doc/install/postgresql_extensions.md
index 9e5a1e3d627..6355806f067 100644
--- a/doc/install/postgresql_extensions.md
+++ b/doc/install/postgresql_extensions.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Managing PostgreSQL extensions
This guide documents how to manage PostgreSQL extensions for installations with an external
diff --git a/doc/integration/README.md b/doc/integration/README.md
index c8ce367e99f..25e8c1a51c1 100644
--- a/doc/integration/README.md
+++ b/doc/integration/README.md
@@ -1,4 +1,7 @@
---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
comments: false
---
diff --git a/doc/integration/akismet.md b/doc/integration/akismet.md
index 7cb8f8b70ce..8be410e97b9 100644
--- a/doc/integration/akismet.md
+++ b/doc/integration/akismet.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Akismet
GitLab leverages [Akismet](https://akismet.com/) to protect against spam. Currently
diff --git a/doc/integration/auth0.md b/doc/integration/auth0.md
index d851b9f5dc7..d53fa6efc29 100644
--- a/doc/integration/auth0.md
+++ b/doc/integration/auth0.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Auth0 OmniAuth Provider
To enable the Auth0 OmniAuth provider, you must create an Auth0 account, and an
diff --git a/doc/integration/azure.md b/doc/integration/azure.md
index 2059707e38c..2964b93055a 100644
--- a/doc/integration/azure.md
+++ b/doc/integration/azure.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Microsoft Azure OAuth2 OmniAuth Provider
To enable the Microsoft Azure OAuth2 OmniAuth provider you must register your application with Azure. Azure will generate a client ID and secret key for you to use.
diff --git a/doc/integration/bitbucket.md b/doc/integration/bitbucket.md
index a151fbf50e7..52bd7aaecc5 100644
--- a/doc/integration/bitbucket.md
+++ b/doc/integration/bitbucket.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Integrate your GitLab server with Bitbucket Cloud
NOTE: **Note:**
diff --git a/doc/integration/cas.md b/doc/integration/cas.md
index eee801350eb..e61988c3301 100644
--- a/doc/integration/cas.md
+++ b/doc/integration/cas.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# CAS OmniAuth Provider
To enable the CAS OmniAuth provider you must register your application with your CAS instance. This requires the service URL GitLab will supply to CAS. It should be something like: `https://gitlab.example.com:443/users/auth/cas3/callback?url`. By default handling for SLO is enabled, you only need to configure CAS for backchannel logout.
diff --git a/doc/integration/external-issue-tracker.md b/doc/integration/external-issue-tracker.md
index 96c9b9d7f62..a4fca36b154 100644
--- a/doc/integration/external-issue-tracker.md
+++ b/doc/integration/external-issue-tracker.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# External issue tracker
GitLab has a great [issue tracker](../user/project/issues/index.md) but you can also use an external
diff --git a/doc/integration/facebook.md b/doc/integration/facebook.md
index dbefb560fe7..bb699fa90b7 100644
--- a/doc/integration/facebook.md
+++ b/doc/integration/facebook.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Facebook OAuth2 OmniAuth Provider
To enable the Facebook OmniAuth provider you must register your application with Facebook. Facebook will generate an app ID and secret key for you to use.
diff --git a/doc/integration/github.md b/doc/integration/github.md
index ce2b50acc54..cff919c902a 100644
--- a/doc/integration/github.md
+++ b/doc/integration/github.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Integrate your GitLab instance with GitHub
You can integrate your GitLab instance with GitHub.com as well as GitHub Enterprise to enable users to import projects from GitHub and/or to login to your GitLab instance with your GitHub account.
diff --git a/doc/integration/gitlab.md b/doc/integration/gitlab.md
index a200f6b6470..c618d226290 100644
--- a/doc/integration/gitlab.md
+++ b/doc/integration/gitlab.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Integrate your server with GitLab.com
Import projects from GitLab.com and login to your GitLab instance with your GitLab.com account.
diff --git a/doc/integration/gmail_action_buttons_for_gitlab.md b/doc/integration/gmail_action_buttons_for_gitlab.md
index 526db8a7338..72196fd0f52 100644
--- a/doc/integration/gmail_action_buttons_for_gitlab.md
+++ b/doc/integration/gmail_action_buttons_for_gitlab.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Gmail actions buttons for GitLab
GitLab supports [Google actions in email](https://developers.google.com/gmail/markup/actions/actions-overview).
diff --git a/doc/integration/google.md b/doc/integration/google.md
index 4cf589c1da8..cd40aaff30a 100644
--- a/doc/integration/google.md
+++ b/doc/integration/google.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Google OAuth2 OmniAuth Provider
To enable the Google OAuth2 OmniAuth provider you must register your application
diff --git a/doc/integration/jenkins.md b/doc/integration/jenkins.md
index 8fc638db95a..7eb147c1fe6 100644
--- a/doc/integration/jenkins.md
+++ b/doc/integration/jenkins.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Jenkins CI service **(STARTER)**
NOTE: **Note:**
diff --git a/doc/integration/jenkins_deprecated.md b/doc/integration/jenkins_deprecated.md
index 5fc30bf3305..63d5ac48765 100644
--- a/doc/integration/jenkins_deprecated.md
+++ b/doc/integration/jenkins_deprecated.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Jenkins CI (deprecated) service
NOTE: **Note:**
diff --git a/doc/integration/oauth2_generic.md b/doc/integration/oauth2_generic.md
index 8566134815a..5957af292ab 100644
--- a/doc/integration/oauth2_generic.md
+++ b/doc/integration/oauth2_generic.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Sign into GitLab with (almost) any OAuth2 provider
The `omniauth-oauth2-generic` gem allows Single Sign On between GitLab and your own OAuth2 provider
diff --git a/doc/integration/oauth_provider.md b/doc/integration/oauth_provider.md
index fd1c21d725d..68d10a3135e 100644
--- a/doc/integration/oauth_provider.md
+++ b/doc/integration/oauth_provider.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# GitLab as OAuth2 authentication service provider
This document is about using GitLab as an OAuth authentication service provider
diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md
index cf09c2f2803..535f97e9a4d 100644
--- a/doc/integration/omniauth.md
+++ b/doc/integration/omniauth.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# OmniAuth
GitLab leverages OmniAuth to allow users to sign in using Twitter, GitHub, and
diff --git a/doc/integration/openid_connect_provider.md b/doc/integration/openid_connect_provider.md
index b66262772da..bf33483f949 100644
--- a/doc/integration/openid_connect_provider.md
+++ b/doc/integration/openid_connect_provider.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# GitLab as OpenID Connect identity provider
This document is about using GitLab as an OpenID Connect identity provider
diff --git a/doc/integration/recaptcha.md b/doc/integration/recaptcha.md
index 1868711ca9c..545f60cddbf 100644
--- a/doc/integration/recaptcha.md
+++ b/doc/integration/recaptcha.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# reCAPTCHA
GitLab leverages [Google's reCAPTCHA](https://www.google.com/recaptcha/about/)
diff --git a/doc/integration/salesforce.md b/doc/integration/salesforce.md
index dbd0a03e3cf..3290f18e2cb 100644
--- a/doc/integration/salesforce.md
+++ b/doc/integration/salesforce.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Salesforce OmniAuth Provider
You can integrate your GitLab instance with [Salesforce](https://www.salesforce.com/) to enable users to log in to your GitLab instance with their Salesforce account.
diff --git a/doc/integration/shibboleth.md b/doc/integration/shibboleth.md
index 1b645541cec..59374d8ad6f 100644
--- a/doc/integration/shibboleth.md
+++ b/doc/integration/shibboleth.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Shibboleth OmniAuth Provider
NOTE: **Note:**
diff --git a/doc/integration/slash_commands.md b/doc/integration/slash_commands.md
index c73db32a42a..ea2c4b3e93f 100644
--- a/doc/integration/slash_commands.md
+++ b/doc/integration/slash_commands.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Slash Commands
> The `run` command was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4466) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.6. [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24780) to [GitLab Core](https://about.gitlab.com/pricing/) in 11.9.
diff --git a/doc/integration/trello_power_up.md b/doc/integration/trello_power_up.md
index fc55dbb9654..22481e14236 100644
--- a/doc/integration/trello_power_up.md
+++ b/doc/integration/trello_power_up.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Trello Power-Up
GitLab's Trello Power-Up enables you to seamlessly attach
diff --git a/doc/integration/twitter.md b/doc/integration/twitter.md
index e501eac0c5f..bfe18c43e9d 100644
--- a/doc/integration/twitter.md
+++ b/doc/integration/twitter.md
@@ -1,3 +1,9 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Twitter OAuth2 OmniAuth Provider
To enable the Twitter OmniAuth provider you must register your application with Twitter. Twitter will generate a client ID and secret key for you to use.
diff --git a/doc/user/analytics/merge_request_analytics.md b/doc/user/analytics/merge_request_analytics.md
index 04a5fa71e19..996e53328aa 100644
--- a/doc/user/analytics/merge_request_analytics.md
+++ b/doc/user/analytics/merge_request_analytics.md
@@ -57,9 +57,11 @@ Data table displaying a maximum of the 100 most recent merge requests merged for
You can filter the data that is presented on the page based on the following parameters:
- Author
-- Assignees
-- Labels
-- Milestones
+- Assignee
+- Label
+- Milestone
+- Source branch
+- Target branch
To filter results:
diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md
index 3cb566c7f77..deb197952ab 100644
--- a/doc/user/group/saml_sso/index.md
+++ b/doc/user/group/saml_sso/index.md
@@ -88,8 +88,6 @@ We intend to add a similar SSO requirement for [Git and API activity](https://gi
When SSO enforcement is enabled for a group, users cannot share a project in the group outside the top-level group, even if the project is forked.
-To disallow users to contribute outside of the top-level group, please see [Group Managed Accounts](group_managed_accounts.md).
-
## Providers
NOTE: **Note:**
diff --git a/lib/api/ci/runner.rb b/lib/api/ci/runner.rb
index c2e2b59d39f..85232b4ae1b 100644
--- a/lib/api/ci/runner.rb
+++ b/lib/api/ci/runner.rb
@@ -207,27 +207,18 @@ module API
error!('400 Missing header Content-Range', 400) unless request.headers.key?('Content-Range')
content_range = request.headers['Content-Range']
- content_range = content_range.split('-')
-
- # TODO:
- # it seems that `Content-Range` as formatted by runner is wrong,
- # the `byte_end` should point to final byte, but it points byte+1
- # that means that we have to calculate end of body,
- # as we cannot use `content_length[1]`
- # Issue: https://gitlab.com/gitlab-org/gitlab-runner/issues/3275
-
- body_data = request.body.read
- body_start = content_range[0].to_i
- body_end = body_start + body_data.bytesize
-
- stream_size = job.trace.append(body_data, body_start)
- unless stream_size == body_end
- break error!('416 Range Not Satisfiable', 416, { 'Range' => "0-#{stream_size}" })
+
+ result = ::Ci::AppendBuildTraceService
+ .new(job, content_range: content_range)
+ .execute(request.body.read)
+
+ if result.status == 416
+ break error!('416 Range Not Satisfiable', 416, { 'Range' => "0-#{result.stream_size}" })
end
- status 202
+ status result.status
header 'Job-Status', job.status
- header 'Range', "0-#{stream_size}"
+ header 'Range', "0-#{result.stream_size}"
header 'X-GitLab-Trace-Update-Interval', job.trace.update_interval.to_s
end
diff --git a/lib/gitlab/badge/coverage/report.rb b/lib/gitlab/badge/coverage/report.rb
index 0df6e858bf4..40fcd2f89f2 100644
--- a/lib/gitlab/badge/coverage/report.rb
+++ b/lib/gitlab/badge/coverage/report.rb
@@ -17,8 +17,6 @@ module Gitlab
key_width: opts[:key_width].to_i,
key_text: opts[:key_text]
}
-
- @pipeline = @project.ci_pipelines.latest_successful_for_ref(@ref)
end
def entity
@@ -42,14 +40,18 @@ module Gitlab
private
+ def pipeline
+ @pipeline ||= @project.ci_pipelines.latest_successful_for_ref(@ref)
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def raw_coverage
- return unless @pipeline
+ return unless pipeline
if @job.blank?
- @pipeline.coverage
+ pipeline.coverage
else
- @pipeline.builds
+ pipeline.builds
.find_by(name: @job)
.try(:coverage)
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 1f4a12b8b8c..5c31006122e 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -25420,6 +25420,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Status was retried."
+msgstr ""
+
msgid "Status:"
msgstr ""
diff --git a/spec/frontend/reports/components/grouped_test_reports_app_spec.js b/spec/frontend/reports/components/grouped_test_reports_app_spec.js
index 556904b7da5..14c984ce32f 100644
--- a/spec/frontend/reports/components/grouped_test_reports_app_spec.js
+++ b/spec/frontend/reports/components/grouped_test_reports_app_spec.js
@@ -1,5 +1,6 @@
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
+import { mockTracking } from 'helpers/tracking_helper';
import GroupedTestReportsApp from '~/reports/components/grouped_test_reports_app.vue';
import { getStoreConfig } from '~/reports/store';
@@ -39,6 +40,7 @@ describe('Grouped test reports app', () => {
};
const findHeader = () => wrapper.find('[data-testid="report-section-code-text"]');
+ const findExpandButton = () => wrapper.find('[data-testid="report-section-expand-button"]');
const findFullTestReportLink = () => wrapper.find('[data-testid="group-test-reports-full-link"]');
const findSummaryDescription = () => wrapper.find('[data-testid="test-summary-row-description"]');
const findIssueDescription = () => wrapper.find('[data-testid="test-issue-body-description"]');
@@ -96,6 +98,35 @@ describe('Grouped test reports app', () => {
});
});
+ describe('`Expand` button', () => {
+ let trackingSpy;
+
+ beforeEach(() => {
+ setReports(newFailedTestReports);
+ mountComponent();
+ document.body.dataset.page = 'projects:merge_requests:show';
+ trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn);
+ });
+
+ it('tracks an event on click', () => {
+ findExpandButton().trigger('click');
+
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, 'expand_test_report_widget', {});
+ });
+
+ it('only tracks the first expansion', () => {
+ expect(trackingSpy).not.toHaveBeenCalled();
+
+ const button = findExpandButton();
+
+ button.trigger('click');
+ button.trigger('click');
+ button.trigger('click');
+
+ expect(trackingSpy).toHaveBeenCalledTimes(1);
+ });
+ });
+
describe('with new failed result', () => {
beforeEach(() => {
setReports(newFailedTestReports);
diff --git a/spec/models/ci/daily_build_group_report_result_spec.rb b/spec/models/ci/daily_build_group_report_result_spec.rb
index 68c5d58cfd5..f16396d62c9 100644
--- a/spec/models/ci/daily_build_group_report_result_spec.rb
+++ b/spec/models/ci/daily_build_group_report_result_spec.rb
@@ -123,5 +123,39 @@ RSpec.describe Ci::DailyBuildGroupReportResult do
end
end
end
+
+ describe '.by_date' do
+ subject(:coverages) { described_class.by_date(start_date) }
+
+ let!(:coverage_1) { create(:ci_daily_build_group_report_result, date: 1.week.ago) }
+
+ context 'when project has several coverage' do
+ let!(:coverage_2) { create(:ci_daily_build_group_report_result, date: 2.weeks.ago) }
+ let(:start_date) { 1.week.ago.to_date.to_s }
+
+ it 'returns the coverage from the start_date' do
+ expect(coverages).to contain_exactly(coverage_1)
+ end
+ end
+
+ context 'when start_date is over 90 days' do
+ let!(:coverage_2) { create(:ci_daily_build_group_report_result, date: 90.days.ago) }
+ let!(:coverage_3) { create(:ci_daily_build_group_report_result, date: 91.days.ago) }
+ let(:start_date) { 1.year.ago.to_date.to_s }
+
+ it 'returns the coverage in the last 90 days' do
+ expect(coverages).to contain_exactly(coverage_1, coverage_2)
+ end
+ end
+
+ context 'when start_date is not a string' do
+ let!(:coverage_2) { create(:ci_daily_build_group_report_result, date: 90.days.ago) }
+ let(:start_date) { 1.week.ago }
+
+ it 'returns the coverage in the last 90 days' do
+ expect(coverages).to contain_exactly(coverage_1, coverage_2)
+ end
+ end
+ end
end
end
diff --git a/spec/models/pages_deployment_spec.rb b/spec/models/pages_deployment_spec.rb
index 057c01d26cf..e059b477e0e 100644
--- a/spec/models/pages_deployment_spec.rb
+++ b/spec/models/pages_deployment_spec.rb
@@ -42,4 +42,17 @@ RSpec.describe PagesDeployment do
deployment = create(:pages_deployment)
expect(deployment.size).to eq(deployment.file.size)
end
+
+ describe '.older_than' do
+ it 'returns deployments with lower id' do
+ old_deployments = create_list(:pages_deployment, 2)
+
+ deployment = create(:pages_deployment)
+
+ # new deployment
+ create(:pages_deployment)
+
+ expect(PagesDeployment.older_than(deployment.id)).to eq(old_deployments)
+ end
+ end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 5f643fb03df..5e2711c791e 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -3668,7 +3668,7 @@ RSpec.describe Project, factory_default: :keep do
let(:project) { create(:project) }
before do
- project.namespace_id = 7
+ project.namespace_id = project.namespace_id + 1
end
it { expect(project.parent_changed?).to be_truthy }
@@ -4219,6 +4219,27 @@ RSpec.describe Project, factory_default: :keep do
expect { project.destroy }.not_to raise_error
end
+
+ context 'when there is an old pages deployment' do
+ let!(:old_deployment_from_another_project) { create(:pages_deployment) }
+ let!(:old_deployment) { create(:pages_deployment, project: project) }
+
+ it 'schedules a destruction of pages deployments' do
+ expect(DestroyPagesDeploymentsWorker).to(
+ receive(:perform_async).with(project.id)
+ )
+
+ project.remove_pages
+ end
+
+ it 'removes pages deployments', :sidekiq_inline do
+ expect do
+ project.remove_pages
+ end.to change { PagesDeployment.count }.by(-1)
+
+ expect(PagesDeployment.find_by_id(old_deployment.id)).to be_nil
+ end
+ end
end
describe '#remove_export' do
diff --git a/spec/services/ci/append_build_trace_service_spec.rb b/spec/services/ci/append_build_trace_service_spec.rb
new file mode 100644
index 00000000000..aa1dd2bbc10
--- /dev/null
+++ b/spec/services/ci/append_build_trace_service_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::AppendBuildTraceService do
+ let(:project) { create(:project) }
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:build) { create(:ci_build, :running, pipeline: pipeline) }
+
+ before do
+ stub_feature_flags(ci_enable_live_trace: true)
+ end
+
+ context 'build trace append is successful' do
+ it 'returns a correct stream size and status code' do
+ stream_size = 192.kilobytes
+ body_data = 'x' * stream_size
+ content_range = "0-#{stream_size}"
+
+ result = described_class
+ .new(build, content_range: content_range)
+ .execute(body_data)
+
+ expect(result.status).to eq 202
+ expect(result.stream_size).to eq stream_size
+ expect(build.trace_chunks.count).to eq 2
+ end
+ end
+
+ context 'when could not correctly append to a trace' do
+ it 'responds with content range violation and data stored' do
+ allow(build).to receive_message_chain(:trace, :append) { 16 }
+
+ result = described_class
+ .new(build, content_range: '0-128')
+ .execute('x' * 128)
+
+ expect(result.status).to eq 416
+ expect(result.stream_size).to eq 16
+ end
+
+ it 'logs exception if build has live trace' do
+ build.trace.append('abcd', 0)
+
+ expect(::Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(anything, hash_including(chunk_index: 0, chunk_store: 'redis'))
+
+ result = described_class
+ .new(build, content_range: '0-128')
+ .execute('x' * 128)
+
+ expect(result.status).to eq 416
+ expect(result.stream_size).to eq 4
+ end
+ end
+end
diff --git a/spec/services/pages/destroy_deployments_service_spec.rb b/spec/services/pages/destroy_deployments_service_spec.rb
new file mode 100644
index 00000000000..0f8e8b6573e
--- /dev/null
+++ b/spec/services/pages/destroy_deployments_service_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Pages::DestroyDeploymentsService do
+ let(:project) { create(:project) }
+ let!(:old_deployments) { create_list(:pages_deployment, 2, project: project) }
+ let!(:last_deployment) { create(:pages_deployment, project: project) }
+ let!(:newer_deployment) { create(:pages_deployment, project: project) }
+ let!(:deployment_from_another_project) { create(:pages_deployment) }
+
+ it 'destroys all deployments of the project' do
+ expect do
+ described_class.new(project).execute
+ end.to change { PagesDeployment.count }.by(-4)
+
+ expect(deployment_from_another_project.reload).to be
+ end
+
+ it 'destroy only deployments older than last deployment if it is provided' do
+ expect do
+ described_class.new(project, last_deployment.id).execute
+ end.to change { PagesDeployment.count }.by(-2)
+
+ expect(last_deployment.reload).to be
+ expect(newer_deployment.reload).to be
+ expect(deployment_from_another_project.reload).to be
+ end
+end
diff --git a/spec/services/projects/update_pages_service_spec.rb b/spec/services/projects/update_pages_service_spec.rb
index d8be4d47437..92772136d69 100644
--- a/spec/services/projects/update_pages_service_spec.rb
+++ b/spec/services/projects/update_pages_service_spec.rb
@@ -71,6 +71,29 @@ RSpec.describe Projects::UpdatePagesService do
expect(project.pages_metadatum.reload.pages_deployment_id).to eq(deployment.id)
end
+ context 'when there is an old pages deployment' do
+ let!(:old_deployment_from_another_project) { create(:pages_deployment) }
+ let!(:old_deployment) { create(:pages_deployment, project: project) }
+
+ it 'schedules a destruction of older deployments' do
+ expect(DestroyPagesDeploymentsWorker).to(
+ receive(:perform_in).with(described_class::OLD_DEPLOYMENTS_DESTRUCTION_DELAY,
+ project.id,
+ instance_of(Integer))
+ )
+
+ execute
+ end
+
+ it 'removes older deployments', :sidekiq_inline do
+ expect do
+ execute
+ end.not_to change { PagesDeployment.count } # it creates one and deletes one
+
+ expect(PagesDeployment.find_by_id(old_deployment.id)).to be_nil
+ end
+ end
+
it 'does not create deployment when zip_pages_deployments feature flag is disabled' do
stub_feature_flags(zip_pages_deployments: false)
diff --git a/spec/services/projects/update_repository_storage_service_spec.rb b/spec/services/projects/update_repository_storage_service_spec.rb
index 0fcd14f3bc9..123f604e7a4 100644
--- a/spec/services/projects/update_repository_storage_service_spec.rb
+++ b/spec/services/projects/update_repository_storage_service_spec.rb
@@ -168,6 +168,24 @@ RSpec.describe Projects::UpdateRepositoryStorageService do
end
end
+ context 'project with no repositories' do
+ let(:project) { create(:project) }
+ let(:repository_storage_move) { create(:project_repository_storage_move, :scheduled, project: project, destination_storage_name: 'test_second_storage') }
+
+ it 'updates the database' do
+ allow(Gitlab::GitalyClient).to receive(:filesystem_id).with('default').and_call_original
+ allow(Gitlab::GitalyClient).to receive(:filesystem_id).with('test_second_storage').and_return(SecureRandom.uuid)
+
+ result = subject.execute
+ project.reload
+
+ expect(result).to be_success
+ expect(project).not_to be_repository_read_only
+ expect(project.repository_storage).to eq('test_second_storage')
+ expect(project.project_repository.shard_name).to eq('test_second_storage')
+ end
+ end
+
context 'with wiki repository' do
include_examples 'moves repository to another storage', 'wiki' do
let(:project) { create(:project, :repository, wiki_enabled: true) }
diff --git a/spec/workers/destroy_pages_deployments_worker_spec.rb b/spec/workers/destroy_pages_deployments_worker_spec.rb
new file mode 100644
index 00000000000..2c20c9004ef
--- /dev/null
+++ b/spec/workers/destroy_pages_deployments_worker_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe DestroyPagesDeploymentsWorker do
+ subject(:worker) { described_class.new }
+
+ let(:project) { create(:project) }
+ let!(:old_deployment) { create(:pages_deployment, project: project) }
+ let!(:last_deployment) { create(:pages_deployment, project: project) }
+ let!(:another_deployment) { create(:pages_deployment) }
+
+ it "doesn't fail if project is already removed" do
+ expect do
+ worker.perform(-1)
+ end.not_to raise_error
+ end
+
+ it 'can be called without last_deployment_id' do
+ expect_next_instance_of(::Pages::DestroyDeploymentsService, project, nil) do |service|
+ expect(service).to receive(:execute).and_call_original
+ end
+
+ expect do
+ worker.perform(project.id)
+ end.to change { PagesDeployment.count }.by(-2)
+ end
+
+ it 'calls destroy service' do
+ expect_next_instance_of(::Pages::DestroyDeploymentsService, project, last_deployment.id) do |service|
+ expect(service).to receive(:execute).and_call_original
+ end
+
+ expect do
+ worker.perform(project.id, last_deployment.id)
+ end.to change { PagesDeployment.count }.by(-1)
+ end
+end