Commit 6980c355 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents 417adc72 18172f28
# frozen_string_literal: true
module ShowInheritedLabelsChecker
extend ActiveSupport::Concern
private
def show_inherited_labels?(include_ancestor_groups)
Feature.enabled?(:show_inherited_labels, @project || @group) || include_ancestor_groups # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
end
......@@ -2,6 +2,7 @@
class Groups::LabelsController < Groups::ApplicationController
include ToggleSubscriptionAction
include ShowInheritedLabelsChecker
before_action :label, only: [:edit, :update, :destroy]
before_action :authorize_admin_labels!, only: [:new, :create, :edit, :update, :destroy]
......@@ -12,8 +13,9 @@ class Groups::LabelsController < Groups::ApplicationController
def index
respond_to do |format|
format.html do
@labels = GroupLabelsFinder
.new(current_user, @group, params.merge(sort: sort)).execute
# at group level we do not want to list project labels,
# we only want `only_group_labels = false` when pulling labels for label filter dropdowns, fetched through json
@labels = available_labels(params.merge(only_group_labels: true)).page(params[:page])
end
format.json do
render json: LabelSerializer.new.represent_appearance(available_labels)
......@@ -74,7 +76,7 @@ class Groups::LabelsController < Groups::ApplicationController
end
def label
@label ||= @group.labels.find(params[:id])
@label ||= available_labels(params.merge(only_group_labels: true)).find(params[:id])
end
alias_method :subscribable_resource, :label
......@@ -102,15 +104,17 @@ class Groups::LabelsController < Groups::ApplicationController
session[:previous_labels_path] = URI(request.referer || '').path
end
def available_labels
def available_labels(options = params)
@available_labels ||=
LabelsFinder.new(
current_user,
group_id: @group.id,
only_group_labels: params[:only_group_labels],
include_ancestor_groups: params[:include_ancestor_groups],
include_descendant_groups: params[:include_descendant_groups],
search: params[:search]).execute
only_group_labels: options[:only_group_labels],
include_ancestor_groups: show_inherited_labels?(params[:include_ancestor_groups]),
sort: sort,
subscribed: options[:subscribed],
include_descendant_groups: options[:include_descendant_groups],
search: options[:search]).execute
end
def sort
......
......@@ -26,8 +26,7 @@ class Import::ManifestController < Import::BaseController
manifest = Gitlab::ManifestImport::Manifest.new(params[:manifest].tempfile)
if manifest.valid?
session[:manifest_import_repositories] = manifest.projects
session[:manifest_import_group_id] = group.id
manifest_import_metadata.save(manifest.projects, group.id)
redirect_to status_import_manifest_path
else
......@@ -96,12 +95,16 @@ class Import::ManifestController < Import::BaseController
# rubocop: disable CodeReuse/ActiveRecord
def group
@group ||= Group.find_by(id: session[:manifest_import_group_id])
@group ||= Group.find_by(id: manifest_import_metadata.group_id)
end
# rubocop: enable CodeReuse/ActiveRecord
def manifest_import_metadata
@manifest_import_status ||= Gitlab::ManifestImport::Metadata.new(current_user, fallback: session)
end
def repositories
@repositories ||= session[:manifest_import_repositories]
@repositories ||= manifest_import_metadata.repositories
end
def find_jobs
......
......@@ -2,6 +2,7 @@
class Projects::LabelsController < Projects::ApplicationController
include ToggleSubscriptionAction
include ShowInheritedLabelsChecker
before_action :check_issuables_available!
before_action :label, only: [:edit, :update, :destroy, :promote]
......@@ -161,7 +162,7 @@ class Projects::LabelsController < Projects::ApplicationController
@available_labels ||=
LabelsFinder.new(current_user,
project_id: @project.id,
include_ancestor_groups: params[:include_ancestor_groups],
include_ancestor_groups: show_inherited_labels?(params[:include_ancestor_groups]),
search: params[:search],
subscribed: params[:subscribed],
sort: sort).execute
......
# frozen_string_literal: true
class GroupLabelsFinder
attr_reader :current_user, :group, :params
def initialize(current_user, group, params = {})
@current_user = current_user
@group = group
@params = params
end
def execute
group.labels
.optionally_subscribed_by(subscriber_id)
.optionally_search(params[:search])
.order_by(params[:sort])
.page(params[:page])
end
private
def subscriber_id
current_user&.id if subscribed?
end
def subscribed?
params[:subscribed] == 'true'
end
end
......@@ -19,7 +19,6 @@
- auto_devops
- backup_restore
- behavior_analytics
- billing
- chatops
- cloud_native_installation
- cluster_cost_optimization
......@@ -87,6 +86,8 @@
- planning_analytics
- product_analytics
- projects
- provision
- purchase
- quality_management
- release_evidence
- release_orchestration
......
---
name: show_inherited_labels
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42960
rollout_issue_url:
group: group::project management
type: development
default_enabled: false
......@@ -67,3 +67,7 @@ That's totally fine. We use HTTP(s) to fetch repository changes from the **prima
## Is this possible to set up a Docker Registry for a **secondary** node that mirrors the one on the **primary** node?
Yes. See [Docker Registry for a **secondary** node](docker_registry.md).
## Can I login to a secondary node?
Yes, but secondary nodes receive all authentication data (like user accounts and logins) from the primary instance. This means you will be re-directed to the primary for authentication and routed back afterwards.
......@@ -117,9 +117,9 @@ For source installations the following settings are nested under `artifacts:` an
|---------|-------------|---------|
| `enabled` | Enable/disable object storage | `false` |
| `remote_directory` | The bucket name where Artifacts will be stored| |
| `direct_upload` | Set to true to enable direct upload of Artifacts without the need of local shared storage. Option may be removed once we decide to support only single storage for all files. | `false` |
| `background_upload` | Set to false to disable automatic upload. Option may be removed once upload is direct to S3 | `true` |
| `proxy_download` | Set to true to enable proxying all files served. Option allows to reduce egress traffic as this allows clients to download directly from remote storage instead of proxying all data | `false` |
| `direct_upload` | Set to `true` to enable direct upload of Artifacts without the need of local shared storage. Option may be removed once we decide to support only single storage for all files. | `false` |
| `background_upload` | Set to `false` to disable automatic upload. Option may be removed once upload is direct to S3 | `true` |
| `proxy_download` | Set to `true` to enable proxying all files served. Option allows to reduce egress traffic as this allows clients to download directly from remote storage instead of proxying all data | `false` |
| `connection` | Various connection options described below | |
#### Connection settings
......@@ -318,7 +318,7 @@ _The uploads are stored by default in
In order to migrate back to local storage:
1. Set both `direct_upload` and `background_upload` to false in `gitlab.rb`, under the artifacts object storage settings.
1. Set both `direct_upload` and `background_upload` to `false` in `gitlab.rb`, under the artifacts object storage settings.
1. [Reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure).
1. Run `gitlab-rake gitlab:artifacts:migrate_to_local`.
1. Disable object_storage for artifacts in `gitlab.rb`:
......
......@@ -92,9 +92,9 @@ then `object_store:`. On Omnibus installations, they are prefixed by
|---------|-------------|---------|
| `enabled` | Enable/disable object storage | `false` |
| `remote_directory` | The bucket name where external diffs will be stored| |
| `direct_upload` | Set to true to enable direct upload of external diffs without the need of local shared storage. Option may be removed once we decide to support only single storage for all files. | `false` |
| `background_upload` | Set to false to disable automatic upload. Option may be removed once upload is direct to S3 | `true` |
| `proxy_download` | Set to true to enable proxying all files served. Option allows to reduce egress traffic as this allows clients to download directly from remote storage instead of proxying all data | `false` |
| `direct_upload` | Set to `true` to enable direct upload of external diffs without the need of local shared storage. Option may be removed once we decide to support only single storage for all files. | `false` |
| `background_upload` | Set to `false` to disable automatic upload. Option may be removed once upload is direct to S3 | `true` |
| `proxy_download` | Set to `true` to enable proxying all files served. Option allows to reduce egress traffic as this allows clients to download directly from remote storage instead of proxying all data | `false` |
| `connection` | Various connection options described below | |
### S3 compatible connection settings
......
......@@ -68,9 +68,9 @@ For source installations the following settings are nested under `uploads:` and
|---------|-------------|---------|
| `enabled` | Enable/disable object storage | `false` |
| `remote_directory` | The bucket name where Uploads will be stored| |
| `direct_upload` | Set to true to remove Puma from the Upload path. Workhorse handles the actual Artifact Upload to Object Storage while Puma does minimal processing to keep track of the upload. There is no need for local shared storage. The option may be removed if support for a single storage type for all files is introduced. Read more on [direct upload](../development/uploads.md#direct-upload). | `false` |
| `background_upload` | Set to false to disable automatic upload. Option may be removed once upload is direct to S3 (if `direct_upload` is set to `true` it will override `background_upload`) | `true` |
| `proxy_download` | Set to true to enable proxying all files served. Option allows to reduce egress traffic as this allows clients to download directly from remote storage instead of proxying all data | `false` |
| `direct_upload` | Set to `true` to remove Puma from the Upload path. Workhorse handles the actual Artifact Upload to Object Storage while Puma does minimal processing to keep track of the upload. There is no need for local shared storage. The option may be removed if support for a single storage type for all files is introduced. Read more on [direct upload](../development/uploads.md#direct-upload). | `false` |
| `background_upload` | Set to `false` to disable automatic upload. Option may be removed once upload is direct to S3 (if `direct_upload` is set to `true` it will override `background_upload`) | `true` |
| `proxy_download` | Set to `true` to enable proxying all files served. Option allows to reduce egress traffic as this allows clients to download directly from remote storage instead of proxying all data | `false` |
| `connection` | Various connection options described below | |
### Connection settings
......
......@@ -172,7 +172,7 @@
:idempotent:
:tags: []
- :name: cronjob:historical_data
:feature_category: :billing
:feature_category: :provision
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
......@@ -236,7 +236,7 @@
:idempotent:
:tags: []
- :name: cronjob:sync_seat_link
:feature_category: :billing
:feature_category: :provision
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
......@@ -700,7 +700,7 @@
:idempotent: true
:tags: []
- :name: sync_seat_link_request
:feature_category: :billing
:feature_category: :provision
:has_external_dependencies: true
:urgency: :low
:resource_boundary: :unknown
......
......@@ -7,7 +7,7 @@ class HistoricalDataWorker # rubocop:disable Scalability/IdempotentWorker
include CronjobQueue
# rubocop:enable Scalability/CronWorkerContext
feature_category :billing
feature_category :provision
def perform
return if License.current.nil? || License.current&.trial?
......
......@@ -3,7 +3,7 @@
class SyncSeatLinkRequestWorker
include ApplicationWorker
feature_category :billing
feature_category :provision
# Retry for up to approximately 6 days
sidekiq_options retry: 20
......
......@@ -7,7 +7,7 @@ class SyncSeatLinkWorker # rubocop:disable Scalability/IdempotentWorker
include CronjobQueue
# rubocop:enable Scalability/CronWorkerContext
feature_category :billing
feature_category :provision
# Retry for up to approximately 17 hours
sidekiq_options retry: 12, dead: false
......
---
name: codeowners_match_ancestor_groups
introduced_by_url:
rollout_issue_url:
group:
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31887
rollout_issue_url:
group: group::source code
type: development
default_enabled: true
# frozen_string_literal: true
module Gitlab
module ManifestImport
class Metadata
EXPIRY_TIME = 1.week
attr_reader :user, :fallback
def initialize(user, fallback: {})
@user = user
@fallback = fallback
end
def save(repositories, group_id)
Gitlab::Redis::SharedState.with do |redis|
redis.multi do
redis.set(key_for('repositories'), Gitlab::Json.dump(repositories), ex: EXPIRY_TIME)
redis.set(key_for('group_id'), group_id, ex: EXPIRY_TIME)
end
end
end
def repositories
redis_get('repositories').then do |repositories|
next unless repositories
Gitlab::Json.parse(repositories).map(&:symbolize_keys)
end || fallback[:manifest_import_repositories]
end
def group_id
redis_get('group_id')&.to_i || fallback[:manifest_import_group_id]
end
private
def key_for(field)
"manifest_import:metadata:user:#{user.id}:#{field}"
end
def redis_get(field)
Gitlab::Redis::SharedState.with do |redis|
redis.get(key_for(field))
end
end
end
end
end
......@@ -9,6 +9,8 @@ RSpec.describe Groups::LabelsController do
before do
group.add_owner(user)
# by default FFs are enabled in specs so we turn it off
stub_feature_flags(show_inherited_labels: false)
sign_in(user)
end
......@@ -32,11 +34,41 @@ RSpec.describe Groups::LabelsController do
subgroup.add_owner(user)
end
it 'returns ancestor group labels' do
get :index, params: { group_id: subgroup, include_ancestor_groups: true, only_group_labels: true }, format: :json
RSpec.shared_examples 'returns ancestor group labels' do
it 'returns ancestor group labels' do
get :index, params: params, format: :json
label_ids = json_response.map {|label| label['title']}
expect(label_ids).to match_array([group_label_1.title, subgroup_label_1.title])
label_ids = json_response.map {|label| label['title']}
expect(label_ids).to match_array([group_label_1.title, subgroup_label_1.title])
end
end
context 'when include_ancestor_groups true' do
let(:params) { { group_id: subgroup, include_ancestor_groups: true, only_group_labels: true } }
it_behaves_like 'returns ancestor group labels'
end
context 'when include_ancestor_groups false' do
let(:params) { { group_id: subgroup, only_group_labels: true } }
it 'does not return ancestor group labels', :aggregate_failures do
get :index, params: params, format: :json
label_ids = json_response.map {|label| label['title']}
expect(label_ids).to match_array([subgroup_label_1.title])
expect(label_ids).not_to include([group_label_1.title])
end
end
context 'when show_inherited_labels enabled' do
let(:params) { { group_id: subgroup } }
before do
stub_feature_flags(show_inherited_labels: true)
end
it_behaves_like 'returns ancestor group labels'
end
end
......
......@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Import::ManifestController do
RSpec.describe Import::ManifestController, :clean_gitlab_redis_shared_state do
include ImportSpecHelper
let_it_be(:user) { create(:user) }
......@@ -16,42 +16,93 @@ RSpec.describe Import::ManifestController do
sign_in(user)
end
def assign_session_group
session[:manifest_import_repositories] = []
session[:manifest_import_group_id] = group.id
describe 'POST upload' do
context 'with a valid manifest' do
it 'saves the manifest and redirects to the status page', :aggregate_failures do
post :upload, params: {
group_id: group.id,
manifest: fixture_file_upload('spec/fixtures/aosp_manifest.xml')
}
metadata = Gitlab::ManifestImport::Metadata.new(user)
expect(metadata.group_id).to eq(group.id)
expect(metadata.repositories.size).to eq(660)
expect(metadata.repositories.first).to include(name: 'platform/build', path: 'build/make')
expect(response).to redirect_to(status_import_manifest_path)
end
end
context 'with an invalid manifest' do
it 'displays an error' do
post :upload, params: {
group_id: group.id,
manifest: fixture_file_upload('spec/fixtures/invalid_manifest.xml')
}
expect(assigns(:errors)).to be_present
end
end
context 'when the user cannot create projects in the group' do
it 'displays an error' do
sign_in(create(:user))
post :upload, params: {
group_id: group.id,
manifest: fixture_file_upload('spec/fixtures/aosp_manifest.xml')
}
expect(assigns(:errors)).to be_present
end
end
end
describe 'GET status' do
let(:repo1) { OpenStruct.new(id: 'test1', url: 'http://demo.host/test1') }
let(:repo2) { OpenStruct.new(id: 'test2', url: 'http://demo.host/test2') }
let(:repo1) { { id: 'test1', url: 'http://demo.host/test1' } }
let(:repo2) { { id: 'test2', url: 'http://demo.host/test2' } }
let(:repos) { [repo1, repo2] }
before do
assign_session_group
shared_examples 'status action' do
it "returns variables for json request" do
project = create(:project, import_type: 'manifest', creator_id: user.id)
session[:manifest_import_repositories] = repos
end
get :status, format: :json
it "returns variables for json request" do
project = create(:project, import_type: 'manifest', creator_id: user.id)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.dig("imported_projects", 0, "id")).to eq(project.id)
expect(json_response.dig("provider_repos", 0, "id")).to eq(repo1[:id])
expect(json_response.dig("provider_repos", 1, "id")).to eq(repo2[:id])
expect(json_response.dig("namespaces", 0, "id")).to eq(group.id)
end
get :status, format: :json
it "does not show already added project" do
project = create(:project, import_type: 'manifest', namespace: user.namespace, import_status: :finished, import_url: repo1[:url])
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.dig("imported_projects", 0, "id")).to eq(project.id)
expect(json_response.dig("provider_repos", 0, "id")).to eq(repo1.id)
expect(json_response.dig("provider_repos", 1, "id")).to eq(repo2.id)
expect(json_response.dig("namespaces", 0, "id")).to eq(group.id)
get :status, format: :json
expect(json_response.dig("imported_projects", 0, "id")).to eq(project.id)
expect(json_response.dig("provider_repos").length).to eq(1)
expect(json_response.dig("provider_repos", 0, "id")).not_to eq(repo1[:id])
end
end
it "does not show already added project" do
project = create(:project, import_type: 'manifest', namespace: user.namespace, import_status: :finished, import_url: repo1.url)
context 'when the data is stored via Gitlab::ManifestImport::Metadata' do
before do
Gitlab::ManifestImport::Metadata.new(user).save(repos, group.id)
end
include_examples 'status action'
end
get :status, format: :json
context 'when the data is stored in the user session' do
before do
session[:manifest_import_repositories] = repos
session[:manifest_import_group_id] = group.id
end
expect(json_response.dig("imported_projects", 0, "id")).to eq(project.id)
expect(json_response.dig("provider_repos").length).to eq(1)
expect(json_response.dig("provider_repos", 0, "id")).not_to eq(repo1.id)
include_examples 'status action'
end
end
end
......@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe Projects::LabelsController do
let(:group) { create(:group) }
let(:project) { create(:project, namespace: group) }
let(:user) { create(:user) }
let_it_be(:group) { create(:group) }
let_it_be(:project, reload: true) { create(:project, namespace: group) }
let_it_be(:user) { create(:user) }
before do
project.add_maintainer(user)
......@@ -14,16 +14,21 @@ RSpec.describe Projects::LabelsController do
end
describe 'GET #index' do
let!(:label_1) { create(:label, project: project, priority: 1, title: 'Label 1') }
let!(:label_2) { create(:label, project: project, priority: 3, title: 'Label 2') }
let!(:label_3) { create(:label, project: project, priority: 1, title: 'Label 3') }
let!(:label_4) { create(:label, project: project, title: 'Label 4') }
let!(:label_5) { create(:label, project: project, title: 'Label 5') }
let!(:group_label_1) { create(:group_label, group: group, title: 'Group Label 1') }
let!(:group_label_2) { create(:group_label, group: group, title: 'Group Label 2') }
let!(:group_label_3) { create(:group_label, group: group, title: 'Group Label 3') }
let!(:group_label_4) { create(:group_label, group: group, title: 'Group Label 4') }
let_it_be(:label_1) { create(:label, project: project, priority: 1, title: 'Label 1') }
let_it_be(:label_2) { create(:label, project: project, priority: 3, title: 'Label 2') }
let_it_be(:label_3) { create(:label, project: project, priority: 1, title: 'Label 3') }
let_it_be(:label_4) { create(:label, project: project, title: 'Label 4') }
let_it_be(:label_5) { create(:label, project: project, title: 'Label 5') }
let_it_be(:group_label_1) { create(:group_label, group: group, title: 'Group Label 1') }
let_it_be(:group_label_2) { create(:group_label, group: group, title: 'Group Label 2') }
let_it_be(:group_label_3) { create(:group_label, group: group, title: 'Group Label 3') }
let_it_be(:group_label_4) { create(:group_label, group: group, title: 'Group Label 4') }
let_it_be(:group_labels) { [group_label_3, group_label_4]}
let_it_be(:project_labels) { [label_4, label_5]}
let_it_be(:group_priority_labels) { [group_label_1, group_label_2]}
let_it_be(:project_priority_labels) { [label_1, label_2, label_3]}
before do
create(:label_priority, project: project, label: group_label_1, priority: 3)
......@@ -68,6 +73,60 @@ RSpec.describe Projects::LabelsController do
end
end
context 'with subgroups' do
let_it_be(:subgroup) { create(:group, parent: group) }
let_it_be(:subgroup_label_1) { create(:group_label, group: subgroup, title: 'subgroup_label_1') }
let_it_be(:subgroup_label_2) { create(:group_label, group: subgroup, title: 'subgroup_label_2') }
before do
project.update!(namespace: subgroup)
subgroup.add_owner(user)
create(:label_priority, project: project, label: subgroup_label_2, priority: 1)
end
RSpec.shared_examples 'returns ancestor group labels' do
it 'returns ancestor group labels', :aggregate_failures do
get :index, params: params
expect(assigns(:labels)).to match_array([subgroup_label_1] + group_labels + project_labels)
expect(assigns(:prioritized_labels)).to match_array([subgroup_label_2] + group_priority_labels + project_priority_labels)
end
end
context 'when show_inherited_labels disabled' do
before do
stub_feature_flags(show_inherited_labels: false)
end
context 'when include_ancestor_groups false' do
let(:params) { { namespace_id: project.namespace.to_param, project_id: project } }
it 'does not return ancestor group labels', :aggregate_failures do
get :index, params: params
expect(assigns(:labels)).to match_array([subgroup_label_1] + project_labels)
expect(assigns(:prioritized_labels)).to match_array([subgroup_label_2] + project_priority_labels)
end
end
context 'when include_ancestor_groups true' do
let(:params) { { namespace_id: project.namespace.to_param, project_id: project, include_ancestor_groups: true } }
it_behaves_like 'returns ancestor group labels'
end
end
context 'when show_inherited_labels enabled' do
let(:params) { { namespace_id: project.namespace.to_param, project_id: project } }
before do
stub_feature_flags(show_inherited_labels: true)
end
it_behaves_like 'returns ancestor group labels'
end
end
def list_labels
get :index, params: { namespace_id: project.namespace.to_param, project_id: project }
end
......@@ -75,7 +134,7 @@ RSpec.describe Projects::LabelsController do
describe 'POST #generate' do
context 'personal project' do
let(:personal_project) { create(:project, namespace: user.namespace) }
let_it_be(:personal_project) { create(:project, namespace: user.namespace) }
it 'creates labels' do
post :generate, params: { namespace_id: personal_project.namespace.to_param, project_id: personal_project }
......@@ -116,8 +175,8 @@ RSpec.describe Projects::LabelsController do
end
describe 'POST #promote' do
let!(:promoted_label_name) { "Promoted Label" }
let!(:label_1) { create(:label, title: promoted_label_name, project: project) }
let_it_be(:promoted_label_name) { "Promoted Label" }
let_it_be(:label_1) { create(:label, title: promoted_label_name, project: project) }
context 'not group reporters' do
it 'denies access' do
......@@ -196,7 +255,7 @@ RSpec.describe Projects::LabelsController do
end
context 'when requesting a redirected path' do
let!(:redirect_route) { project.redirect_routes.create(path: project.full_path + 'old') }
let_it_be(:redirect_route) { project.redirect_routes.create(path: project.full_path + 'old') }
it 'redirects to the canonical path' do
get :index, params: { namespace_id: project.namespace, project_id: project.to_param + 'old' }
......@@ -242,7 +301,7 @@ RSpec.describe Projects::LabelsController do
end
context 'when requesting a redirected path' do
let!(:redirect_route) { project.redirect_routes.create(path: project.full_path + 'old') }
let_it_be(:redirect_route) { project.redirect_routes.create(path: project.full_path + 'old') }
it 'returns not found' do
post :generate, params: { namespace_id: project.namespace, project_id: project.to_param + 'old' }
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GroupLabelsFinder, '#execute' do
let!(:group) { create(:group) }
let!(:user) { create(:user) }
let!(:label1) { create(:group_label, title: 'Foo', description: 'Lorem ipsum', group: group) }
let!(:label2) { create(:group_label, title: 'Bar', description: 'Fusce consequat', group: group) }
it 'returns all group labels sorted by name if no params' do
result = described_class.new(user, group).execute
expect(result.to_a).to match_array([label2, label1])
end
it 'returns all group labels sorted by name desc' do
result = described_class.new(user, group, sort: 'name_desc').execute
expect(result.to_a).to match_array([label2, label1])
end
it 'returns group labels that match search' do
result = described_class.new(user, group, search: 'Foo').execute
expect(result.to_a).to match_array([label1])
end
it 'returns group labels user subscribed to' do
label2.subscribe(user)
result = described_class.new(user, group, subscribed: 'true').execute
expect(result.to_a).to match_array([label2])
end
it 'returns second page of labels' do
result = described_class.new(user, group, page: '2').execute
expect(result.to_a).to match_array([])
end
end
<manifest>
<remote review="invalid-url" />
<project name="platform/build"/>
</manifest>
......@@ -12,19 +12,7 @@ RSpec.describe Gitlab::ManifestImport::Manifest do
end
context 'missing or invalid attributes' do
let(:file) { Tempfile.new('foo') }
before do
content = <<~EOS
<manifest>
<remote review="invalid-url" />
<project name="platform/build"/>
</manifest>
EOS
file.write(content)
file.rewind
end
let(:file) { File.open(Rails.root.join('spec/fixtures/invalid_manifest.xml')) }
it { expect(manifest.valid?).to be false }
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::ManifestImport::Metadata, :clean_gitlab_redis_shared_state do
let(:user) { double(id: 1) }
let(:repositories) do
[
{ id: 'test1', url: 'http://demo.host/test1' },
{ id: 'test2', url: 'http://demo.host/test2' }
]
end
describe '#save' do
it 'stores data in Redis with an expiry of EXPIRY_TIME' do
status = described_class.new(user)
repositories_key = 'manifest_import:metadata:user:1:repositories'
group_id_key = 'manifest_import:metadata:user:1:group_id'
status.save(repositories, 2)
Gitlab::Redis::SharedState.with do |redis|
expect(redis.ttl(repositories_key)).to be_within(5).of(described_class::EXPIRY_TIME)
expect(redis.ttl(group_id_key)).to be_within(5).of(described_class::EXPIRY_TIME)
end
end
end
describe '#repositories' do
it 'allows repositories to round-trip with symbol keys' do
status = described_class.new(user)
status.save(repositories, 2)
expect(status.repositories).to eq(repositories)
end
it 'uses the fallback when there is nothing in Redis' do
fallback = { manifest_import_repositories: repositories }
status = described_class.new(user, fallback: fallback)
expect(status.repositories).to eq(repositories)
end
end
describe '#group_id' do
it 'returns the group ID as an integer' do
status = described_class.new(user)
status.save(repositories, 2)
expect(status.group_id).to eq(2)
end
it 'uses the fallback when there is nothing in Redis' do
fallback = { manifest_import_group_id: 3 }
status = described_class.new(user, fallback: fallback)
expect(status.group_id).to eq(3)
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment