Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
5fe2ffc8
Commit
5fe2ffc8
authored
Feb 01, 2021
by
GitLab Bot
Browse files
Options
Browse Files
Download
Plain Diff
Automatic merge of gitlab-org/gitlab master
parents
a0f57c39
4d8eae7f
Changes
55
Hide whitespace changes
Inline
Side-by-side
Showing
55 changed files
with
446 additions
and
256 deletions
+446
-256
app/assets/javascripts/filtered_search/recent_searches_storage_keys.js
...vascripts/filtered_search/recent_searches_storage_keys.js
+2
-0
app/assets/javascripts/pages/projects/project_members/index.js
...ssets/javascripts/pages/projects/project_members/index.js
+64
-0
app/assets/javascripts/projects/members/constants.js
app/assets/javascripts/projects/members/constants.js
+1
-0
app/assets/javascripts/projects/members/utils.js
app/assets/javascripts/projects/members/utils.js
+8
-0
app/controllers/projects/project_members_controller.rb
app/controllers/projects/project_members_controller.rb
+4
-0
app/models/ci/build.rb
app/models/ci/build.rb
+5
-40
app/models/ci/processable.rb
app/models/ci/processable.rb
+56
-0
app/models/ci/resource.rb
app/models/ci/resource.rb
+3
-3
app/models/ci/resource_group.rb
app/models/ci/resource_group.rb
+5
-5
app/models/commit_status.rb
app/models/commit_status.rb
+1
-9
app/models/readme_blob.rb
app/models/readme_blob.rb
+0
-17
app/models/repository.rb
app/models/repository.rb
+3
-28
app/services/ci/resource_groups/assign_resource_from_resource_group_service.rb
...rce_groups/assign_resource_from_resource_group_service.rb
+2
-2
app/views/projects/project_members/index.html.haml
app/views/projects/project_members/index.html.haml
+35
-14
changelogs/unreleased/281677_space_in_filename.yml
changelogs/unreleased/281677_space_in_filename.yml
+5
-0
config/feature_flags/development/vue_project_members_list.yml
...ig/feature_flags/development/vue_project_members_list.yml
+8
-0
doc/api/members.md
doc/api/members.md
+5
-2
ee/changelogs/unreleased/vij-add-last-activity.yml
ee/changelogs/unreleased/vij-add-last-activity.yml
+5
-0
ee/lib/ee/api/entities/billable_member.rb
ee/lib/ee/api/entities/billable_member.rb
+1
-0
ee/spec/features/groups/members/override_ldap_memberships_spec.rb
...features/groups/members/override_ldap_memberships_spec.rb
+1
-0
ee/spec/features/projects/audit_events_spec.rb
ee/spec/features/projects/audit_events_spec.rb
+2
-0
ee/spec/features/projects/members/invite_group_and_members_spec.rb
...eatures/projects/members/invite_group_and_members_spec.rb
+1
-0
ee/spec/features/projects/members/member_is_removed_from_project_spec.rb
...s/projects/members/member_is_removed_from_project_spec.rb
+2
-0
ee/spec/lib/ee/api/entities/billable_member_spec.rb
ee/spec/lib/ee/api/entities/billable_member_spec.rb
+7
-1
lib/gitlab/ci/config/entry/job.rb
lib/gitlab/ci/config/entry/job.rb
+2
-4
lib/gitlab/ci/config/entry/processable.rb
lib/gitlab/ci/config/entry/processable.rb
+5
-3
lib/gitlab/ci/pipeline/seed/build/resource_group.rb
lib/gitlab/ci/pipeline/seed/build/resource_group.rb
+5
-5
lib/gitlab/search/query.rb
lib/gitlab/search/query.rb
+15
-3
locale/gitlab.pot
locale/gitlab.pot
+6
-0
spec/factories/ci/resource.rb
spec/factories/ci/resource.rb
+1
-1
spec/features/admin/admin_projects_spec.rb
spec/features/admin/admin_projects_spec.rb
+2
-0
spec/features/projects/members/anonymous_user_sees_members_spec.rb
...ures/projects/members/anonymous_user_sees_members_spec.rb
+2
-0
spec/features/projects/members/group_members_spec.rb
spec/features/projects/members/group_members_spec.rb
+2
-0
spec/features/projects/members/groups_with_access_list_spec.rb
...features/projects/members/groups_with_access_list_spec.rb
+2
-0
spec/features/projects/members/invite_group_spec.rb
spec/features/projects/members/invite_group_spec.rb
+1
-0
spec/features/projects/members/list_spec.rb
spec/features/projects/members/list_spec.rb
+8
-0
spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb
...s/members/master_adds_member_with_expiration_date_spec.rb
+2
-0
spec/features/projects/members/sorting_spec.rb
spec/features/projects/members/sorting_spec.rb
+2
-0
spec/features/projects/members/tabs_spec.rb
spec/features/projects/members/tabs_spec.rb
+1
-0
spec/features/projects/settings/user_manages_project_members_spec.rb
...es/projects/settings/user_manages_project_members_spec.rb
+2
-0
spec/frontend/projects/members/utils_spec.js
spec/frontend/projects/members/utils_spec.js
+14
-0
spec/lib/gitlab/ci/config/entry/processable_spec.rb
spec/lib/gitlab/ci/config/entry/processable_spec.rb
+29
-0
spec/lib/gitlab/file_finder_spec.rb
spec/lib/gitlab/file_finder_spec.rb
+8
-0
spec/lib/gitlab/repository_cache_adapter_spec.rb
spec/lib/gitlab/repository_cache_adapter_spec.rb
+3
-4
spec/lib/gitlab/search/query_spec.rb
spec/lib/gitlab/search/query_spec.rb
+18
-0
spec/models/ci/build_spec.rb
spec/models/ci/build_spec.rb
+0
-54
spec/models/ci/pipeline_spec.rb
spec/models/ci/pipeline_spec.rb
+1
-1
spec/models/ci/processable_spec.rb
spec/models/ci/processable_spec.rb
+54
-0
spec/models/ci/resource_group_spec.rb
spec/models/ci/resource_group_spec.rb
+6
-6
spec/models/ci/resource_spec.rb
spec/models/ci/resource_spec.rb
+1
-1
spec/models/commit_status_spec.rb
spec/models/commit_status_spec.rb
+0
-17
spec/models/readme_blob_spec.rb
spec/models/readme_blob_spec.rb
+0
-17
spec/models/repository_spec.rb
spec/models/repository_spec.rb
+1
-17
spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb
.../ci/create_pipeline_service/parent_child_pipeline_spec.rb
+25
-0
spec/services/ci/create_pipeline_service_spec.rb
spec/services/ci/create_pipeline_service_spec.rb
+2
-2
No files found.
app/assets/javascripts/filtered_search/recent_searches_storage_keys.js
View file @
5fe2ffc8
...
...
@@ -3,4 +3,6 @@ export default {
merge_requests
:
'
merge-request-recent-searches
'
,
group_members
:
'
group-members-recent-searches
'
,
group_invited_members
:
'
group-invited-members-recent-searches
'
,
project_members
:
'
project-members-recent-searches
'
,
project_group_links
:
'
project-group-links-recent-searches
'
,
};
app/assets/javascripts/pages/projects/project_members/index.js
View file @
5fe2ffc8
...
...
@@ -6,6 +6,8 @@ import groupsSelect from '~/groups_select';
import
RemoveMemberModal
from
'
~/vue_shared/components/remove_member_modal.vue
'
;
import
initInviteMembersModal
from
'
~/invite_members/init_invite_members_modal
'
;
import
initInviteMembersTrigger
from
'
~/invite_members/init_invite_members_trigger
'
;
import
{
__
}
from
'
~/locale
'
;
import
{
deprecatedCreateFlash
as
flash
}
from
'
~/flash
'
;
function
mountRemoveMemberModal
()
{
const
el
=
document
.
querySelector
(
'
.js-remove-member-modal
'
);
...
...
@@ -32,3 +34,65 @@ document.addEventListener('DOMContentLoaded', () => {
new
Members
();
// eslint-disable-line no-new
new
UsersSelect
();
// eslint-disable-line no-new
});
if
(
window
.
gon
.
features
.
vueProjectMembersList
)
{
const
SHARED_FIELDS
=
[
'
account
'
,
'
expires
'
,
'
maxRole
'
,
'
expiration
'
,
'
actions
'
];
Promise
.
all
([
import
(
'
~/members/index
'
),
import
(
'
~/members/utils
'
),
import
(
'
~/projects/members/utils
'
),
import
(
'
~/locale
'
),
])
.
then
(
([
{
initMembersApp
},
{
groupLinkRequestFormatter
},
{
projectMemberRequestFormatter
},
{
s__
},
])
=>
{
initMembersApp
(
document
.
querySelector
(
'
.js-project-members-list
'
),
{
tableFields
:
SHARED_FIELDS
.
concat
([
'
source
'
,
'
granted
'
]),
tableAttrs
:
{
tr
:
{
'
data-qa-selector
'
:
'
member_row
'
}
},
tableSortableFields
:
[
'
account
'
,
'
granted
'
,
'
maxRole
'
,
'
lastSignIn
'
],
requestFormatter
:
projectMemberRequestFormatter
,
filteredSearchBar
:
{
show
:
true
,
tokens
:
[
'
with_inherited_permissions
'
],
searchParam
:
'
search
'
,
placeholder
:
s__
(
'
Members|Filter members
'
),
recentSearchesStorageKey
:
'
project_members
'
,
},
});
initMembersApp
(
document
.
querySelector
(
'
.js-project-group-links-list
'
),
{
tableFields
:
SHARED_FIELDS
.
concat
(
'
granted
'
),
tableAttrs
:
{
table
:
{
'
data-qa-selector
'
:
'
groups_list
'
},
tr
:
{
'
data-qa-selector
'
:
'
group_row
'
},
},
requestFormatter
:
groupLinkRequestFormatter
,
filteredSearchBar
:
{
show
:
true
,
tokens
:
[],
searchParam
:
'
search_groups
'
,
placeholder
:
s__
(
'
Members|Search groups
'
),
recentSearchesStorageKey
:
'
project_group_links
'
,
},
});
initMembersApp
(
document
.
querySelector
(
'
.js-project-invited-members-list
'
),
{
tableFields
:
SHARED_FIELDS
.
concat
(
'
invited
'
),
requestFormatter
:
projectMemberRequestFormatter
,
});
initMembersApp
(
document
.
querySelector
(
'
.js-project-access-requests-list
'
),
{
tableFields
:
SHARED_FIELDS
.
concat
(
'
requested
'
),
requestFormatter
:
projectMemberRequestFormatter
,
});
},
)
.
catch
(()
=>
{
flash
(
__
(
'
An error occurred while loading the members, please try again.
'
));
});
}
app/assets/javascripts/projects/members/constants.js
0 → 100644
View file @
5fe2ffc8
export
const
PROJECT_MEMBER_BASE_PROPERTY_NAME
=
'
project_member
'
;
app/assets/javascripts/projects/members/utils.js
0 → 100644
View file @
5fe2ffc8
import
{
baseRequestFormatter
}
from
'
~/members/utils
'
;
import
{
PROJECT_MEMBER_BASE_PROPERTY_NAME
}
from
'
./constants
'
;
import
{
MEMBER_ACCESS_LEVEL_PROPERTY_NAME
}
from
'
~/members/constants
'
;
export
const
projectMemberRequestFormatter
=
baseRequestFormatter
(
PROJECT_MEMBER_BASE_PROPERTY_NAME
,
MEMBER_ACCESS_LEVEL_PROPERTY_NAME
,
);
app/controllers/projects/project_members_controller.rb
View file @
5fe2ffc8
...
...
@@ -8,6 +8,10 @@ class Projects::ProjectMembersController < Projects::ApplicationController
# Authorize
before_action
:authorize_admin_project_member!
,
except:
[
:index
,
:leave
,
:request_access
]
before_action
do
push_frontend_feature_flag
(
:vue_project_members_list
,
@project
)
end
feature_category
:authentication_and_authorization
def
index
...
...
app/models/ci/build.rb
View file @
5fe2ffc8
...
...
@@ -20,7 +20,6 @@ module Ci
belongs_to
:runner
belongs_to
:trigger_request
belongs_to
:erased_by
,
class_name:
'User'
belongs_to
:resource_group
,
class_name:
'Ci::ResourceGroup'
,
inverse_of: :builds
belongs_to
:pipeline
,
class_name:
'Ci::Pipeline'
,
foreign_key: :commit_id
RUNNER_FEATURES
=
{
...
...
@@ -38,7 +37,6 @@ module Ci
DEGRADATION_THRESHOLD_VARIABLE_NAME
=
'DEGRADATION_THRESHOLD'
has_one
:deployment
,
as: :deployable
,
class_name:
'Deployment'
has_one
:resource
,
class_name:
'Ci::Resource'
,
inverse_of: :build
has_one
:pending_state
,
class_name:
'Ci::BuildPendingState'
,
inverse_of: :build
has_many
:trace_sections
,
class_name:
'Ci::BuildTraceSection'
has_many
:trace_chunks
,
class_name:
'Ci::BuildTraceChunk'
,
foreign_key: :build_id
,
inverse_of: :build
...
...
@@ -236,21 +234,14 @@ module Ci
state_machine
:status
do
event
:enqueue
do
transition
[
:created
,
:skipped
,
:manual
,
:scheduled
]
=>
:waiting_for_resource
,
if: :requires_resource?
transition
[
:created
,
:skipped
,
:manual
,
:scheduled
]
=>
:preparing
,
if: :any_unmet_prerequisites?
end
event
:enqueue_scheduled
do
transition
scheduled: :waiting_for_resource
,
if: :requires_resource?
transition
scheduled: :preparing
,
if: :any_unmet_prerequisites?
transition
scheduled: :pending
end
event
:enqueue_waiting_for_resource
do
transition
waiting_for_resource: :preparing
,
if: :any_unmet_prerequisites?
transition
waiting_for_resource: :pending
end
event
:enqueue_preparing
do
transition
preparing: :pending
end
...
...
@@ -279,23 +270,6 @@ module Ci
build
.
scheduled_at
=
build
.
options_scheduled_at
end
before_transition
any
=>
:waiting_for_resource
do
|
build
|
build
.
waiting_for_resource_at
=
Time
.
current
end
before_transition
on: :enqueue_waiting_for_resource
do
|
build
|
next
unless
build
.
requires_resource?
build
.
resource_group
.
assign_resource_to
(
build
)
# If false is returned, it stops the transition
end
after_transition
any
=>
:waiting_for_resource
do
|
build
|
build
.
run_after_commit
do
Ci
::
ResourceGroups
::
AssignResourceFromResourceGroupWorker
.
perform_async
(
build
.
resource_group_id
)
end
end
before_transition
on: :enqueue_preparing
do
|
build
|
!
build
.
any_unmet_prerequisites?
# If false is returned, it stops the transition
end
...
...
@@ -328,16 +302,6 @@ module Ci
end
end
after_transition
any
=>
::
Ci
::
Build
.
completed_statuses
do
|
build
|
next
unless
build
.
resource_group_id
.
present?
next
unless
build
.
resource_group
.
release_resource_from
(
build
)
build
.
run_after_commit
do
Ci
::
ResourceGroups
::
AssignResourceFromResourceGroupWorker
.
perform_async
(
build
.
resource_group_id
)
end
end
after_transition
any
=>
[
:success
,
:failed
,
:canceled
]
do
|
build
|
build
.
run_after_commit
do
build
.
run_status_commit_hooks!
...
...
@@ -467,6 +431,11 @@ module Ci
pipeline
.
builds
.
retried
.
where
(
name:
self
.
name
).
count
end
override
:all_met_to_become_pending?
def
all_met_to_become_pending?
super
&&
!
any_unmet_prerequisites?
end
def
any_unmet_prerequisites?
prerequisites
.
present?
end
...
...
@@ -501,10 +470,6 @@ module Ci
end
end
def
requires_resource?
self
.
resource_group_id
.
present?
end
def
has_environment?
environment
.
present?
end
...
...
app/models/ci/processable.rb
View file @
5fe2ffc8
...
...
@@ -3,6 +3,11 @@
module
Ci
class
Processable
<
::
CommitStatus
include
Gitlab
::
Utils
::
StrongMemoize
extend
::
Gitlab
::
Utils
::
Override
has_one
:resource
,
class_name:
'Ci::Resource'
,
foreign_key:
'build_id'
,
inverse_of: :processable
belongs_to
:resource_group
,
class_name:
'Ci::ResourceGroup'
,
inverse_of: :processables
accepts_nested_attributes_for
:needs
...
...
@@ -20,6 +25,48 @@ module Ci
where
(
'NOT EXISTS (?)'
,
needs
)
end
state_machine
:status
do
event
:enqueue
do
transition
[
:created
,
:skipped
,
:manual
,
:scheduled
]
=>
:waiting_for_resource
,
if: :with_resource_group?
end
event
:enqueue_scheduled
do
transition
scheduled: :waiting_for_resource
,
if: :with_resource_group?
end
event
:enqueue_waiting_for_resource
do
transition
waiting_for_resource: :preparing
,
if: :any_unmet_prerequisites?
transition
waiting_for_resource: :pending
end
before_transition
any
=>
:waiting_for_resource
do
|
processable
|
processable
.
waiting_for_resource_at
=
Time
.
current
end
before_transition
on: :enqueue_waiting_for_resource
do
|
processable
|
next
unless
processable
.
with_resource_group?
processable
.
resource_group
.
assign_resource_to
(
processable
)
end
after_transition
any
=>
:waiting_for_resource
do
|
processable
|
processable
.
run_after_commit
do
Ci
::
ResourceGroups
::
AssignResourceFromResourceGroupWorker
.
perform_async
(
processable
.
resource_group_id
)
end
end
after_transition
any
=>
::
Ci
::
Processable
.
completed_statuses
do
|
processable
|
next
unless
processable
.
with_resource_group?
next
unless
processable
.
resource_group
.
release_resource_from
(
processable
)
processable
.
run_after_commit
do
Ci
::
ResourceGroups
::
AssignResourceFromResourceGroupWorker
.
perform_async
(
processable
.
resource_group_id
)
end
end
end
def
self
.
select_with_aggregated_needs
(
project
)
aggregated_needs_names
=
Ci
::
BuildNeed
.
scoped_build
...
...
@@ -77,6 +124,15 @@ module Ci
raise
NotImplementedError
end
override
:all_met_to_become_pending?
def
all_met_to_become_pending?
super
&&
!
with_resource_group?
end
def
with_resource_group?
self
.
resource_group_id
.
present?
end
# Overriding scheduling_type enum's method for nil `scheduling_type`s
def
scheduling_type_dag?
scheduling_type
.
nil?
?
find_legacy_scheduling_type
==
:dag
:
super
...
...
app/models/ci/resource.rb
View file @
5fe2ffc8
...
...
@@ -5,9 +5,9 @@ module Ci
extend
Gitlab
::
Ci
::
Model
belongs_to
:resource_group
,
class_name:
'Ci::ResourceGroup'
,
inverse_of: :resources
belongs_to
:
build
,
class_name:
'Ci::Buil
d'
,
inverse_of: :resource
belongs_to
:
processable
,
class_name:
'Ci::Processable'
,
foreign_key:
'build_i
d'
,
inverse_of: :resource
scope
:free
,
->
{
where
(
build
:
nil
)
}
scope
:retained_by
,
->
(
build
)
{
where
(
build:
build
)
}
scope
:free
,
->
{
where
(
processable
:
nil
)
}
scope
:retained_by
,
->
(
processable
)
{
where
(
processable:
processable
)
}
end
end
app/models/ci/resource_group.rb
View file @
5fe2ffc8
...
...
@@ -7,7 +7,7 @@ module Ci
belongs_to
:project
,
inverse_of: :resource_groups
has_many
:resources
,
class_name:
'Ci::Resource'
,
inverse_of: :resource_group
has_many
:
builds
,
class_name:
'Ci::Build
'
,
inverse_of: :resource_group
has_many
:
processables
,
class_name:
'Ci::Processable
'
,
inverse_of: :resource_group
validates
:key
,
length:
{
maximum:
255
},
...
...
@@ -19,12 +19,12 @@ module Ci
##
# NOTE: This is concurrency-safe method that the subquery in the `UPDATE`
# works as explicit locking.
def
assign_resource_to
(
build
)
resources
.
free
.
limit
(
1
).
update_all
(
build_id:
build
.
id
)
>
0
def
assign_resource_to
(
processable
)
resources
.
free
.
limit
(
1
).
update_all
(
build_id:
processable
.
id
)
>
0
end
def
release_resource_from
(
build
)
resources
.
retained_by
(
build
).
update_all
(
build_id:
nil
)
>
0
def
release_resource_from
(
processable
)
resources
.
retained_by
(
processable
).
update_all
(
build_id:
nil
)
>
0
end
private
...
...
app/models/commit_status.rb
View file @
5fe2ffc8
...
...
@@ -255,15 +255,7 @@ class CommitStatus < ApplicationRecord
end
def
all_met_to_become_pending?
!
any_unmet_prerequisites?
&&
!
requires_resource?
end
def
any_unmet_prerequisites?
false
end
def
requires_resource?
false
true
end
def
auto_canceled?
...
...
app/models/readme_blob.rb
deleted
100644 → 0
View file @
a0f57c39
# frozen_string_literal: true
class
ReadmeBlob
<
SimpleDelegator
include
BlobActiveModel
attr_reader
:repository
def
initialize
(
blob
,
repository
)
@repository
=
repository
super
(
blob
)
end
def
rendered_markup
repository
.
rendered_readme
end
end
app/models/repository.rb
View file @
5fe2ffc8
...
...
@@ -39,7 +39,7 @@ class Repository
#
# For example, for entry `:commit_count` there's a method called `commit_count` which
# stores its data in the `commit_count` cache key.
CACHED_METHODS
=
%i(size commit_count re
ndered_readme re
adme_path contribution_guide
CACHED_METHODS
=
%i(size commit_count readme_path contribution_guide
changelog license_blob license_key gitignore
gitlab_ci_yml branch_names tag_names branch_count
tag_count avatar exists? root_ref merged_branch_names
...
...
@@ -53,7 +53,7 @@ class Repository
# changed. This Hash maps file types (as returned by Gitlab::FileDetector) to
# the corresponding methods to call for refreshing caches.
METHOD_CACHES_FOR_FILE_TYPES
=
{
readme:
%i(re
ndered_readme re
adme_path)
,
readme:
%i(readme_path)
,
changelog: :changelog
,
license:
%i(license_blob license_key license)
,
contributing: :contribution_guide
,
...
...
@@ -498,23 +498,7 @@ class Repository
end
def
blob_at
(
sha
,
path
)
blob
=
Blob
.
decorate
(
raw_repository
.
blob_at
(
sha
,
path
),
container
)
# Don't attempt to return a special result if there is no blob at all
return
unless
blob
# Don't attempt to return a special result if this can't be a README
return
blob
unless
Gitlab
::
FileDetector
.
type_of
(
blob
.
name
)
==
:readme
# Don't attempt to return a special result unless we're looking at HEAD
return
blob
unless
head_commit
&
.
sha
==
sha
case
path
when
head_tree
&
.
readme_path
ReadmeBlob
.
new
(
blob
,
self
)
else
blob
end
Blob
.
decorate
(
raw_repository
.
blob_at
(
sha
,
path
),
container
)
rescue
Gitlab
::
Git
::
Repository
::
NoRepository
nil
end
...
...
@@ -612,15 +596,6 @@ class Repository
end
cache_method
:readme_path
def
rendered_readme
return
unless
readme
context
=
{
project:
project
}
MarkupHelper
.
markup_unsafe
(
readme
.
name
,
readme
.
data
,
context
)
end
cache_method
:rendered_readme
def
contribution_guide
file_on_head
(
:contributing
)
end
...
...
app/services/ci/resource_groups/assign_resource_from_resource_group_service.rb
View file @
5fe2ffc8
...
...
@@ -7,8 +7,8 @@ module Ci
def
execute
(
resource_group
)
free_resources
=
resource_group
.
resources
.
free
.
count
resource_group
.
builds
.
waiting_for_resource
.
take
(
free_resources
).
each
do
|
build
|
build
.
enqueue_waiting_for_resource
resource_group
.
processables
.
waiting_for_resource
.
take
(
free_resources
).
each
do
|
processable
|
processable
.
enqueue_waiting_for_resource
end
end
# rubocop: enable CodeReuse/ActiveRecord
...
...
app/views/projects/project_members/index.html.haml
View file @
5fe2ffc8
-
page_title
_
(
"Members"
)
-
group
=
@project
.
group
-
vue_project_members_list_enabled
=
Feature
.
enabled?
(
:vue_project_members_list
,
@project
)
.js-remove-member-modal
.row.gl-mt-3
...
...
@@ -74,24 +75,44 @@
%span
.badge.badge-pill
=
@requesters
.
count
.tab-content
#tab-members
.tab-pane
{
class:
(
'active'
unless
groups_tab_active?
)
}
=
render
'projects/project_members/team'
,
project:
@project
,
group:
group
,
members:
@project_members
,
current_user_is_group_owner:
current_user_is_group_owner?
(
@project
)
-
if
vue_project_members_list_enabled
.js-project-members-list
{
data:
project_members_list_data_attributes
(
@project
,
@project_members
)
}
.loading
.spinner.spinner-md
-
else
=
render
'projects/project_members/team'
,
project:
@project
,
group:
group
,
members:
@project_members
,
current_user_is_group_owner:
current_user_is_group_owner?
(
@project
)
=
paginate
@project_members
,
theme:
"gitlab"
,
params:
{
search_groups:
nil
}
-
if
show_groups?
(
@group_links
)
#tab-groups
.tab-pane
{
class:
(
'active'
if
groups_tab_active?
)
}
=
render
'projects/project_members/groups'
,
group_links:
@group_links
-
if
vue_project_members_list_enabled
.js-project-group-links-list
{
data:
project_group_links_list_data_attributes
(
@project
,
@group_links
)
}
.loading
.spinner.spinner-md
-
else
=
render
'projects/project_members/groups'
,
group_links:
@group_links
-
if
show_invited_members?
(
@project
,
@invited_members
)
#tab-invited-members
.tab-pane
.card.card-without-border
=
render
'shared/members/tab_pane/header'
do
=
render
'shared/members/tab_pane/title'
do
=
html_escape
(
_
(
'Members invited to %{strong_start}%{project_name}%{strong_end}'
))
%
{
project_name:
@project
.
name
,
strong_start:
'<strong>'
.
html_safe
,
strong_end:
'</strong>'
.
html_safe
}
%ul
.content-list.members-list
=
render
partial:
'shared/members/member'
,
collection:
@invited_members
,
as: :member
,
locals:
{
membership_source:
@project
,
group:
group
,
current_user_is_group_owner:
current_user_is_group_owner?
(
@project
)
}
-
if
vue_project_members_list_enabled
.js-project-invited-members-list
{
data:
project_members_list_data_attributes
(
@project
,
@invited_members
)
}
.loading
.spinner.spinner-md
-
else
.card.card-without-border
=
render
'shared/members/tab_pane/header'
do
=
render
'shared/members/tab_pane/title'
do
=
html_escape
(
_
(
'Members invited to %{strong_start}%{project_name}%{strong_end}'
))
%
{
project_name:
@project
.
name
,
strong_start:
'<strong>'
.
html_safe
,
strong_end:
'</strong>'
.
html_safe
}
%ul
.content-list.members-list
=
render
partial:
'shared/members/member'
,
collection:
@invited_members
,
as: :member
,
locals:
{
membership_source:
@project
,
group:
group
,
current_user_is_group_owner:
current_user_is_group_owner?
(
@project
)
}
-
if
show_access_requests?
(
@project
,
@requesters
)
#tab-access-requests
.tab-pane
.card.card-without-border
=
render
'shared/members/tab_pane/header'
do
=
render
'shared/members/tab_pane/title'
do
=
html_escape
(
_
(
'Users requesting access to %{strong_start}%{project_name}%{strong_end}'
))
%
{
project_name:
@project
.
name
,
strong_start:
'<strong>'
.
html_safe
,
strong_end:
'</strong>'
.
html_safe
}
%ul
.content-list.members-list
=
render
partial:
'shared/members/member'
,
collection:
@requesters
,
as: :member
,
locals:
{
membership_source:
@project
,
group:
group
}
-
if
vue_project_members_list_enabled
.js-project-access-requests-list
{
data:
project_members_list_data_attributes
(
@project
,
@requesters
)
}
.loading
.spinner.spinner-md
-
else
.card.card-without-border
=
render
'shared/members/tab_pane/header'
do
=
render
'shared/members/tab_pane/title'
do
=
html_escape
(
_
(
'Users requesting access to %{strong_start}%{project_name}%{strong_end}'
))
%
{
project_name:
@project
.
name
,
strong_start:
'<strong>'
.
html_safe
,
strong_end:
'</strong>'
.
html_safe
}
%ul
.content-list.members-list
=
render
partial:
'shared/members/member'
,
collection:
@requesters
,
as: :member
,
locals:
{
membership_source:
@project
,
group:
group
}
changelogs/unreleased/281677_space_in_filename.yml
0 → 100644
View file @
5fe2ffc8
---
title
:
Improve search filter by taking space in file path into account
merge_request
:
52392
author
:
type
:
fixed
config/feature_flags/development/vue_project_members_list.yml
0 → 100644
View file @
5fe2ffc8
---
name
:
vue_project_members_list
introduced_by_url
:
https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52148
rollout_issue_url
:
https://gitlab.com/gitlab-org/gitlab/-/issues/299954
milestone
:
'
13.9'
type
:
development
group
:
group::access
default_enabled
:
false
doc/api/members.md
View file @
5fe2ffc8
...
...
@@ -284,6 +284,7 @@ Example response:
"state"
:
"active"
,
"avatar_url"
:
"https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon"
,
"web_url"
:
"http://192.168.1.8:3000/root"
,
"last_activity_on"
:
"2021-01-27"
},
{
"id"
:
2
,
...
...
@@ -292,7 +293,8 @@ Example response:
"state"
:
"active"
,
"avatar_url"
:
"https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon"
,
"web_url"
:
"http://192.168.1.8:3000/root"
,
"email"
:
"john@example.com"
"email"
:
"john@example.com"
,
"last_activity_on"
:
"2021-01-25"
},
{
"id"
:
3
,
...
...
@@ -300,7 +302,8 @@ Example response:
"name"
:
"Foo bar"
,
"state"
:
"active"
,
"avatar_url"
:
"https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon"
,
"web_url"
:
"http://192.168.1.8:3000/root"
"web_url"
:
"http://192.168.1.8:3000/root"
,
"last_activity_on"
:
"2021-01-20"
}
]
```
...
...
ee/changelogs/unreleased/vij-add-last-activity.yml
0 → 100644
View file @
5fe2ffc8
---
title
:
Add last_activity_on attribute to Billable Members API
merge_request
:
52666
author
:
type
:
changed
ee/lib/ee/api/entities/billable_member.rb
View file @
5fe2ffc8
...
...
@@ -5,6 +5,7 @@ module EE
module
Entities
class
BillableMember
<
::
API
::
Entities
::
UserBasic
expose
:public_email
,
as: :email
expose
:last_activity_on
end
end
end
...
...
ee/spec/features/groups/members/override_ldap_memberships_spec.rb
View file @
5fe2ffc8
...
...
@@ -18,6 +18,7 @@ RSpec.describe 'Groups > Members > Maintainer/Owner can override LDAP access lev
let!
(
:regular_member
)
{
create
(
:group_member
,
:guest
,
group:
group
,
user:
maryjane
,
ldap:
false
)
}
before
do
stub_feature_flags
(
vue_project_members_list:
false
)
# We need to actually activate the LDAP config otherwise `Group#ldap_synced?` will always be false!
allow
(
Gitlab
.
config
.
ldap
).
to
receive_messages
(
enabled:
true
)
...
...
ee/spec/features/projects/audit_events_spec.rb
View file @
5fe2ffc8
...
...
@@ -8,6 +8,8 @@ RSpec.describe 'Projects > Audit Events', :js do
let
(
:project
)
{
create
(
:project
,
:repository
,
namespace:
user
.
namespace
)
}
before
do
stub_feature_flags
(
vue_project_members_list:
false
)
project
.
add_maintainer
(
user
)
sign_in
(
user
)
end
...
...
ee/spec/features/projects/members/invite_group_and_members_spec.rb
View file @
5fe2ffc8
...
...
@@ -10,6 +10,7 @@ RSpec.describe 'Project > Members > Invite group and members', :js do
before
do
stub_feature_flags
(
invite_members_group_modal:
false
)
stub_feature_flags
(
vue_project_members_list:
false
)
end
describe
'Share group lock'
do
...
...
ee/spec/features/projects/members/member_is_removed_from_project_spec.rb
View file @
5fe2ffc8
...
...
@@ -8,6 +8,8 @@ RSpec.describe 'Projects > Members > Member is removed from project' do
let
(
:other_user
)
{
create
(
:user
)
}
before
do
stub_feature_flags
(
vue_project_members_list:
false
)
project
.
add_maintainer
(
user
)
project
.
add_maintainer
(
other_user
)
sign_in
(
user
)
...
...
ee/spec/lib/ee/api/entities/billable_member_spec.rb
View file @
5fe2ffc8
...
...
@@ -3,10 +3,16 @@
require
'spec_helper'
RSpec
.
describe
::
EE
::
API
::
Entities
::
BillableMember
do
let
(
:member
)
{
build
(
:user
,
public_email:
public_email
,
email:
'private@email.com'
)
}
let
(
:last_activity_on
)
{
Date
.
today
}
let
(
:public_email
)
{
nil
}
let
(
:member
)
{
build
(
:user
,
public_email:
public_email
,
email:
'private@email.com'
,
last_activity_on:
last_activity_on
)
}
subject
(
:entity_representation
)
{
described_class
.
new
(
member
).
as_json
}
it
'returns the last_activity_on attribute'
do
expect
(
entity_representation
[
:last_activity_on
]).
to
eq
last_activity_on
end
context
'when the user has a public_email assigned'
do
let
(
:public_email
)
{
'public@email.com'
}
...
...
lib/gitlab/ci/config/entry/job.rb
View file @
5fe2ffc8
...
...
@@ -14,7 +14,7 @@ module Gitlab
ALLOWED_KEYS
=
%i[tags script type image services start_in artifacts
cache dependencies before_script after_script
environment coverage retry parallel interruptible timeout
re
source_group re
lease secrets]
.
freeze
release secrets]
.
freeze
REQUIRED_BY_NEEDS
=
%i[stage]
.
freeze
...
...
@@ -30,7 +30,6 @@ module Gitlab
}
validates
:dependencies
,
array_of_strings:
true
validates
:resource_group
,
type:
String
validates
:allow_failure
,
hash_or_boolean:
true
end
...
...
@@ -124,7 +123,7 @@ module Gitlab
attributes
:script
,
:tags
,
:when
,
:dependencies
,
:needs
,
:retry
,
:parallel
,
:start_in
,
:interruptible
,
:timeout
,
:resource_group
,
:interruptible
,
:timeout
,
:release
,
:allow_failure
def
self
.
matching?
(
name
,
config
)
...
...
@@ -174,7 +173,6 @@ module Gitlab
ignore:
ignored?
,
allow_failure_criteria:
allow_failure_criteria
,
needs:
needs_defined?
?
needs_value
:
nil
,
resource_group:
resource_group
,
scheduling_type:
needs_defined?
?
:dag
:
:stage
).
compact
end
...
...
lib/gitlab/ci/config/entry/processable.rb
View file @
5fe2ffc8
...
...
@@ -15,7 +15,7 @@ module Gitlab
include
::
Gitlab
::
Config
::
Entry
::
Inheritable
PROCESSABLE_ALLOWED_KEYS
=
%i[extends stage only except rules variables
inherit allow_failure when needs]
.
freeze
inherit allow_failure when needs
resource_group
]
.
freeze
included
do
validations
do
...
...
@@ -32,6 +32,7 @@ module Gitlab
with_options
allow_nil:
true
do
validates
:extends
,
array_of_strings_or_string:
true
validates
:rules
,
array_of_hashes:
true
validates
:resource_group
,
type:
String
end
end
...
...
@@ -64,7 +65,7 @@ module Gitlab
inherit:
false
,
default:
{}
attributes
:extends
,
:rules
attributes
:extends
,
:rules
,
:resource_group
end
def
compose!
(
deps
=
nil
)
...
...
@@ -125,7 +126,8 @@ module Gitlab
rules:
rules_value
,
variables:
root_and_job_variables_value
,
only:
only_value
,
except:
except_value
}.
compact
except:
except_value
,
resource_group:
resource_group
}.
compact
end
def
root_and_job_variables_value
...
...
lib/gitlab/ci/pipeline/seed/build/resource_group.rb
View file @
5fe2ffc8
...
...
@@ -8,17 +8,17 @@ module Gitlab
class
ResourceGroup
<
Seed
::
Base
include
Gitlab
::
Utils
::
StrongMemoize
attr_reader
:
build
,
:resource_group_key
attr_reader
:
processable
,
:resource_group_key
def
initialize
(
build
,
resource_group_key
)
@
build
=
build
def
initialize
(
processable
,
resource_group_key
)
@
processable
=
processable
@resource_group_key
=
resource_group_key
end
def
to_resource
return
unless
resource_group_key
.
present?
resource_group
=
build
.
project
.
resource_groups
resource_group
=
processable
.
project
.
resource_groups
.
safe_find_or_create_by
(
key:
expanded_resource_group_key
)
resource_group
if
resource_group
.
persisted?
...
...
@@ -28,7 +28,7 @@ module Gitlab
def
expanded_resource_group_key
strong_memoize
(
:expanded_resource_group_key
)
do
ExpandVariables
.
expand
(
resource_group_key
,
->
{
build
.
simple_variables
})
ExpandVariables
.
expand
(
resource_group_key
,
->
{
processable
.
simple_variables
})
end
end
end
...
...
lib/gitlab/search/query.rb
View file @
5fe2ffc8
...
...
@@ -5,6 +5,9 @@ module Gitlab
class
Query
<
SimpleDelegator
include
EncodingHelper
QUOTES_REGEXP
=
%r{
\A
"|"
\Z
}
.
freeze
TOKEN_WITH_QUOTES_REGEXP
=
%r{
\s
(?=(?:[^"]|"[^"]*")*$)}
.
freeze
def
initialize
(
query
,
filter_opts
=
{},
&
block
)
@raw_query
=
query
.
dup
@filters
=
[]
...
...
@@ -35,22 +38,24 @@ module Gitlab
def
extract_filters
fragments
=
[]
query_tokens
=
parse_raw_query
filters
=
@filters
.
each_with_object
([])
do
|
filter
,
parsed_filters
|
match
=
@raw_query
.
split
.
find
{
|
part
|
part
=~
/\A-?
#{
filter
[
:name
]
}
:/
}
match
=
query_tokens
.
find
{
|
part
|
part
=~
/\A-?
#{
filter
[
:name
]
}
:/
}
next
unless
match
input
=
match
.
split
(
':'
)[
1
..-
1
].
join
next
if
input
.
empty?
filter
[
:negated
]
=
match
.
start_with?
(
"-"
)
filter
[
:value
]
=
parse_filter
(
filter
,
input
)
filter
[
:value
]
=
parse_filter
(
filter
,
input
.
gsub
(
QUOTES_REGEXP
,
''
)
)
filter
[
:regex_value
]
=
Regexp
.
escape
(
filter
[
:value
]).
gsub
(
'\*'
,
'.*?'
)
fragments
<<
match
parsed_filters
<<
filter
end
query
=
(
@raw_query
.
split
-
fragments
).
join
(
' '
)
query
=
(
query_tokens
-
fragments
).
join
(
' '
)
query
=
'*'
if
query
.
empty?
[
query
,
filters
]
...
...
@@ -61,6 +66,13 @@ module Gitlab
@filter_options
[
:encode_binary
]
?
encode_binary
(
result
)
:
result
end
def
parse_raw_query
# Positive lookahead for any non-quote char or even number of quotes
# for example '"search term" path:"foo bar.txt"' would break into
# ["search term", "path:\"foo bar.txt\""]
@raw_query
.
split
(
TOKEN_WITH_QUOTES_REGEXP
).
reject
(
&
:empty?
)
end
end
end
end
locale/gitlab.pot
View file @
5fe2ffc8
...
...
@@ -3281,6 +3281,9 @@ msgstr ""
msgid "An error occurred while loading the file. Please try again later."
msgstr ""
msgid "An error occurred while loading the members, please try again."
msgstr ""
msgid "An error occurred while loading the merge request changes."
msgstr ""
...
...
@@ -18101,6 +18104,9 @@ msgstr ""
msgid "Members|Role updated successfully."
msgstr ""
msgid "Members|Search groups"
msgstr ""
msgid "Members|Search invited"
msgstr ""
...
...
spec/factories/ci/resource.rb
View file @
5fe2ffc8
...
...
@@ -5,7 +5,7 @@ FactoryBot.define do
resource_group
factory: :ci_resource_group
trait
(
:retained
)
do
build
factory: :ci_build
processable
factory: :ci_build
end
end
end
spec/features/admin/admin_projects_spec.rb
View file @
5fe2ffc8
...
...
@@ -10,6 +10,8 @@ RSpec.describe "Admin::Projects" do
let
(
:current_user
)
{
create
(
:admin
)
}
before
do
stub_feature_flags
(
vue_project_members_list:
false
)
sign_in
(
current_user
)
gitlab_enable_admin_mode_sign_in
(
current_user
)
end
...
...
spec/features/projects/members/anonymous_user_sees_members_spec.rb
View file @
5fe2ffc8
...
...
@@ -8,6 +8,8 @@ RSpec.describe 'Projects > Members > Anonymous user sees members' do
let
(
:project
)
{
create
(
:project
,
:public
)
}
before
do
stub_feature_flags
(
vue_project_members_list:
false
)
project
.
add_maintainer
(
user
)
create
(
:project_group_link
,
project:
project
,
group:
group
)
end
...
...
spec/features/projects/members/group_members_spec.rb
View file @
5fe2ffc8
...
...
@@ -13,6 +13,8 @@ RSpec.describe 'Projects members', :js do
let
(
:group_requester
)
{
create
(
:user
)
}
before
do
stub_feature_flags
(
vue_project_members_list:
false
)
project
.
add_developer
(
developer
)
group
.
add_owner
(
user
)
sign_in
(
user
)
...
...
spec/features/projects/members/groups_with_access_list_spec.rb
View file @
5fe2ffc8
...
...
@@ -11,6 +11,8 @@ RSpec.describe 'Projects > Members > Groups with access list', :js do
let!
(
:group_link
)
{
create
(
:project_group_link
,
project:
project
,
group:
group
,
**
additional_link_attrs
)
}
before
do
stub_feature_flags
(
vue_project_members_list:
false
)
travel_to
Time
.
now
.
utc
.
beginning_of_day
project
.
add_maintainer
(
user
)
...
...
spec/features/projects/members/invite_group_spec.rb
View file @
5fe2ffc8
...
...
@@ -10,6 +10,7 @@ RSpec.describe 'Project > Members > Invite group', :js do
before
do
stub_feature_flags
(
invite_members_group_modal:
false
)
stub_feature_flags
(
vue_project_members_list:
false
)
end
describe
'Share with group lock'
do
...
...
spec/features/projects/members/list_spec.rb
View file @
5fe2ffc8
...
...
@@ -13,10 +13,18 @@ RSpec.describe 'Project members list' do
before
do
stub_feature_flags
(
invite_members_group_modal:
false
)
stub_feature_flags
(
vue_project_members_list:
false
)
sign_in
(
user1
)
group
.
add_owner
(
user1
)
end
it
'pushes `vue_project_members_list` feature flag to the frontend'
do
visit_members_page
expect
(
page
).
to
have_pushed_frontend_feature_flags
(
vueProjectMembersList:
false
)
end
it
'show members from project and group'
do
project
.
add_developer
(
user2
)
...
...
spec/features/projects/members/master_adds_member_with_expiration_date_spec.rb
View file @
5fe2ffc8
...
...
@@ -11,6 +11,8 @@ RSpec.describe 'Projects > Members > Maintainer adds member with expiration date
let
(
:new_member
)
{
create
(
:user
)
}
before
do
stub_feature_flags
(
vue_project_members_list:
false
)
travel_to
Time
.
now
.
utc
.
beginning_of_day
project
.
add_maintainer
(
maintainer
)
...
...
spec/features/projects/members/sorting_spec.rb
View file @
5fe2ffc8
...
...
@@ -8,6 +8,8 @@ RSpec.describe 'Projects > Members > Sorting' do
let
(
:project
)
{
create
(
:project
,
namespace:
maintainer
.
namespace
,
creator:
maintainer
)
}
before
do
stub_feature_flags
(
vue_project_members_list:
false
)
create
(
:project_member
,
:developer
,
user:
developer
,
project:
project
,
created_at:
3
.
days
.
ago
)
sign_in
(
maintainer
)
...
...
spec/features/projects/members/tabs_spec.rb
View file @
5fe2ffc8
...
...
@@ -20,6 +20,7 @@ RSpec.describe 'Projects > Members > Tabs' do
end
before
do
stub_feature_flags
(
vue_project_members_list:
false
)
allow
(
Kaminari
.
config
).
to
receive
(
:default_per_page
).
and_return
(
1
)
sign_in
(
user
)
...
...
spec/features/projects/settings/user_manages_project_members_spec.rb
View file @
5fe2ffc8
...
...
@@ -11,6 +11,8 @@ RSpec.describe 'Projects > Settings > User manages project members' do
let
(
:user_mike
)
{
create
(
:user
,
name:
'Mike'
)
}
before
do
stub_feature_flags
(
vue_project_members_list:
false
)
project
.
add_maintainer
(
user
)
project
.
add_developer
(
user_dmitriy
)
sign_in
(
user
)
...
...
spec/frontend/projects/members/utils_spec.js
0 → 100644
View file @
5fe2ffc8
import
{
projectMemberRequestFormatter
}
from
'
~/projects/members/utils
'
;
describe
(
'
project member utils
'
,
()
=>
{
describe
(
'
projectMemberRequestFormatter
'
,
()
=>
{
it
(
'
returns expected format
'
,
()
=>
{
expect
(
projectMemberRequestFormatter
({
accessLevel
:
50
,
expires_at
:
'
2020-10-16
'
,
}),
).
toEqual
({
project_member
:
{
access_level
:
50
,
expires_at
:
'
2020-10-16
'
}
});
});
});
});
spec/lib/gitlab/ci/config/entry/processable_spec.rb
View file @
5fe2ffc8
...
...
@@ -73,6 +73,15 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
end
end
context
'when resource_group key is not a string'
do
let
(
:config
)
{
{
resource_group:
123
}
}
it
'returns error about wrong value type'
do
expect
(
entry
).
not_to
be_valid
expect
(
entry
.
errors
).
to
include
"job resource group should be a string"
end
end
context
'when it uses both "when:" and "rules:"'
do
let
(
:config
)
do
{
...
...
@@ -340,6 +349,26 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
end
end
context
'with resource group'
do
using
RSpec
::
Parameterized
::
TableSyntax
where
(
:resource_group
,
:result
)
do
'iOS'
|
'iOS'
'review/$CI_COMMIT_REF_NAME'
|
'review/$CI_COMMIT_REF_NAME'
nil
|
nil
end
with_them
do
let
(
:config
)
{
{
script:
'ls'
,
resource_group:
resource_group
}.
compact
}
it
do
entry
.
compose!
(
deps
)
expect
(
entry
.
resource_group
).
to
eq
(
result
)
end
end
end
context
'with inheritance'
do
context
'of variables'
do
let
(
:config
)
do
...
...
spec/lib/gitlab/file_finder_spec.rb
View file @
5fe2ffc8
...
...
@@ -53,6 +53,14 @@ RSpec.describe Gitlab::FileFinder do
end
end
context
'with white space in the path'
do
it
'filters by path correctly'
do
results
=
subject
.
find
(
'directory path:"with space/README.md"'
)
expect
(
results
.
count
).
to
eq
(
1
)
end
end
it
'does not cause N+1 query'
do
expect
(
Gitlab
::
GitalyClient
).
to
receive
(
:call
).
at_most
(
10
).
times
.
and_call_original
...
...
spec/lib/gitlab/repository_cache_adapter_spec.rb
View file @
5fe2ffc8
...
...
@@ -292,12 +292,11 @@ RSpec.describe Gitlab::RepositoryCacheAdapter do
describe
'#expire_method_caches'
do
it
'expires the caches of the given methods'
do
expect
(
cache
).
to
receive
(
:expire
).
with
(
:rendered_readme
)
expect
(
cache
).
to
receive
(
:expire
).
with
(
:branch_names
)
expect
(
redis_set_cache
).
to
receive
(
:expire
).
with
(
:
rendered_readme
,
:
branch_names
)
expect
(
redis_hash_cache
).
to
receive
(
:delete
).
with
(
:
rendered_readme
,
:
branch_names
)
expect
(
redis_set_cache
).
to
receive
(
:expire
).
with
(
:branch_names
)
expect
(
redis_hash_cache
).
to
receive
(
:delete
).
with
(
:branch_names
)
repository
.
expire_method_caches
(
%i(
rendered_readme
branch_names)
)
repository
.
expire_method_caches
(
%i(branch_names)
)
end
it
'does not expire caches for non-existent methods'
do
...
...
spec/lib/gitlab/search/query_spec.rb
View file @
5fe2ffc8
...
...
@@ -46,4 +46,22 @@ RSpec.describe Gitlab::Search::Query do
expect
(
subject
.
filters
).
to
all
(
include
(
negated:
true
))
end
end
context
'with filter value in quotes'
do
let
(
:query
)
{
'"foo bar" name:"my test script.txt"'
}
it
'does not break the filter value in quotes'
do
expect
(
subject
.
term
).
to
eq
(
'"foo bar"'
)
expect
(
subject
.
filters
[
0
]).
to
include
(
name: :name
,
negated:
false
,
value:
"MY TEST SCRIPT.TXT"
)
end
end
context
'with extra white spaces between the query words'
do
let
(
:query
)
{
' foo = bar name:"my test.txt"'
}
it
'removes the extra whitespace between tokens'
do
expect
(
subject
.
term
).
to
eq
(
'foo = bar'
)
expect
(
subject
.
filters
[
0
]).
to
include
(
name: :name
,
negated:
false
,
value:
"MY TEST.TXT"
)
end
end
end
spec/models/ci/build_spec.rb
View file @
5fe2ffc8
...
...
@@ -1185,60 +1185,6 @@ RSpec.describe Ci::Build do
end
end
describe
'state transition with resource group'
do
let
(
:resource_group
)
{
create
(
:ci_resource_group
,
project:
project
)
}
context
'when build status is created'
do
let
(
:build
)
{
create
(
:ci_build
,
:created
,
project:
project
,
resource_group:
resource_group
)
}
it
'is waiting for resource when build is enqueued'
do
expect
(
Ci
::
ResourceGroups
::
AssignResourceFromResourceGroupWorker
).
to
receive
(
:perform_async
).
with
(
resource_group
.
id
)
expect
{
build
.
enqueue!
}.
to
change
{
build
.
status
}.
from
(
'created'
).
to
(
'waiting_for_resource'
)
expect
(
build
.
waiting_for_resource_at
).
not_to
be_nil
end
context
'when build is waiting for resource'
do
before
do
build
.
update_column
(
:status
,
'waiting_for_resource'
)
end
it
'is enqueued when build requests resource'
do
expect
{
build
.
enqueue_waiting_for_resource!
}.
to
change
{
build
.
status
}.
from
(
'waiting_for_resource'
).
to
(
'pending'
)
end
it
'releases a resource when build finished'
do
expect
(
build
.
resource_group
).
to
receive
(
:release_resource_from
).
with
(
build
).
and_call_original
expect
(
Ci
::
ResourceGroups
::
AssignResourceFromResourceGroupWorker
).
to
receive
(
:perform_async
).
with
(
build
.
resource_group_id
)
build
.
enqueue_waiting_for_resource!
build
.
success!
end
context
'when build has prerequisites'
do
before
do
allow
(
build
).
to
receive
(
:any_unmet_prerequisites?
)
{
true
}
end
it
'is preparing when build is enqueued'
do
expect
{
build
.
enqueue_waiting_for_resource!
}.
to
change
{
build
.
status
}.
from
(
'waiting_for_resource'
).
to
(
'preparing'
)
end
end
context
'when there are no available resources'
do
before
do
resource_group
.
assign_resource_to
(
create
(
:ci_build
))
end
it
'stays as waiting for resource when build requests resource'
do
expect
{
build
.
enqueue_waiting_for_resource
}.
not_to
change
{
build
.
status
}
end
end
end
end
end
describe
'#on_stop'
do
subject
{
build
.
on_stop
}
...
...
spec/models/ci/pipeline_spec.rb
View file @
5fe2ffc8
...
...
@@ -2321,7 +2321,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context
'on waiting for resource'
do
before
do
allow
(
build
).
to
receive
(
:
requires_resource
?
)
{
true
}
allow
(
build
).
to
receive
(
:
with_resource_group
?
)
{
true
}
allow
(
Ci
::
ResourceGroups
::
AssignResourceFromResourceGroupWorker
).
to
receive
(
:perform_async
)
build
.
enqueue
...
...
spec/models/ci/processable_spec.rb
View file @
5fe2ffc8
...
...
@@ -122,4 +122,58 @@ RSpec.describe Ci::Processable do
it
{
is_expected
.
to
be_empty
}
end
end
describe
'state transition with resource group'
do
let
(
:resource_group
)
{
create
(
:ci_resource_group
,
project:
project
)
}
context
'when build status is created'
do
let
(
:build
)
{
create
(
:ci_build
,
:created
,
project:
project
,
resource_group:
resource_group
)
}
it
'is waiting for resource when build is enqueued'
do
expect
(
Ci
::
ResourceGroups
::
AssignResourceFromResourceGroupWorker
).
to
receive
(
:perform_async
).
with
(
resource_group
.
id
)
expect
{
build
.
enqueue!
}.
to
change
{
build
.
status
}.
from
(
'created'
).
to
(
'waiting_for_resource'
)
expect
(
build
.
waiting_for_resource_at
).
not_to
be_nil
end
context
'when build is waiting for resource'
do
before
do
build
.
update_column
(
:status
,
'waiting_for_resource'
)
end
it
'is enqueued when build requests resource'
do
expect
{
build
.
enqueue_waiting_for_resource!
}.
to
change
{
build
.
status
}.
from
(
'waiting_for_resource'
).
to
(
'pending'
)
end
it
'releases a resource when build finished'
do
expect
(
build
.
resource_group
).
to
receive
(
:release_resource_from
).
with
(
build
).
and_call_original
expect
(
Ci
::
ResourceGroups
::
AssignResourceFromResourceGroupWorker
).
to
receive
(
:perform_async
).
with
(
build
.
resource_group_id
)
build
.
enqueue_waiting_for_resource!
build
.
success!
end
context
'when build has prerequisites'
do
before
do
allow
(
build
).
to
receive
(
:any_unmet_prerequisites?
)
{
true
}
end
it
'is preparing when build is enqueued'
do
expect
{
build
.
enqueue_waiting_for_resource!
}.
to
change
{
build
.
status
}.
from
(
'waiting_for_resource'
).
to
(
'preparing'
)
end
end
context
'when there are no available resources'
do
before
do
resource_group
.
assign_resource_to
(
create
(
:ci_build
))
end
it
'stays as waiting for resource when build requests resource'
do
expect
{
build
.
enqueue_waiting_for_resource
}.
not_to
change
{
build
.
status
}
end
end
end
end
end
end
spec/models/ci/resource_group_spec.rb
View file @
5fe2ffc8
...
...
@@ -32,12 +32,12 @@ RSpec.describe Ci::ResourceGroup do
let
(
:build
)
{
create
(
:ci_build
)
}
let
(
:resource_group
)
{
create
(
:ci_resource_group
)
}
it
'retains resource for the
build
'
do
expect
(
resource_group
.
resources
.
first
.
build
).
to
be_nil
it
'retains resource for the
processable
'
do
expect
(
resource_group
.
resources
.
first
.
processable
).
to
be_nil
is_expected
.
to
eq
(
true
)
expect
(
resource_group
.
resources
.
first
.
build
).
to
eq
(
build
)
expect
(
resource_group
.
resources
.
first
.
processable
).
to
eq
(
build
)
end
context
'when there are no free resources'
do
...
...
@@ -51,7 +51,7 @@ RSpec.describe Ci::ResourceGroup do
end
context
'when the build has already retained a resource'
do
let!
(
:another_resource
)
{
create
(
:ci_resource
,
resource_group:
resource_group
,
build
:
build
)
}
let!
(
:another_resource
)
{
create
(
:ci_resource
,
resource_group:
resource_group
,
processable
:
build
)
}
it
'fails to retain resource'
do
expect
{
subject
}.
to
raise_error
(
ActiveRecord
::
RecordNotUnique
)
...
...
@@ -71,11 +71,11 @@ RSpec.describe Ci::ResourceGroup do
end
it
'releases resource from the build'
do
expect
(
resource_group
.
resources
.
first
.
build
).
to
eq
(
build
)
expect
(
resource_group
.
resources
.
first
.
processable
).
to
eq
(
build
)
is_expected
.
to
eq
(
true
)
expect
(
resource_group
.
resources
.
first
.
build
).
to
be_nil
expect
(
resource_group
.
resources
.
first
.
processable
).
to
be_nil
end
end
...
...
spec/models/ci/resource_spec.rb
View file @
5fe2ffc8
...
...
@@ -19,7 +19,7 @@ RSpec.describe Ci::Resource do
subject
{
described_class
.
retained_by
(
build
)
}
let
(
:build
)
{
create
(
:ci_build
)
}
let!
(
:resource
)
{
create
(
:ci_resource
,
build
:
build
)
}
let!
(
:resource
)
{
create
(
:ci_resource
,
processable
:
build
)
}
it
'returns retained resources'
do
is_expected
.
to
eq
([
resource
])
...
...
spec/models/commit_status_spec.rb
View file @
5fe2ffc8
...
...
@@ -725,22 +725,6 @@ RSpec.describe CommitStatus do
let
(
:commit_status
)
{
create
(
:commit_status
)
}
it
{
is_expected
.
to
eq
(
true
)
}
context
'when build requires a resource'
do
before
do
allow
(
commit_status
).
to
receive
(
:requires_resource?
)
{
true
}
end
it
{
is_expected
.
to
eq
(
false
)
}
end
context
'when build has a prerequisite'
do
before
do
allow
(
commit_status
).
to
receive
(
:any_unmet_prerequisites?
)
{
true
}
end
it
{
is_expected
.
to
eq
(
false
)
}
end
end
describe
'#enqueue'
do
...
...
@@ -748,7 +732,6 @@ RSpec.describe CommitStatus do
before
do
allow
(
Time
).
to
receive
(
:now
).
and_return
(
current_time
)
expect
(
commit_status
.
any_unmet_prerequisites?
).
to
eq
false
end
shared_examples
'commit status enqueued'
do
...
...
spec/models/readme_blob_spec.rb
deleted
100644 → 0
View file @
a0f57c39
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
ReadmeBlob
do
include
FakeBlobHelpers
describe
'policy'
do
let
(
:project
)
{
build
(
:project
,
:repository
)
}
subject
{
described_class
.
new
(
fake_blob
(
path:
'README.md'
),
project
.
repository
)
}
it
'works with policy'
do
expect
(
Ability
.
allowed?
(
project
.
creator
,
:read_blob
,
subject
)).
to
be_truthy
end
end
end
spec/models/repository_spec.rb
View file @
5fe2ffc8
...
...
@@ -483,12 +483,6 @@ RSpec.describe Repository do
it
{
is_expected
.
to
be_an_instance_of
(
::
Blob
)
}
end
context
'readme blob on HEAD'
do
subject
{
repository
.
blob_at
(
repository
.
head_commit
.
sha
,
'README.md'
)
}
it
{
is_expected
.
to
be_an_instance_of
(
::
ReadmeBlob
)
}
end
context
'readme blob not on HEAD'
do
subject
{
repository
.
blob_at
(
repository
.
find_branch
(
'feature'
).
target
,
'README.md'
)
}
...
...
@@ -1938,7 +1932,6 @@ RSpec.describe Repository do
expect
(
repository
).
to
receive
(
:expire_method_caches
).
with
([
:size
,
:commit_count
,
:rendered_readme
,
:readme_path
,
:contribution_guide
,
:changelog
,
...
...
@@ -2314,14 +2307,6 @@ RSpec.describe Repository do
expect
(
repository
.
readme
).
to
be_nil
end
end
context
'when a README exists'
do
let
(
:project
)
{
create
(
:project
,
:repository
)
}
it
'returns the README'
do
expect
(
repository
.
readme
).
to
be_an_instance_of
(
ReadmeBlob
)
end
end
end
end
...
...
@@ -2527,9 +2512,8 @@ RSpec.describe Repository do
describe
'#refresh_method_caches'
do
it
'refreshes the caches of the given types'
do
expect
(
repository
).
to
receive
(
:expire_method_caches
)
.
with
(
%i(re
ndered_readme re
adme_path license_blob license_key license)
)
.
with
(
%i(readme_path license_blob license_key license)
)
expect
(
repository
).
to
receive
(
:rendered_readme
)
expect
(
repository
).
to
receive
(
:readme_path
)
expect
(
repository
).
to
receive
(
:license_blob
)
expect
(
repository
).
to
receive
(
:license_key
)
...
...
spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb
View file @
5fe2ffc8
...
...
@@ -76,6 +76,31 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
}
end
end
context
'with resource group'
do
let
(
:config
)
do
<<~
YAML
instrumentation_test:
stage: test
resource_group: iOS
trigger:
include:
- local: path/to/child.yml
YAML
end
# TODO: This test will be properly implemented in the next MR
# for https://gitlab.com/gitlab-org/gitlab/-/issues/39057.
it
'creates bridge job but still resource group is no-op'
,
:aggregate_failures
do
pipeline
=
create_pipeline!
test
=
pipeline
.
statuses
.
find_by
(
name:
'instrumentation_test'
)
expect
(
pipeline
).
to
be_persisted
expect
(
test
).
to
be_a
Ci
::
Bridge
expect
(
project
.
resource_groups
.
count
).
to
eq
(
0
)
end
end
end
describe
'child pipeline triggers'
do
...
...
spec/services/ci/create_pipeline_service_spec.rb
View file @
5fe2ffc8
...
...
@@ -952,9 +952,9 @@ RSpec.describe Ci::CreatePipelineService do
expect
(
result
).
to
be_persisted
expect
(
deploy_job
.
resource_group
.
key
).
to
eq
(
resource_group_key
)
expect
(
project
.
resource_groups
.
count
).
to
eq
(
1
)
expect
(
resource_group
.
build
s
.
count
).
to
eq
(
1
)
expect
(
resource_group
.
processable
s
.
count
).
to
eq
(
1
)
expect
(
resource_group
.
resources
.
count
).
to
eq
(
1
)
expect
(
resource_group
.
resources
.
first
.
build
).
to
eq
(
nil
)
expect
(
resource_group
.
resources
.
first
.
processable
).
to
eq
(
nil
)
end
context
'when resource group key includes predefined variables'
do
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment