Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-07-27 09:10:42 +00:00
parent 1d9c7ebdad
commit 5add825158
31 changed files with 158 additions and 46 deletions

View File

@ -52,6 +52,8 @@ export default {
return tabName === this.activeTab;
},
navigateTo(tabName) {
if (this.isActive(tabName)) return;
this.$router.push({ name: tabName });
},
},

View File

@ -1,7 +1,12 @@
import * as Sentry from '@sentry/browser';
import { pickBy } from 'lodash';
import { parseUrlPathname } from '~/lib/utils/url_utility';
import { NEEDS_PROPERTY, SUPPORTED_FILTER_PARAMETERS, validPipelineTabNames } from './constants';
import {
NEEDS_PROPERTY,
SUPPORTED_FILTER_PARAMETERS,
validPipelineTabNames,
pipelineTabName,
} from './constants';
/*
The following functions are the main engine in transforming the data as
received from the endpoint into the format the d3 graph expects.
@ -144,9 +149,8 @@ export const getPipelineDefaultTab = (url) => {
const regexp = /\w*$/;
const [tabName] = strippedUrl.match(regexp);
if (tabName && validPipelineTabNames.includes(tabName)) {
return tabName;
}
if (tabName && validPipelineTabNames.includes(tabName)) return tabName;
if (tabName === '') return pipelineTabName;
return null;
};

View File

@ -17,8 +17,8 @@ module TimeTrackable
attribute :time_estimate, default: 0
validates :time_estimate, numericality: { message: 'has an invalid format' }, allow_nil: false
validate :check_negative_time_spent
validate :check_time_estimate
validate :check_negative_time_spent
has_many :timelogs, dependent: :destroy, autosave: true # rubocop:disable Cop/ActiveRecordDependent
after_initialize :set_time_estimate_default_value
@ -106,4 +106,11 @@ module TimeTrackable
def original_total_time_spent
@original_total_time_spent ||= total_time_spent
end
def check_time_estimate
return unless new_record? || time_estimate_changed?
return if time_estimate.is_a?(Numeric) && time_estimate >= 0
errors.add(:time_estimate, _('must have a valid format and be greater than or equal to zero.'))
end
end

View File

@ -397,7 +397,7 @@ class Group < Namespace
end
def visibility_level_allowed_by_projects?(level = self.visibility_level)
!projects.where('visibility_level > ?', level).exists?
!projects.without_deleted.where('visibility_level > ?', level).exists?
end
def visibility_level_allowed_by_sub_groups?(level = self.visibility_level)

View File

@ -1,10 +1,6 @@
# frozen_string_literal: true
class SentNotification < ApplicationRecord
include IgnorableColumns
ignore_column %i[line_code note_type position], remove_with: '16.3', remove_after: '2023-07-22'
belongs_to :project
belongs_to :noteable, polymorphic: true # rubocop:disable Cop/PolymorphicAssociations
belongs_to :recipient, class_name: "User"

View File

@ -114,7 +114,11 @@ module Projects
# It's possible that the project was destroyed, but some after_commit
# hook failed and caused us to end up here. A destroyed model will be a frozen hash,
# which cannot be altered.
project.update(delete_error: message, pending_delete: false) unless project.destroyed?
unless project.destroyed?
# Restrict project visibility if the parent group visibility was made more restrictive while the project was scheduled for deletion.
visibility_level = project.visibility_level_allowed_by_group? ? project.visibility_level : project.group.visibility_level
project.update(delete_error: message, pending_delete: false, visibility_level: visibility_level)
end
log_error("Deletion failed on #{project.full_path} with the following message: #{message}")
end

View File

@ -5,5 +5,7 @@
dismissible: false,
alert_options: { class: 'project-deletion-failed-message' }) do |c|
- c.with_body do
This project was scheduled for deletion, but failed with the following message:
= _('This project was scheduled for deletion, but failed with the following message:')
= project.delete_error
%br
= _('The project visibility may have been made more restrictive if the parent group\'s visibility changed while the deletion was scheduled.')

View File

@ -8,6 +8,7 @@
#
---
- advisory_database
- ai_abstraction_layer
- api
- api_security
- application_instrumentation
@ -67,6 +68,7 @@
- gitaly
- gitlab_cli
- gitlab_docs
- gitlab_duo_chat
- global_search
- groups_and_projects
- helm_chart_registry
@ -96,7 +98,8 @@
- pages
- pipeline_composition
- portfolio_management
- product_analytics
- product_analytics_data_management
- product_analytics_visualization
- pubsec_services
- purchase
- quality_management

View File

@ -3,7 +3,7 @@ table_name: product_analytics_events_experimental
classes:
- ProductAnalyticsEvent
feature_categories:
- product_analytics
- product_analytics_data_management
description: Product analytic events, experimental feature.
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/fc6c53e6f7b47dc22c8619a5a6fe491d29778d3f
milestone: '13.2'

View File

@ -12,10 +12,11 @@ General development guidelines and tips for the [Import/Export feature](../user/
## Security
The Import/Export feature is constantly updated (adding new things to export), however
the code hasn't been refactored in a long time. We should perform a code audit (see
[confidential issue](../user/project/issues/confidential_issues.md) `https://gitlab.com/gitlab-org/gitlab/-/issues/20720`).
The Import/Export feature is constantly updated (adding new things to export). However,
the code hasn't been refactored in a long time. We should perform a code audit
to make sure its dynamic nature does not increase the number of security concerns.
GitLab team members can view more information in this confidential issue:
`https://gitlab.com/gitlab-org/gitlab/-/issues/20720`.
### Security in the code

View File

@ -32,7 +32,7 @@ To install the GitLab for Jira Cloud app:
1. In Jira, on the top bar, select **Apps > Explore more apps** and search for `GitLab for Jira Cloud`.
1. Select **GitLab for Jira Cloud**, then select **Get it now**.
Alternatively, [get the app directly from the Atlassian Marketplace](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?tab=overview&hosting=cloud).
Alternatively, [get the app directly from the Atlassian Marketplace](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?tab=overview&hosting=cloud).
You can now [configure the GitLab for Jira Cloud app](#configure-the-gitlab-for-jira-cloud-app).
@ -75,6 +75,7 @@ The following data is synced:
Most updates to the app are automatic. For more information, see the
[Atlassian documentation](https://developer.atlassian.com/platform/marketplace/upgrading-and-versioning-cloud-apps/).
If the app requires additional permissions, [you must manually approve the update in Jira](https://developer.atlassian.com/platform/marketplace/upgrading-and-versioning-cloud-apps/#changes-that-require-manual-customer-approval).
## Set up OAuth authentication for self-managed instances **(FREE SELF)**
@ -382,6 +383,6 @@ Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remot
A `403` status code is returned if:
- The user information cannot be fetched from Jira.
- The authenticated Jira user does not have administrator access.
- The authenticated Jira user does not have [site administrator](https://support.atlassian.com/user-management/docs/give-users-admin-permissions/#Make-someone-a-site-admin) access.
To resolve this issue, ensure the authenticated user is a Jira site administrator and try again.

View File

@ -17,7 +17,7 @@ To create Jira credentials, here's what we're going to do:
Prerequisite:
- You must have administrator access to the Jira instance.
- You must have [site administrator](https://support.atlassian.com/user-management/docs/give-users-admin-permissions/#Make-someone-a-site-admin) access to the Jira instance.
## Create a Jira user

View File

@ -161,7 +161,7 @@ example, no additional storage has yet been purchased.
To remove the read-only state from the Red and Green projects, 50 GB additional storage is purchased.
Assuming the Green and Red projects' repositories and LFS grow past the 10 GB quota, the purchased storage
available decreases. All projects remain read-only because 40 GB purchased storage is available:
available decreases. All projects no longer have the read-only status because 40 GB purchased storage is available:
50 GB (purchased storage) - 10 GB (total excess storage used).
| Repository | Storage used | Excess storage | Quota | Status |

View File

@ -46,7 +46,7 @@ module Gitlab
init_commit = objects.last
diff_tree = Gitlab::Git::DiffTree.from_commit(init_commit)
objects.prepend(diff_tree) if diff_tree
return [diff_tree] + objects if diff_tree
objects
end

View File

@ -159,12 +159,10 @@ module Gitlab
current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project)
end
parse_params do |raw_duration|
Gitlab::TimeTrackingFormatter.parse(raw_duration)
Gitlab::TimeTrackingFormatter.parse(raw_duration, keep_zero: true)
end
command :estimate, :estimate_time do |time_estimate|
if time_estimate
@updates[:time_estimate] = time_estimate
end
@updates[:time_estimate] = time_estimate
end
desc { _('Add or subtract spent time') }

View File

@ -13164,6 +13164,9 @@ msgstr ""
msgid "Could not restore the group"
msgstr ""
msgid "Could not retrieve the list of branches. Use the YAML editor mode, or refresh this page later. To view the list of branches, go to %{boldStart}Code - Branches%{boldEnd}"
msgstr ""
msgid "Could not retrieve the list of protected branches. Use the YAML editor mode, or refresh this page later. To view the list of protected branches, go to %{boldStart}Settings - Branches%{boldEnd} and expand %{boldStart}Protected branches%{boldEnd}."
msgstr ""
@ -46720,6 +46723,9 @@ msgstr ""
msgid "The project size exceeds the export limit."
msgstr ""
msgid "The project visibility may have been made more restrictive if the parent group's visibility changed while the deletion was scheduled."
msgstr ""
msgid "The project was successfully forked."
msgstr ""
@ -47815,6 +47821,9 @@ msgstr ""
msgid "This project reached the limit of custom domains. (Max %d)"
msgstr ""
msgid "This project was scheduled for deletion, but failed with the following message:"
msgstr ""
msgid "This project will be deleted on %{date}"
msgstr ""
@ -55681,6 +55690,9 @@ msgstr ""
msgid "must have a repository"
msgstr ""
msgid "must have a valid format and be greater than or equal to zero."
msgstr ""
msgid "must match %{association}.project_id"
msgstr ""

View File

@ -2,7 +2,7 @@
require "spec_helper"
RSpec.describe ProductAnalyticsTracking, :snowplow, feature_category: :product_analytics do
RSpec.describe ProductAnalyticsTracking, :snowplow, feature_category: :product_analytics_data_management do
include TrackingHelpers
include SnowplowHelpers

View File

@ -1,5 +1,5 @@
import { createJobsHash, generateJobNeedsDict, getPipelineDefaultTab } from '~/pipelines/utils';
import { validPipelineTabNames } from '~/pipelines/constants';
import { validPipelineTabNames, pipelineTabName } from '~/pipelines/constants';
describe('utils functions', () => {
const jobName1 = 'build_1';
@ -173,8 +173,8 @@ describe('utils functions', () => {
describe('getPipelineDefaultTab', () => {
const baseUrl = 'http://gitlab.com/user/multi-projects-small/-/pipelines/332/';
it('returns null if there is only the base url', () => {
expect(getPipelineDefaultTab(baseUrl)).toBe(null);
it('returns pipeline tab name if there is only the base url', () => {
expect(getPipelineDefaultTab(baseUrl)).toBe(pipelineTabName);
});
it('returns null if there was no valid last url part', () => {

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::SnowplowEventDefinitionGenerator, :silence_stdout, feature_category: :product_analytics do
RSpec.describe Gitlab::SnowplowEventDefinitionGenerator, :silence_stdout, feature_category: :product_analytics_data_management do
let(:ce_temp_dir) { Dir.mktmpdir }
let(:ee_temp_dir) { Dir.mktmpdir }
let(:timestamp) { Time.now.utc.strftime('%Y%m%d%H%M%S') }

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Analytics::CycleAnalytics::StageEvents::StageEvent, feature_category: :product_analytics do
RSpec.describe Gitlab::Analytics::CycleAnalytics::StageEvents::StageEvent, feature_category: :product_analytics_data_management do
let(:instance) { described_class.new({}) }
it { expect(described_class).to respond_to(:name) }

View File

@ -2,7 +2,7 @@
require "spec_helper"
RSpec.describe Gitlab::InternalEvents::EventDefinitions, feature_category: :product_analytics do
RSpec.describe Gitlab::InternalEvents::EventDefinitions, feature_category: :product_analytics_data_management do
after(:all) do
described_class.instance_variable_set(:@events, nil)
end

View File

@ -2,7 +2,7 @@
require "spec_helper"
RSpec.describe Gitlab::InternalEvents, :snowplow, feature_category: :product_analytics do
RSpec.describe Gitlab::InternalEvents, :snowplow, feature_category: :product_analytics_data_management do
include TrackingHelpers
include SnowplowHelpers

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe ProductAnalytics::Settings, feature_category: :product_analytics do
RSpec.describe ProductAnalytics::Settings, feature_category: :product_analytics_data_management do
let_it_be(:project) { create(:project) }
subject { described_class.for_project(project) }

View File

@ -3,7 +3,7 @@
require 'spec_helper'
require_migration!
RSpec.describe CopyClickhouseConnectionStringToEncryptedVar, feature_category: :product_analytics do
RSpec.describe CopyClickhouseConnectionStringToEncryptedVar, feature_category: :product_analytics_data_management do
let!(:migration) { described_class.new }
let(:setting) { table(:application_settings).create!(clickhouse_connection_string: 'https://example.com/test') }

View File

@ -3,7 +3,7 @@
require "spec_helper"
require_migration!
RSpec.describe BackfillProductAnalyticsDataCollectorHost, feature_category: :product_analytics do
RSpec.describe BackfillProductAnalyticsDataCollectorHost, feature_category: :product_analytics_data_management do
let!(:application_settings) { table(:application_settings) }
describe '#up' do

View File

@ -390,6 +390,13 @@ RSpec.describe Group, feature_category: :groups_and_projects do
expect(internal_group).to be_invalid
expect(internal_group.errors[:visibility_level]).to include('private is not allowed since this group contains projects with higher visibility.')
end
it 'is valid if higher visibility project is deleted' do
internal_project.update_attribute(:pending_delete, true)
internal_group.visibility_level = Gitlab::VisibilityLevel::PRIVATE
expect(internal_group).to be_valid
end
end
context 'when group has a higher visibility' do

View File

@ -132,13 +132,59 @@ RSpec.describe Notes::QuickActionsService, feature_category: :team_planning do
end
describe '/estimate' do
let(:note_text) { '/estimate 1h' }
before do
# reset to 10 minutes before each test
note.noteable.update!(time_estimate: 600)
end
it 'adds time estimate to noteable' do
content = execute(note)
shared_examples 'does not update time_estimate and displays the correct error message' do
it 'shows validation error message' do
content = execute(note)
expect(content).to be_empty
expect(note.noteable.time_estimate).to eq(3600)
expect(content).to be_empty
expect(note.noteable.errors[:time_estimate]).to include('must have a valid format and be greater than or equal to zero.')
expect(note.noteable.reload.time_estimate).to eq(600)
end
end
context 'when the time estimate is valid' do
let(:note_text) { '/estimate 1h' }
it 'adds time estimate to noteable' do
content = execute(note)
expect(content).to be_empty
expect(note.noteable.reload.time_estimate).to eq(3600)
end
end
context 'when the time estimate is 0' do
let(:note_text) { '/estimate 0' }
it 'adds time estimate to noteable' do
content = execute(note)
expect(content).to be_empty
expect(note.noteable.reload.time_estimate).to eq(0)
end
end
context 'when the time estimate is invalid' do
let(:note_text) { '/estimate a' }
include_examples "does not update time_estimate and displays the correct error message"
end
context 'when the time estimate is partially invalid' do
let(:note_text) { '/estimate 1d 3id' }
include_examples "does not update time_estimate and displays the correct error message"
end
context 'when the time estimate is negative' do
let(:note_text) { '/estimate -1h' }
include_examples "does not update time_estimate and displays the correct error message"
end
end

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe ProductAnalytics::BuildActivityGraphService, feature_category: :product_analytics do
RSpec.describe ProductAnalytics::BuildActivityGraphService, feature_category: :product_analytics_data_management do
let_it_be(:project) { create(:project) }
let_it_be(:time_now) { Time.zone.now }
let_it_be(:time_ago) { Time.zone.now - 5.days }

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe ProductAnalytics::BuildGraphService, feature_category: :product_analytics do
RSpec.describe ProductAnalytics::BuildGraphService, feature_category: :product_analytics_data_management do
let_it_be(:project) { create(:project) }
let_it_be(:events) do

View File

@ -115,6 +115,23 @@ RSpec.describe Projects::DestroyService, :aggregate_failures, :event_store_publi
expect(project.reload.delete_error).to be_present
expect(project.delete_error).to match(error_message)
end
context 'when parent group visibility was made more restrictive while project was marked "pending deletion"' do
let!(:group) { create(:group, :public) }
let!(:project) { create(:project, :repository, :public, namespace: group) }
it 'sets the project visibility level to that of the parent group' do
group.add_owner(user)
project.group.update_attribute(:visibility_level, Gitlab::VisibilityLevel::INTERNAL)
expect(project.reload.visibility_level).to be(Gitlab::VisibilityLevel::PUBLIC)
expect(project.group.visibility_level).to be(Gitlab::VisibilityLevel::INTERNAL)
destroy_project(project, user, {})
expect(project.reload.visibility_level).to be(Gitlab::VisibilityLevel::INTERNAL)
end
end
end
context "deleting a project with merge requests" do

View File

@ -1454,9 +1454,21 @@ RSpec.describe QuickActions::InterpretService, feature_category: :team_planning
let(:issuable) { issue }
end
it_behaves_like 'failed command' do
context 'when provided an invalid estimate' do
let(:content) { '/estimate abc' }
let(:issuable) { issue }
it 'populates {} if content contains an unsupported command' do
_, updates, _ = service.execute(content, issuable)
expect(updates[:time_estimate]).to be_nil
end
it "returns empty message" do
_, _, message = service.execute(content, issuable)
expect(message).to be_empty
end
end
it_behaves_like 'spend command' do